eactionpack 2.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (338) hide show
  1. data/CHANGELOG +7 -0
  2. data/MIT-LICENSE +21 -0
  3. data/README +469 -0
  4. data/RUNNING_UNIT_TESTS +24 -0
  5. data/Rakefile +146 -0
  6. data/install.rb +30 -0
  7. data/lib/action_controller.rb +79 -0
  8. data/lib/action_controller/assertions.rb +69 -0
  9. data/lib/action_controller/assertions/dom_assertions.rb +39 -0
  10. data/lib/action_controller/assertions/model_assertions.rb +20 -0
  11. data/lib/action_controller/assertions/response_assertions.rb +172 -0
  12. data/lib/action_controller/assertions/routing_assertions.rb +146 -0
  13. data/lib/action_controller/assertions/selector_assertions.rb +491 -0
  14. data/lib/action_controller/assertions/tag_assertions.rb +130 -0
  15. data/lib/action_controller/base.rb +1288 -0
  16. data/lib/action_controller/benchmarking.rb +94 -0
  17. data/lib/action_controller/caching.rb +72 -0
  18. data/lib/action_controller/caching/actions.rb +144 -0
  19. data/lib/action_controller/caching/fragments.rb +138 -0
  20. data/lib/action_controller/caching/pages.rb +154 -0
  21. data/lib/action_controller/caching/sql_cache.rb +18 -0
  22. data/lib/action_controller/caching/sweeping.rb +97 -0
  23. data/lib/action_controller/cgi_ext.rb +16 -0
  24. data/lib/action_controller/cgi_ext/cookie.rb +110 -0
  25. data/lib/action_controller/cgi_ext/query_extension.rb +22 -0
  26. data/lib/action_controller/cgi_ext/session.rb +73 -0
  27. data/lib/action_controller/cgi_ext/stdinput.rb +24 -0
  28. data/lib/action_controller/cgi_process.rb +223 -0
  29. data/lib/action_controller/components.rb +166 -0
  30. data/lib/action_controller/cookies.rb +96 -0
  31. data/lib/action_controller/dispatcher.rb +162 -0
  32. data/lib/action_controller/filters.rb +642 -0
  33. data/lib/action_controller/flash.rb +172 -0
  34. data/lib/action_controller/headers.rb +31 -0
  35. data/lib/action_controller/helpers.rb +221 -0
  36. data/lib/action_controller/http_authentication.rb +124 -0
  37. data/lib/action_controller/integration.rb +634 -0
  38. data/lib/action_controller/layout.rb +309 -0
  39. data/lib/action_controller/mime_responds.rb +173 -0
  40. data/lib/action_controller/mime_type.rb +186 -0
  41. data/lib/action_controller/mime_types.rb +20 -0
  42. data/lib/action_controller/polymorphic_routes.rb +191 -0
  43. data/lib/action_controller/record_identifier.rb +102 -0
  44. data/lib/action_controller/request.rb +764 -0
  45. data/lib/action_controller/request_forgery_protection.rb +140 -0
  46. data/lib/action_controller/request_profiler.rb +169 -0
  47. data/lib/action_controller/rescue.rb +258 -0
  48. data/lib/action_controller/resources.rb +572 -0
  49. data/lib/action_controller/response.rb +76 -0
  50. data/lib/action_controller/routing.rb +387 -0
  51. data/lib/action_controller/routing/builder.rb +203 -0
  52. data/lib/action_controller/routing/optimisations.rb +120 -0
  53. data/lib/action_controller/routing/recognition_optimisation.rb +162 -0
  54. data/lib/action_controller/routing/route.rb +240 -0
  55. data/lib/action_controller/routing/route_set.rb +436 -0
  56. data/lib/action_controller/routing/routing_ext.rb +46 -0
  57. data/lib/action_controller/routing/segments.rb +283 -0
  58. data/lib/action_controller/session/active_record_store.rb +340 -0
  59. data/lib/action_controller/session/cookie_store.rb +166 -0
  60. data/lib/action_controller/session/drb_server.rb +32 -0
  61. data/lib/action_controller/session/drb_store.rb +35 -0
  62. data/lib/action_controller/session/mem_cache_store.rb +98 -0
  63. data/lib/action_controller/session_management.rb +158 -0
  64. data/lib/action_controller/status_codes.rb +88 -0
  65. data/lib/action_controller/streaming.rb +155 -0
  66. data/lib/action_controller/templates/rescues/_request_and_response.erb +24 -0
  67. data/lib/action_controller/templates/rescues/_trace.erb +26 -0
  68. data/lib/action_controller/templates/rescues/diagnostics.erb +11 -0
  69. data/lib/action_controller/templates/rescues/layout.erb +29 -0
  70. data/lib/action_controller/templates/rescues/missing_template.erb +2 -0
  71. data/lib/action_controller/templates/rescues/routing_error.erb +10 -0
  72. data/lib/action_controller/templates/rescues/template_error.erb +21 -0
  73. data/lib/action_controller/templates/rescues/unknown_action.erb +2 -0
  74. data/lib/action_controller/test_case.rb +83 -0
  75. data/lib/action_controller/test_process.rb +526 -0
  76. data/lib/action_controller/url_rewriter.rb +142 -0
  77. data/lib/action_controller/vendor/html-scanner/html/document.rb +68 -0
  78. data/lib/action_controller/vendor/html-scanner/html/node.rb +537 -0
  79. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +173 -0
  80. data/lib/action_controller/vendor/html-scanner/html/selector.rb +828 -0
  81. data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +105 -0
  82. data/lib/action_controller/vendor/html-scanner/html/version.rb +11 -0
  83. data/lib/action_controller/verification.rb +130 -0
  84. data/lib/action_pack.rb +24 -0
  85. data/lib/action_pack/version.rb +9 -0
  86. data/lib/action_view.rb +44 -0
  87. data/lib/action_view/base.rb +335 -0
  88. data/lib/action_view/helpers/active_record_helper.rb +276 -0
  89. data/lib/action_view/helpers/asset_tag_helper.rb +599 -0
  90. data/lib/action_view/helpers/atom_feed_helper.rb +143 -0
  91. data/lib/action_view/helpers/benchmark_helper.rb +33 -0
  92. data/lib/action_view/helpers/cache_helper.rb +40 -0
  93. data/lib/action_view/helpers/capture_helper.rb +161 -0
  94. data/lib/action_view/helpers/date_helper.rb +711 -0
  95. data/lib/action_view/helpers/debug_helper.rb +31 -0
  96. data/lib/action_view/helpers/form_helper.rb +767 -0
  97. data/lib/action_view/helpers/form_options_helper.rb +458 -0
  98. data/lib/action_view/helpers/form_tag_helper.rb +458 -0
  99. data/lib/action_view/helpers/javascript_helper.rb +148 -0
  100. data/lib/action_view/helpers/number_helper.rb +186 -0
  101. data/lib/action_view/helpers/record_identification_helper.rb +20 -0
  102. data/lib/action_view/helpers/record_tag_helper.rb +59 -0
  103. data/lib/action_view/helpers/sanitize_helper.rb +229 -0
  104. data/lib/action_view/helpers/tag_helper.rb +134 -0
  105. data/lib/action_view/helpers/text_helper.rb +507 -0
  106. data/lib/action_view/helpers/url_helper.rb +573 -0
  107. data/lib/action_view/inline_template.rb +20 -0
  108. data/lib/action_view/partial_template.rb +70 -0
  109. data/lib/action_view/partials.rb +158 -0
  110. data/lib/action_view/template.rb +125 -0
  111. data/lib/action_view/template_error.rb +110 -0
  112. data/lib/action_view/template_finder.rb +176 -0
  113. data/lib/action_view/template_handler.rb +34 -0
  114. data/lib/action_view/template_handlers/builder.rb +27 -0
  115. data/lib/action_view/template_handlers/compilable.rb +128 -0
  116. data/lib/action_view/template_handlers/erb.rb +56 -0
  117. data/lib/action_view/test_case.rb +58 -0
  118. data/lib/actionpack.rb +1 -0
  119. data/test/abstract_unit.rb +36 -0
  120. data/test/active_record_unit.rb +105 -0
  121. data/test/activerecord/active_record_store_test.rb +141 -0
  122. data/test/activerecord/render_partial_with_record_identification_test.rb +191 -0
  123. data/test/adv_attr_test.rb +20 -0
  124. data/test/controller/action_pack_assertions_test.rb +543 -0
  125. data/test/controller/addresses_render_test.rb +43 -0
  126. data/test/controller/assert_select_test.rb +331 -0
  127. data/test/controller/base_test.rb +219 -0
  128. data/test/controller/benchmark_test.rb +32 -0
  129. data/test/controller/caching_test.rb +581 -0
  130. data/test/controller/capture_test.rb +89 -0
  131. data/test/controller/cgi_test.rb +116 -0
  132. data/test/controller/components_test.rb +140 -0
  133. data/test/controller/content_type_test.rb +139 -0
  134. data/test/controller/controller_fixtures/app/controllers/admin/user_controller.rb +0 -0
  135. data/test/controller/controller_fixtures/app/controllers/user_controller.rb +0 -0
  136. data/test/controller/controller_fixtures/vendor/plugins/bad_plugin/lib/plugin_controller.rb +0 -0
  137. data/test/controller/cookie_test.rb +146 -0
  138. data/test/controller/custom_handler_test.rb +45 -0
  139. data/test/controller/deprecation/deprecated_base_methods_test.rb +37 -0
  140. data/test/controller/dispatcher_test.rb +105 -0
  141. data/test/controller/fake_controllers.rb +33 -0
  142. data/test/controller/fake_models.rb +11 -0
  143. data/test/controller/filter_params_test.rb +49 -0
  144. data/test/controller/filters_test.rb +881 -0
  145. data/test/controller/flash_test.rb +146 -0
  146. data/test/controller/header_test.rb +14 -0
  147. data/test/controller/helper_test.rb +210 -0
  148. data/test/controller/html-scanner/cdata_node_test.rb +15 -0
  149. data/test/controller/html-scanner/document_test.rb +148 -0
  150. data/test/controller/html-scanner/node_test.rb +89 -0
  151. data/test/controller/html-scanner/sanitizer_test.rb +269 -0
  152. data/test/controller/html-scanner/tag_node_test.rb +238 -0
  153. data/test/controller/html-scanner/text_node_test.rb +50 -0
  154. data/test/controller/html-scanner/tokenizer_test.rb +131 -0
  155. data/test/controller/http_authentication_test.rb +54 -0
  156. data/test/controller/integration_test.rb +252 -0
  157. data/test/controller/integration_upload_test.rb +43 -0
  158. data/test/controller/layout_test.rb +255 -0
  159. data/test/controller/mime_responds_test.rb +514 -0
  160. data/test/controller/mime_type_test.rb +84 -0
  161. data/test/controller/new_render_test.rb +843 -0
  162. data/test/controller/polymorphic_routes_test.rb +174 -0
  163. data/test/controller/record_identifier_test.rb +139 -0
  164. data/test/controller/redirect_test.rb +289 -0
  165. data/test/controller/render_test.rb +484 -0
  166. data/test/controller/request_forgery_protection_test.rb +305 -0
  167. data/test/controller/request_test.rb +928 -0
  168. data/test/controller/rescue_test.rb +517 -0
  169. data/test/controller/resources_test.rb +873 -0
  170. data/test/controller/routing_test.rb +2464 -0
  171. data/test/controller/selector_test.rb +628 -0
  172. data/test/controller/send_file_test.rb +138 -0
  173. data/test/controller/session/cookie_store_test.rb +258 -0
  174. data/test/controller/session/mem_cache_store_test.rb +181 -0
  175. data/test/controller/session_fixation_test.rb +89 -0
  176. data/test/controller/session_management_test.rb +178 -0
  177. data/test/controller/test_test.rb +695 -0
  178. data/test/controller/url_rewriter_test.rb +310 -0
  179. data/test/controller/verification_test.rb +270 -0
  180. data/test/controller/view_paths_test.rb +140 -0
  181. data/test/controller/webservice_test.rb +229 -0
  182. data/test/fixtures/addresses/list.erb +1 -0
  183. data/test/fixtures/bad_customers/_bad_customer.html.erb +1 -0
  184. data/test/fixtures/companies.yml +24 -0
  185. data/test/fixtures/company.rb +10 -0
  186. data/test/fixtures/content_type/render_default_content_types_for_respond_to.rhtml +1 -0
  187. data/test/fixtures/content_type/render_default_for_js.js.erb +1 -0
  188. data/test/fixtures/content_type/render_default_for_rhtml.rhtml +1 -0
  189. data/test/fixtures/content_type/render_default_for_rxml.rxml +1 -0
  190. data/test/fixtures/customers/_customer.html.erb +1 -0
  191. data/test/fixtures/db_definitions/sqlite.sql +49 -0
  192. data/test/fixtures/developer.rb +9 -0
  193. data/test/fixtures/developers.yml +21 -0
  194. data/test/fixtures/developers_projects.yml +13 -0
  195. data/test/fixtures/fun/games/hello_world.erb +1 -0
  196. data/test/fixtures/functional_caching/_partial.erb +3 -0
  197. data/test/fixtures/functional_caching/fragment_cached.html.erb +2 -0
  198. data/test/fixtures/functional_caching/html_fragment_cached_with_partial.html.erb +1 -0
  199. data/test/fixtures/functional_caching/js_fragment_cached_with_partial.js.rjs +1 -0
  200. data/test/fixtures/good_customers/_good_customer.html.erb +1 -0
  201. data/test/fixtures/helpers/abc_helper.rb +5 -0
  202. data/test/fixtures/helpers/fun/games_helper.rb +3 -0
  203. data/test/fixtures/helpers/fun/pdf_helper.rb +3 -0
  204. data/test/fixtures/layout_tests/alt/hello.rhtml +1 -0
  205. data/test/fixtures/layout_tests/layouts/controller_name_space/nested.rhtml +1 -0
  206. data/test/fixtures/layout_tests/layouts/item.rhtml +1 -0
  207. data/test/fixtures/layout_tests/layouts/layout_test.rhtml +1 -0
  208. data/test/fixtures/layout_tests/layouts/multiple_extensions.html.erb +1 -0
  209. data/test/fixtures/layout_tests/layouts/third_party_template_library.mab +1 -0
  210. data/test/fixtures/layout_tests/views/hello.rhtml +1 -0
  211. data/test/fixtures/layouts/block_with_layout.erb +3 -0
  212. data/test/fixtures/layouts/builder.builder +3 -0
  213. data/test/fixtures/layouts/partial_with_layout.erb +3 -0
  214. data/test/fixtures/layouts/standard.erb +1 -0
  215. data/test/fixtures/layouts/talk_from_action.erb +2 -0
  216. data/test/fixtures/layouts/yield.erb +2 -0
  217. data/test/fixtures/mascot.rb +3 -0
  218. data/test/fixtures/mascots.yml +4 -0
  219. data/test/fixtures/mascots/_mascot.html.erb +1 -0
  220. data/test/fixtures/multipart/binary_file +0 -0
  221. data/test/fixtures/multipart/boundary_problem_file +10 -0
  222. data/test/fixtures/multipart/bracketed_param +5 -0
  223. data/test/fixtures/multipart/large_text_file +10 -0
  224. data/test/fixtures/multipart/mixed_files +0 -0
  225. data/test/fixtures/multipart/mona_lisa.jpg +0 -0
  226. data/test/fixtures/multipart/single_parameter +5 -0
  227. data/test/fixtures/multipart/text_file +10 -0
  228. data/test/fixtures/override/test/hello_world.erb +1 -0
  229. data/test/fixtures/override2/layouts/test/sub.erb +1 -0
  230. data/test/fixtures/post_test/layouts/post.html.erb +1 -0
  231. data/test/fixtures/post_test/layouts/super_post.iphone.erb +1 -0
  232. data/test/fixtures/post_test/post/index.html.erb +1 -0
  233. data/test/fixtures/post_test/post/index.iphone.erb +1 -0
  234. data/test/fixtures/post_test/super_post/index.html.erb +1 -0
  235. data/test/fixtures/post_test/super_post/index.iphone.erb +1 -0
  236. data/test/fixtures/project.rb +3 -0
  237. data/test/fixtures/projects.yml +7 -0
  238. data/test/fixtures/public/404.html +1 -0
  239. data/test/fixtures/public/500.html +1 -0
  240. data/test/fixtures/public/images/rails.png +0 -0
  241. data/test/fixtures/public/javascripts/application.js +1 -0
  242. data/test/fixtures/public/javascripts/bank.js +1 -0
  243. data/test/fixtures/public/javascripts/robber.js +1 -0
  244. data/test/fixtures/public/javascripts/version.1.0.js +1 -0
  245. data/test/fixtures/public/stylesheets/bank.css +1 -0
  246. data/test/fixtures/public/stylesheets/robber.css +1 -0
  247. data/test/fixtures/public/stylesheets/version.1.0.css +1 -0
  248. data/test/fixtures/replies.yml +15 -0
  249. data/test/fixtures/reply.rb +7 -0
  250. data/test/fixtures/respond_to/all_types_with_layout.html.erb +1 -0
  251. data/test/fixtures/respond_to/custom_constant_handling_without_block.mobile.erb +1 -0
  252. data/test/fixtures/respond_to/iphone_with_html_response_type.html.erb +1 -0
  253. data/test/fixtures/respond_to/iphone_with_html_response_type.iphone.erb +1 -0
  254. data/test/fixtures/respond_to/layouts/missing.html.erb +1 -0
  255. data/test/fixtures/respond_to/layouts/standard.html.erb +1 -0
  256. data/test/fixtures/respond_to/layouts/standard.iphone.erb +1 -0
  257. data/test/fixtures/respond_to/using_defaults.html.erb +1 -0
  258. data/test/fixtures/respond_to/using_defaults.js.rjs +1 -0
  259. data/test/fixtures/respond_to/using_defaults.xml.builder +1 -0
  260. data/test/fixtures/respond_to/using_defaults_with_type_list.html.erb +1 -0
  261. data/test/fixtures/respond_to/using_defaults_with_type_list.js.rjs +1 -0
  262. data/test/fixtures/respond_to/using_defaults_with_type_list.xml.builder +1 -0
  263. data/test/fixtures/scope/test/modgreet.erb +1 -0
  264. data/test/fixtures/shared.html.erb +1 -0
  265. data/test/fixtures/symlink_parent/symlinked_layout.erb +5 -0
  266. data/test/fixtures/test/_customer.erb +1 -0
  267. data/test/fixtures/test/_customer_counter.erb +1 -0
  268. data/test/fixtures/test/_customer_greeting.erb +1 -0
  269. data/test/fixtures/test/_form.erb +1 -0
  270. data/test/fixtures/test/_hash_greeting.erb +1 -0
  271. data/test/fixtures/test/_hash_object.erb +2 -0
  272. data/test/fixtures/test/_hello.builder +1 -0
  273. data/test/fixtures/test/_labelling_form.erb +1 -0
  274. data/test/fixtures/test/_layout_for_partial.html.erb +3 -0
  275. data/test/fixtures/test/_partial.erb +1 -0
  276. data/test/fixtures/test/_partial.html.erb +1 -0
  277. data/test/fixtures/test/_partial.js.erb +1 -0
  278. data/test/fixtures/test/_partial_for_use_in_layout.html.erb +1 -0
  279. data/test/fixtures/test/_partial_only.erb +1 -0
  280. data/test/fixtures/test/_person.erb +2 -0
  281. data/test/fixtures/test/_raise.html.erb +1 -0
  282. data/test/fixtures/test/action_talk_to_layout.erb +2 -0
  283. data/test/fixtures/test/block_content_for.erb +2 -0
  284. data/test/fixtures/test/calling_partial_with_layout.html.erb +1 -0
  285. data/test/fixtures/test/capturing.erb +4 -0
  286. data/test/fixtures/test/content_for.erb +2 -0
  287. data/test/fixtures/test/content_for_concatenated.erb +3 -0
  288. data/test/fixtures/test/content_for_with_parameter.erb +2 -0
  289. data/test/fixtures/test/delete_with_js.rjs +2 -0
  290. data/test/fixtures/test/dot.directory/render_file_with_ivar.erb +1 -0
  291. data/test/fixtures/test/enum_rjs_test.rjs +6 -0
  292. data/test/fixtures/test/erb_content_for.erb +2 -0
  293. data/test/fixtures/test/formatted_html_erb.html.erb +1 -0
  294. data/test/fixtures/test/formatted_xml_erb.builder +1 -0
  295. data/test/fixtures/test/formatted_xml_erb.html.erb +1 -0
  296. data/test/fixtures/test/formatted_xml_erb.xml.erb +1 -0
  297. data/test/fixtures/test/greeting.erb +1 -0
  298. data/test/fixtures/test/greeting.js.rjs +1 -0
  299. data/test/fixtures/test/hello.builder +4 -0
  300. data/test/fixtures/test/hello_world.erb +1 -0
  301. data/test/fixtures/test/hello_world_container.builder +3 -0
  302. data/test/fixtures/test/hello_world_from_rxml.builder +4 -0
  303. data/test/fixtures/test/hello_world_with_layout_false.erb +1 -0
  304. data/test/fixtures/test/hello_xml_world.builder +11 -0
  305. data/test/fixtures/test/list.erb +1 -0
  306. data/test/fixtures/test/non_erb_block_content_for.builder +4 -0
  307. data/test/fixtures/test/potential_conflicts.erb +4 -0
  308. data/test/fixtures/test/render_file_from_template.html.erb +1 -0
  309. data/test/fixtures/test/render_file_with_ivar.erb +1 -0
  310. data/test/fixtures/test/render_file_with_locals.erb +1 -0
  311. data/test/fixtures/test/render_to_string_test.erb +1 -0
  312. data/test/fixtures/test/update_element_with_capture.erb +9 -0
  313. data/test/fixtures/test/using_layout_around_block.html.erb +1 -0
  314. data/test/fixtures/topic.rb +3 -0
  315. data/test/fixtures/topics.yml +22 -0
  316. data/test/fixtures/topics/_topic.html.erb +1 -0
  317. data/test/template/active_record_helper_test.rb +268 -0
  318. data/test/template/asset_tag_helper_test.rb +514 -0
  319. data/test/template/atom_feed_helper_test.rb +179 -0
  320. data/test/template/benchmark_helper_test.rb +60 -0
  321. data/test/template/date_helper_test.rb +1791 -0
  322. data/test/template/deprecated_erb_variable_test.rb +9 -0
  323. data/test/template/erb_util_test.rb +24 -0
  324. data/test/template/form_helper_test.rb +885 -0
  325. data/test/template/form_options_helper_test.rb +1333 -0
  326. data/test/template/form_tag_helper_test.rb +272 -0
  327. data/test/template/javascript_helper_test.rb +73 -0
  328. data/test/template/number_helper_test.rb +97 -0
  329. data/test/template/record_tag_helper_test.rb +54 -0
  330. data/test/template/sanitize_helper_test.rb +48 -0
  331. data/test/template/tag_helper_test.rb +77 -0
  332. data/test/template/template_finder_test.rb +73 -0
  333. data/test/template/template_object_test.rb +95 -0
  334. data/test/template/test_test.rb +56 -0
  335. data/test/template/text_helper_test.rb +367 -0
  336. data/test/template/url_helper_test.rb +544 -0
  337. data/test/testing_sandbox.rb +15 -0
  338. metadata +469 -0
@@ -0,0 +1,2464 @@
1
+ require 'abstract_unit'
2
+ require 'controller/fake_controllers'
3
+ require 'action_controller/routing'
4
+
5
+ class MilestonesController < ActionController::Base
6
+ def index() head :ok end
7
+ alias_method :show, :index
8
+ def rescue_action(e) raise e end
9
+ end
10
+
11
+ RunTimeTests = ARGV.include? 'time'
12
+ ROUTING = ActionController::Routing
13
+
14
+ class ROUTING::RouteBuilder
15
+ attr_reader :warn_output
16
+
17
+ def warn(msg)
18
+ (@warn_output ||= []) << msg
19
+ end
20
+ end
21
+
22
+ # See RFC 3986, section 3.3 for allowed path characters.
23
+ class UriReservedCharactersRoutingTest < Test::Unit::TestCase
24
+ def setup
25
+ ActionController::Routing.use_controllers! ['controller']
26
+ @set = ActionController::Routing::RouteSet.new
27
+ @set.draw do |map|
28
+ map.connect ':controller/:action/:variable/*additional'
29
+ end
30
+
31
+ safe, unsafe = %w(: @ & = + $ , ;), %w(^ / ? # [ ])
32
+ hex = unsafe.map { |char| '%' + char.unpack('H2').first.upcase }
33
+
34
+ @segment = "#{safe.join}#{unsafe.join}".freeze
35
+ @escaped = "#{safe.join}#{hex.join}".freeze
36
+ end
37
+
38
+ def test_route_generation_escapes_unsafe_path_characters
39
+ assert_equal "/contr#{@segment}oller/act#{@escaped}ion/var#{@escaped}iable/add#{@escaped}itional-1/add#{@escaped}itional-2",
40
+ @set.generate(:controller => "contr#{@segment}oller",
41
+ :action => "act#{@segment}ion",
42
+ :variable => "var#{@segment}iable",
43
+ :additional => ["add#{@segment}itional-1", "add#{@segment}itional-2"])
44
+ end
45
+
46
+ def test_route_recognition_unescapes_path_components
47
+ options = { :controller => "controller",
48
+ :action => "act#{@segment}ion",
49
+ :variable => "var#{@segment}iable",
50
+ :additional => ["add#{@segment}itional-1", "add#{@segment}itional-2"] }
51
+ assert_equal options, @set.recognize_path("/controller/act#{@escaped}ion/var#{@escaped}iable/add#{@escaped}itional-1/add#{@escaped}itional-2")
52
+ end
53
+
54
+ def test_route_generation_allows_passing_non_string_values_to_generated_helper
55
+ assert_equal "/controller/action/variable/1/2", @set.generate(:controller => "controller",
56
+ :action => "action",
57
+ :variable => "variable",
58
+ :additional => [1, 2])
59
+ end
60
+ end
61
+
62
+ class LegacyRouteSetTests < Test::Unit::TestCase
63
+ attr_reader :rs
64
+ def setup
65
+ # These tests assume optimisation is on, so re-enable it.
66
+ ActionController::Base.optimise_named_routes = true
67
+
68
+ @rs = ::ActionController::Routing::RouteSet.new
69
+ @rs.draw {|m| m.connect ':controller/:action/:id' }
70
+
71
+ ActionController::Routing.use_controllers! %w(content admin/user admin/news_feed)
72
+ end
73
+
74
+ def test_default_setup
75
+ assert_equal({:controller => "content", :action => 'index'}, rs.recognize_path("/content"))
76
+ assert_equal({:controller => "content", :action => 'list'}, rs.recognize_path("/content/list"))
77
+ assert_equal({:controller => "content", :action => 'show', :id => '10'}, rs.recognize_path("/content/show/10"))
78
+
79
+ assert_equal({:controller => "admin/user", :action => 'show', :id => '10'}, rs.recognize_path("/admin/user/show/10"))
80
+
81
+ assert_equal '/admin/user/show/10', rs.generate(:controller => 'admin/user', :action => 'show', :id => 10)
82
+
83
+ assert_equal '/admin/user/show', rs.generate({:action => 'show'}, {:controller => 'admin/user', :action => 'list', :id => '10'})
84
+ assert_equal '/admin/user/list/10', rs.generate({}, {:controller => 'admin/user', :action => 'list', :id => '10'})
85
+
86
+ assert_equal '/admin/stuff', rs.generate({:controller => 'stuff'}, {:controller => 'admin/user', :action => 'list', :id => '10'})
87
+ assert_equal '/stuff', rs.generate({:controller => '/stuff'}, {:controller => 'admin/user', :action => 'list', :id => '10'})
88
+ end
89
+
90
+ def test_ignores_leading_slash
91
+ @rs.draw {|m| m.connect '/:controller/:action/:id'}
92
+ test_default_setup
93
+ end
94
+
95
+ def test_time_recognition
96
+ # We create many routes to make situation more realistic
97
+ @rs = ::ActionController::Routing::RouteSet.new
98
+ @rs.draw { |map|
99
+ map.frontpage '', :controller => 'search', :action => 'new'
100
+ map.resources :videos do |video|
101
+ video.resources :comments
102
+ video.resource :file, :controller => 'video_file'
103
+ video.resource :share, :controller => 'video_shares'
104
+ video.resource :abuse, :controller => 'video_abuses'
105
+ end
106
+ map.resources :abuses, :controller => 'video_abuses'
107
+ map.resources :video_uploads
108
+ map.resources :video_visits
109
+
110
+ map.resources :users do |user|
111
+ user.resource :settings
112
+ user.resources :videos
113
+ end
114
+ map.resources :channels do |channel|
115
+ channel.resources :videos, :controller => 'channel_videos'
116
+ end
117
+ map.resource :session
118
+ map.resource :lost_password
119
+ map.search 'search', :controller => 'search'
120
+ map.resources :pages
121
+ map.connect ':controller/:action/:id'
122
+ }
123
+ n = 1000
124
+ if RunTimeTests
125
+ GC.start
126
+ rectime = Benchmark.realtime do
127
+ n.times do
128
+ rs.recognize_path("/videos/1234567", {:method => :get})
129
+ rs.recognize_path("/videos/1234567/abuse", {:method => :get})
130
+ rs.recognize_path("/users/1234567/settings", {:method => :get})
131
+ rs.recognize_path("/channels/1234567", {:method => :get})
132
+ rs.recognize_path("/session/new", {:method => :get})
133
+ rs.recognize_path("/admin/user/show/10", {:method => :get})
134
+ end
135
+ end
136
+ puts "\n\nRecognition (#{rs.routes.size} routes):"
137
+ per_url = rectime / (n * 6)
138
+ puts "#{per_url * 1000} ms/url"
139
+ puts "#{1 / per_url} url/s\n\n"
140
+ end
141
+ end
142
+ def test_time_generation
143
+ n = 5000
144
+ if RunTimeTests
145
+ GC.start
146
+ pairs = [
147
+ [{:controller => 'content', :action => 'index'}, {:controller => 'content', :action => 'show'}],
148
+ [{:controller => 'content'}, {:controller => 'content', :action => 'index'}],
149
+ [{:controller => 'content', :action => 'list'}, {:controller => 'content', :action => 'index'}],
150
+ [{:controller => 'content', :action => 'show', :id => '10'}, {:controller => 'content', :action => 'list'}],
151
+ [{:controller => 'admin/user', :action => 'index'}, {:controller => 'admin/user', :action => 'show'}],
152
+ [{:controller => 'admin/user'}, {:controller => 'admin/user', :action => 'index'}],
153
+ [{:controller => 'admin/user', :action => 'list'}, {:controller => 'admin/user', :action => 'index'}],
154
+ [{:controller => 'admin/user', :action => 'show', :id => '10'}, {:controller => 'admin/user', :action => 'list'}],
155
+ ]
156
+ p = nil
157
+ gentime = Benchmark.realtime do
158
+ n.times do
159
+ pairs.each {|(a, b)| rs.generate(a, b)}
160
+ end
161
+ end
162
+
163
+ puts "\n\nGeneration (RouteSet): (#{(n * 8)} urls)"
164
+ per_url = gentime / (n * 8)
165
+ puts "#{per_url * 1000} ms/url"
166
+ puts "#{1 / per_url} url/s\n\n"
167
+ end
168
+ end
169
+
170
+ def test_route_with_colon_first
171
+ rs.draw do |map|
172
+ map.connect '/:controller/:action/:id', :action => 'index', :id => nil
173
+ map.connect ':url', :controller => 'tiny_url', :action => 'translate'
174
+ end
175
+ end
176
+
177
+ def test_route_with_regexp_for_controller
178
+ rs.draw do |map|
179
+ map.connect ':controller/:admintoken/:action/:id', :controller => /admin\/.+/
180
+ map.connect ':controller/:action/:id'
181
+ end
182
+ assert_equal({:controller => "admin/user", :admintoken => "foo", :action => "index"},
183
+ rs.recognize_path("/admin/user/foo"))
184
+ assert_equal({:controller => "content", :action => "foo"}, rs.recognize_path("/content/foo"))
185
+ assert_equal '/admin/user/foo', rs.generate(:controller => "admin/user", :admintoken => "foo", :action => "index")
186
+ assert_equal '/content/foo', rs.generate(:controller => "content", :action => "foo")
187
+ end
188
+
189
+ def test_route_with_regexp_and_dot
190
+ rs.draw do |map|
191
+ map.connect ':controller/:action/:file',
192
+ :controller => /admin|user/,
193
+ :action => /upload|download/,
194
+ :defaults => {:file => nil},
195
+ :requirements => {:file => %r{[^/]+(\.[^/]+)?}}
196
+ end
197
+ # Without a file extension
198
+ assert_equal '/user/download/file',
199
+ rs.generate(:controller => "user", :action => "download", :file => "file")
200
+ assert_equal(
201
+ {:controller => "user", :action => "download", :file => "file"},
202
+ rs.recognize_path("/user/download/file"))
203
+
204
+ # Now, let's try a file with an extension, really a dot (.)
205
+ assert_equal '/user/download/file.jpg',
206
+ rs.generate(
207
+ :controller => "user", :action => "download", :file => "file.jpg")
208
+ assert_equal(
209
+ {:controller => "user", :action => "download", :file => "file.jpg"},
210
+ rs.recognize_path("/user/download/file.jpg"))
211
+ end
212
+
213
+ def test_basic_named_route
214
+ rs.add_named_route :home, '', :controller => 'content', :action => 'list'
215
+ x = setup_for_named_route
216
+ assert_equal("http://named.route.test/",
217
+ x.send(:home_url))
218
+ end
219
+
220
+ def test_basic_named_route_with_relative_url_root
221
+ rs.add_named_route :home, '', :controller => 'content', :action => 'list'
222
+ x = setup_for_named_route
223
+ x.relative_url_root="/foo"
224
+ assert_equal("http://named.route.test/foo/",
225
+ x.send(:home_url))
226
+ assert_equal "/foo/", x.send(:home_path)
227
+ end
228
+
229
+ def test_named_route_with_option
230
+ rs.add_named_route :page, 'page/:title', :controller => 'content', :action => 'show_page'
231
+ x = setup_for_named_route
232
+ assert_equal("http://named.route.test/page/new%20stuff",
233
+ x.send(:page_url, :title => 'new stuff'))
234
+ end
235
+
236
+ def test_named_route_with_default
237
+ rs.add_named_route :page, 'page/:title', :controller => 'content', :action => 'show_page', :title => 'AboutPage'
238
+ x = setup_for_named_route
239
+ assert_equal("http://named.route.test/page/AboutRails",
240
+ x.send(:page_url, :title => "AboutRails"))
241
+
242
+ end
243
+
244
+ def test_named_route_with_nested_controller
245
+ rs.add_named_route :users, 'admin/user', :controller => 'admin/user', :action => 'index'
246
+ x = setup_for_named_route
247
+ assert_equal("http://named.route.test/admin/user",
248
+ x.send(:users_url))
249
+ end
250
+
251
+ uses_mocha "named route optimisation" do
252
+ def test_optimised_named_route_call_never_uses_url_for
253
+ rs.add_named_route :users, 'admin/user', :controller => '/admin/user', :action => 'index'
254
+ rs.add_named_route :user, 'admin/user/:id', :controller=>'/admin/user', :action=>'show'
255
+ x = setup_for_named_route
256
+ x.expects(:url_for).never
257
+ x.send(:users_url)
258
+ x.send(:users_path)
259
+ x.send(:user_url, 2, :foo=>"bar")
260
+ x.send(:user_path, 3, :bar=>"foo")
261
+ end
262
+
263
+ def test_optimised_named_route_with_host
264
+ rs.add_named_route :pages, 'pages', :controller => 'content', :action => 'show_page', :host => 'foo.com'
265
+ x = setup_for_named_route
266
+ x.expects(:url_for).with(:host => 'foo.com', :only_path => false, :controller => 'content', :action => 'show_page', :use_route => :pages).once
267
+ x.send(:pages_url)
268
+ end
269
+ end
270
+
271
+ def setup_for_named_route
272
+ klass = Class.new(MockController)
273
+ rs.install_helpers(klass)
274
+ klass.new(rs)
275
+ end
276
+
277
+ def test_named_route_without_hash
278
+ rs.draw do |map|
279
+ map.normal ':controller/:action/:id'
280
+ end
281
+ end
282
+
283
+ def test_named_route_root
284
+ rs.draw do |map|
285
+ map.root :controller => "hello"
286
+ end
287
+ x = setup_for_named_route
288
+ assert_equal("http://named.route.test/", x.send(:root_url))
289
+ assert_equal("/", x.send(:root_path))
290
+ end
291
+
292
+ def test_named_route_with_regexps
293
+ rs.draw do |map|
294
+ map.article 'page/:year/:month/:day/:title', :controller => 'page', :action => 'show',
295
+ :year => /\d+/, :month => /\d+/, :day => /\d+/
296
+ map.connect ':controller/:action/:id'
297
+ end
298
+ x = setup_for_named_route
299
+ # assert_equal(
300
+ # {:controller => 'page', :action => 'show', :title => 'hi', :use_route => :article, :only_path => false},
301
+ # x.send(:article_url, :title => 'hi')
302
+ # )
303
+ assert_equal(
304
+ "http://named.route.test/page/2005/6/10/hi",
305
+ x.send(:article_url, :title => 'hi', :day => 10, :year => 2005, :month => 6)
306
+ )
307
+ end
308
+
309
+ def test_changing_controller
310
+ assert_equal '/admin/stuff/show/10', rs.generate(
311
+ {:controller => 'stuff', :action => 'show', :id => 10},
312
+ {:controller => 'admin/user', :action => 'index'}
313
+ )
314
+ end
315
+
316
+ def test_paths_escaped
317
+ rs.draw do |map|
318
+ map.path 'file/*path', :controller => 'content', :action => 'show_file'
319
+ map.connect ':controller/:action/:id'
320
+ end
321
+
322
+ # No + to space in URI escaping, only for query params.
323
+ results = rs.recognize_path "/file/hello+world/how+are+you%3F"
324
+ assert results, "Recognition should have succeeded"
325
+ assert_equal ['hello+world', 'how+are+you?'], results[:path]
326
+
327
+ # Use %20 for space instead.
328
+ results = rs.recognize_path "/file/hello%20world/how%20are%20you%3F"
329
+ assert results, "Recognition should have succeeded"
330
+ assert_equal ['hello world', 'how are you?'], results[:path]
331
+
332
+ results = rs.recognize_path "/file"
333
+ assert results, "Recognition should have succeeded"
334
+ assert_equal [], results[:path]
335
+ end
336
+
337
+ def test_paths_slashes_unescaped_with_ordered_parameters
338
+ rs.add_named_route :path, '/file/*path', :controller => 'content'
339
+
340
+ # No / to %2F in URI, only for query params.
341
+ x = setup_for_named_route
342
+ assert_equal("/file/hello/world", x.send(:path_path, 'hello/world'))
343
+ end
344
+
345
+ def test_non_controllers_cannot_be_matched
346
+ rs.draw do |map|
347
+ map.connect ':controller/:action/:id'
348
+ end
349
+ assert_raises(ActionController::RoutingError) { rs.recognize_path("/not_a/show/10") }
350
+ end
351
+
352
+ def test_paths_do_not_accept_defaults
353
+ assert_raises(ActionController::RoutingError) do
354
+ rs.draw do |map|
355
+ map.path 'file/*path', :controller => 'content', :action => 'show_file', :path => %w(fake default)
356
+ map.connect ':controller/:action/:id'
357
+ end
358
+ end
359
+
360
+ rs.draw do |map|
361
+ map.path 'file/*path', :controller => 'content', :action => 'show_file', :path => []
362
+ map.connect ':controller/:action/:id'
363
+ end
364
+ end
365
+
366
+ def test_should_list_options_diff_when_routing_requirements_dont_match
367
+ rs.draw do |map|
368
+ map.post 'post/:id', :controller=> 'post', :action=> 'show', :requirements => {:id => /\d+/}
369
+ end
370
+ exception = assert_raise(ActionController::RoutingError) { rs.generate(:controller => 'post', :action => 'show', :bad_param => "foo", :use_route => "post") }
371
+ assert_match /^post_url failed to generate/, exception.message
372
+ from_match = exception.message.match(/from \{[^\}]+\}/).to_s
373
+ assert_match /:bad_param=>"foo"/, from_match
374
+ assert_match /:action=>"show"/, from_match
375
+ assert_match /:controller=>"post"/, from_match
376
+
377
+ expected_match = exception.message.match(/expected: \{[^\}]+\}/).to_s
378
+ assert_no_match /:bad_param=>"foo"/, expected_match
379
+ assert_match /:action=>"show"/, expected_match
380
+ assert_match /:controller=>"post"/, expected_match
381
+
382
+ diff_match = exception.message.match(/diff: \{[^\}]+\}/).to_s
383
+ assert_match /:bad_param=>"foo"/, diff_match
384
+ assert_no_match /:action=>"show"/, diff_match
385
+ assert_no_match /:controller=>"post"/, diff_match
386
+ end
387
+
388
+ # this specifies the case where your formerly would get a very confusing error message with an empty diff
389
+ def test_should_have_better_error_message_when_options_diff_is_empty
390
+ rs.draw do |map|
391
+ map.content '/content/:query', :controller => 'content', :action => 'show'
392
+ end
393
+
394
+ exception = assert_raise(ActionController::RoutingError) { rs.generate(:controller => 'content', :action => 'show', :use_route => "content") }
395
+ assert_match %r[:action=>"show"], exception.message
396
+ assert_match %r[:controller=>"content"], exception.message
397
+ assert_match %r[you may have ambiguous routes, or you may need to supply additional parameters for this route], exception.message
398
+ assert_match %r[content_url has the following required parameters: \["content", :query\] - are they all satisfied?], exception.message
399
+ end
400
+
401
+ def test_dynamic_path_allowed
402
+ rs.draw do |map|
403
+ map.connect '*path', :controller => 'content', :action => 'show_file'
404
+ end
405
+
406
+ assert_equal '/pages/boo', rs.generate(:controller => 'content', :action => 'show_file', :path => %w(pages boo))
407
+ end
408
+
409
+ def test_dynamic_recall_paths_allowed
410
+ rs.draw do |map|
411
+ map.connect '*path', :controller => 'content', :action => 'show_file'
412
+ end
413
+
414
+ recall_path = ActionController::Routing::PathSegment::Result.new(%w(pages boo))
415
+ assert_equal '/pages/boo', rs.generate({}, :controller => 'content', :action => 'show_file', :path => recall_path)
416
+ end
417
+
418
+ def test_backwards
419
+ rs.draw do |map|
420
+ map.connect 'page/:id/:action', :controller => 'pages', :action => 'show'
421
+ map.connect ':controller/:action/:id'
422
+ end
423
+
424
+ assert_equal '/page/20', rs.generate({:id => 20}, {:controller => 'pages', :action => 'show'})
425
+ assert_equal '/page/20', rs.generate(:controller => 'pages', :id => 20, :action => 'show')
426
+ assert_equal '/pages/boo', rs.generate(:controller => 'pages', :action => 'boo')
427
+ end
428
+
429
+ def test_route_with_fixnum_default
430
+ rs.draw do |map|
431
+ map.connect 'page/:id', :controller => 'content', :action => 'show_page', :id => 1
432
+ map.connect ':controller/:action/:id'
433
+ end
434
+
435
+ assert_equal '/page', rs.generate(:controller => 'content', :action => 'show_page')
436
+ assert_equal '/page', rs.generate(:controller => 'content', :action => 'show_page', :id => 1)
437
+ assert_equal '/page', rs.generate(:controller => 'content', :action => 'show_page', :id => '1')
438
+ assert_equal '/page/10', rs.generate(:controller => 'content', :action => 'show_page', :id => 10)
439
+
440
+ assert_equal({:controller => "content", :action => 'show_page', :id => '1'}, rs.recognize_path("/page"))
441
+ assert_equal({:controller => "content", :action => 'show_page', :id => '1'}, rs.recognize_path("/page/1"))
442
+ assert_equal({:controller => "content", :action => 'show_page', :id => '10'}, rs.recognize_path("/page/10"))
443
+ end
444
+
445
+ # For newer revision
446
+ def test_route_with_text_default
447
+ rs.draw do |map|
448
+ map.connect 'page/:id', :controller => 'content', :action => 'show_page', :id => 1
449
+ map.connect ':controller/:action/:id'
450
+ end
451
+
452
+ assert_equal '/page/foo', rs.generate(:controller => 'content', :action => 'show_page', :id => 'foo')
453
+ assert_equal({:controller => "content", :action => 'show_page', :id => 'foo'}, rs.recognize_path("/page/foo"))
454
+
455
+ token = "\321\202\320\265\320\272\321\201\321\202" # 'text' in russian
456
+ escaped_token = CGI::escape(token)
457
+
458
+ assert_equal '/page/' + escaped_token, rs.generate(:controller => 'content', :action => 'show_page', :id => token)
459
+ assert_equal({:controller => "content", :action => 'show_page', :id => token}, rs.recognize_path("/page/#{escaped_token}"))
460
+ end
461
+
462
+ def test_action_expiry
463
+ assert_equal '/content', rs.generate({:controller => 'content'}, {:controller => 'content', :action => 'show'})
464
+ end
465
+
466
+ def test_recognition_with_uppercase_controller_name
467
+ assert_equal({:controller => "content", :action => 'index'}, rs.recognize_path("/Content"))
468
+ assert_equal({:controller => "content", :action => 'list'}, rs.recognize_path("/ConTent/list"))
469
+ assert_equal({:controller => "content", :action => 'show', :id => '10'}, rs.recognize_path("/CONTENT/show/10"))
470
+
471
+ # these used to work, before the routes rewrite, but support for this was pulled in the new version...
472
+ #assert_equal({'controller' => "admin/news_feed", 'action' => 'index'}, rs.recognize_path("Admin/NewsFeed"))
473
+ #assert_equal({'controller' => "admin/news_feed", 'action' => 'index'}, rs.recognize_path("Admin/News_Feed"))
474
+ end
475
+
476
+ def test_requirement_should_prevent_optional_id
477
+ rs.draw do |map|
478
+ map.post 'post/:id', :controller=> 'post', :action=> 'show', :requirements => {:id => /\d+/}
479
+ end
480
+
481
+ assert_equal '/post/10', rs.generate(:controller => 'post', :action => 'show', :id => 10)
482
+
483
+ assert_raises ActionController::RoutingError do
484
+ rs.generate(:controller => 'post', :action => 'show')
485
+ end
486
+ end
487
+
488
+ def test_both_requirement_and_optional
489
+ rs.draw do |map|
490
+ map.blog('test/:year', :controller => 'post', :action => 'show',
491
+ :defaults => { :year => nil },
492
+ :requirements => { :year => /\d{4}/ }
493
+ )
494
+ map.connect ':controller/:action/:id'
495
+ end
496
+
497
+ assert_equal '/test', rs.generate(:controller => 'post', :action => 'show')
498
+ assert_equal '/test', rs.generate(:controller => 'post', :action => 'show', :year => nil)
499
+
500
+ x = setup_for_named_route
501
+ assert_equal("http://named.route.test/test",
502
+ x.send(:blog_url))
503
+ end
504
+
505
+ def test_set_to_nil_forgets
506
+ rs.draw do |map|
507
+ map.connect 'pages/:year/:month/:day', :controller => 'content', :action => 'list_pages', :month => nil, :day => nil
508
+ map.connect ':controller/:action/:id'
509
+ end
510
+
511
+ assert_equal '/pages/2005',
512
+ rs.generate(:controller => 'content', :action => 'list_pages', :year => 2005)
513
+ assert_equal '/pages/2005/6',
514
+ rs.generate(:controller => 'content', :action => 'list_pages', :year => 2005, :month => 6)
515
+ assert_equal '/pages/2005/6/12',
516
+ rs.generate(:controller => 'content', :action => 'list_pages', :year => 2005, :month => 6, :day => 12)
517
+
518
+ assert_equal '/pages/2005/6/4',
519
+ rs.generate({:day => 4}, {:controller => 'content', :action => 'list_pages', :year => '2005', :month => '6', :day => '12'})
520
+
521
+ assert_equal '/pages/2005/6',
522
+ rs.generate({:day => nil}, {:controller => 'content', :action => 'list_pages', :year => '2005', :month => '6', :day => '12'})
523
+
524
+ assert_equal '/pages/2005',
525
+ rs.generate({:day => nil, :month => nil}, {:controller => 'content', :action => 'list_pages', :year => '2005', :month => '6', :day => '12'})
526
+ end
527
+
528
+ def test_url_with_no_action_specified
529
+ rs.draw do |map|
530
+ map.connect '', :controller => 'content'
531
+ map.connect ':controller/:action/:id'
532
+ end
533
+
534
+ assert_equal '/', rs.generate(:controller => 'content', :action => 'index')
535
+ assert_equal '/', rs.generate(:controller => 'content')
536
+ end
537
+
538
+ def test_named_url_with_no_action_specified
539
+ rs.draw do |map|
540
+ map.home '', :controller => 'content'
541
+ map.connect ':controller/:action/:id'
542
+ end
543
+
544
+ assert_equal '/', rs.generate(:controller => 'content', :action => 'index')
545
+ assert_equal '/', rs.generate(:controller => 'content')
546
+
547
+ x = setup_for_named_route
548
+ assert_equal("http://named.route.test/",
549
+ x.send(:home_url))
550
+ end
551
+
552
+ def test_url_generated_when_forgetting_action
553
+ [{:controller => 'content', :action => 'index'}, {:controller => 'content'}].each do |hash|
554
+ rs.draw do |map|
555
+ map.home '', hash
556
+ map.connect ':controller/:action/:id'
557
+ end
558
+ assert_equal '/', rs.generate({:action => nil}, {:controller => 'content', :action => 'hello'})
559
+ assert_equal '/', rs.generate({:controller => 'content'})
560
+ assert_equal '/content/hi', rs.generate({:controller => 'content', :action => 'hi'})
561
+ end
562
+ end
563
+
564
+ def test_named_route_method
565
+ rs.draw do |map|
566
+ map.categories 'categories', :controller => 'content', :action => 'categories'
567
+ map.connect ':controller/:action/:id'
568
+ end
569
+
570
+ assert_equal '/categories', rs.generate(:controller => 'content', :action => 'categories')
571
+ assert_equal '/content/hi', rs.generate({:controller => 'content', :action => 'hi'})
572
+ end
573
+
574
+ def test_named_routes_array
575
+ test_named_route_method
576
+ assert_equal [:categories], rs.named_routes.names
577
+ end
578
+
579
+ def test_nil_defaults
580
+ rs.draw do |map|
581
+ map.connect 'journal',
582
+ :controller => 'content',
583
+ :action => 'list_journal',
584
+ :date => nil, :user_id => nil
585
+ map.connect ':controller/:action/:id'
586
+ end
587
+
588
+ assert_equal '/journal', rs.generate(:controller => 'content', :action => 'list_journal', :date => nil, :user_id => nil)
589
+ end
590
+
591
+ def setup_request_method_routes_for(method)
592
+ @request = ActionController::TestRequest.new
593
+ @request.env["REQUEST_METHOD"] = method
594
+ @request.request_uri = "/match"
595
+
596
+ rs.draw do |r|
597
+ r.connect '/match', :controller => 'books', :action => 'get', :conditions => { :method => :get }
598
+ r.connect '/match', :controller => 'books', :action => 'post', :conditions => { :method => :post }
599
+ r.connect '/match', :controller => 'books', :action => 'put', :conditions => { :method => :put }
600
+ r.connect '/match', :controller => 'books', :action => 'delete', :conditions => { :method => :delete }
601
+ end
602
+ end
603
+
604
+ %w(GET POST PUT DELETE).each do |request_method|
605
+ define_method("test_request_method_recognized_with_#{request_method}") do
606
+ begin
607
+ Object.const_set(:BooksController, Class.new(ActionController::Base))
608
+
609
+ setup_request_method_routes_for(request_method)
610
+
611
+ assert_nothing_raised { rs.recognize(@request) }
612
+ assert_equal request_method.downcase, @request.path_parameters[:action]
613
+ ensure
614
+ Object.send(:remove_const, :BooksController) rescue nil
615
+ end
616
+ end
617
+ end
618
+
619
+ def test_subpath_recognized
620
+ Object.const_set(:SubpathBooksController, Class.new(ActionController::Base))
621
+
622
+ rs.draw do |r|
623
+ r.connect '/books/:id/edit', :controller => 'subpath_books', :action => 'edit'
624
+ r.connect '/items/:id/:action', :controller => 'subpath_books'
625
+ r.connect '/posts/new/:action', :controller => 'subpath_books'
626
+ r.connect '/posts/:id', :controller => 'subpath_books', :action => "show"
627
+ end
628
+
629
+ hash = rs.recognize_path "/books/17/edit"
630
+ assert_not_nil hash
631
+ assert_equal %w(subpath_books 17 edit), [hash[:controller], hash[:id], hash[:action]]
632
+
633
+ hash = rs.recognize_path "/items/3/complete"
634
+ assert_not_nil hash
635
+ assert_equal %w(subpath_books 3 complete), [hash[:controller], hash[:id], hash[:action]]
636
+
637
+ hash = rs.recognize_path "/posts/new/preview"
638
+ assert_not_nil hash
639
+ assert_equal %w(subpath_books preview), [hash[:controller], hash[:action]]
640
+
641
+ hash = rs.recognize_path "/posts/7"
642
+ assert_not_nil hash
643
+ assert_equal %w(subpath_books show 7), [hash[:controller], hash[:action], hash[:id]]
644
+ ensure
645
+ Object.send(:remove_const, :SubpathBooksController) rescue nil
646
+ end
647
+
648
+ def test_subpath_generated
649
+ Object.const_set(:SubpathBooksController, Class.new(ActionController::Base))
650
+
651
+ rs.draw do |r|
652
+ r.connect '/books/:id/edit', :controller => 'subpath_books', :action => 'edit'
653
+ r.connect '/items/:id/:action', :controller => 'subpath_books'
654
+ r.connect '/posts/new/:action', :controller => 'subpath_books'
655
+ end
656
+
657
+ assert_equal "/books/7/edit", rs.generate(:controller => "subpath_books", :id => 7, :action => "edit")
658
+ assert_equal "/items/15/complete", rs.generate(:controller => "subpath_books", :id => 15, :action => "complete")
659
+ assert_equal "/posts/new/preview", rs.generate(:controller => "subpath_books", :action => "preview")
660
+ ensure
661
+ Object.send(:remove_const, :SubpathBooksController) rescue nil
662
+ end
663
+
664
+ def test_failed_requirements_raises_exception_with_violated_requirements
665
+ rs.draw do |r|
666
+ r.foo_with_requirement 'foos/:id', :controller=>'foos', :requirements=>{:id=>/\d+/}
667
+ end
668
+
669
+ x = setup_for_named_route
670
+ assert_raises(ActionController::RoutingError) do
671
+ x.send(:foo_with_requirement_url, "I am Against the requirements")
672
+ end
673
+ end
674
+
675
+ def test_routes_changed_correctly_after_clear
676
+ ActionController::Base.optimise_named_routes = true
677
+ rs = ::ActionController::Routing::RouteSet.new
678
+ rs.draw do |r|
679
+ r.connect 'ca', :controller => 'ca', :action => "aa"
680
+ r.connect 'cb', :controller => 'cb', :action => "ab"
681
+ r.connect 'cc', :controller => 'cc', :action => "ac"
682
+ r.connect ':controller/:action/:id'
683
+ r.connect ':controller/:action/:id.:format'
684
+ end
685
+
686
+ hash = rs.recognize_path "/cc"
687
+
688
+ assert_not_nil hash
689
+ assert_equal %w(cc ac), [hash[:controller], hash[:action]]
690
+
691
+ rs.draw do |r|
692
+ r.connect 'cb', :controller => 'cb', :action => "ab"
693
+ r.connect 'cc', :controller => 'cc', :action => "ac"
694
+ r.connect ':controller/:action/:id'
695
+ r.connect ':controller/:action/:id.:format'
696
+ end
697
+
698
+ hash = rs.recognize_path "/cc"
699
+
700
+ assert_not_nil hash
701
+ assert_equal %w(cc ac), [hash[:controller], hash[:action]]
702
+ end
703
+ end
704
+
705
+ class SegmentTest < Test::Unit::TestCase
706
+
707
+ def test_first_segment_should_interpolate_for_structure
708
+ s = ROUTING::Segment.new
709
+ def s.interpolation_statement(array) 'hello' end
710
+ assert_equal 'hello', s.continue_string_structure([])
711
+ end
712
+
713
+ def test_interpolation_statement
714
+ s = ROUTING::StaticSegment.new
715
+ s.value = "Hello"
716
+ assert_equal "Hello", eval(s.interpolation_statement([]))
717
+ assert_equal "HelloHello", eval(s.interpolation_statement([s]))
718
+
719
+ s2 = ROUTING::StaticSegment.new
720
+ s2.value = "-"
721
+ assert_equal "Hello-Hello", eval(s.interpolation_statement([s, s2]))
722
+
723
+ s3 = ROUTING::StaticSegment.new
724
+ s3.value = "World"
725
+ assert_equal "Hello-World", eval(s3.interpolation_statement([s, s2]))
726
+ end
727
+
728
+ end
729
+
730
+ class StaticSegmentTest < Test::Unit::TestCase
731
+
732
+ def test_interpolation_chunk_should_respect_raw
733
+ s = ROUTING::StaticSegment.new
734
+ s.value = 'Hello World'
735
+ assert ! s.raw?
736
+ assert_equal 'Hello%20World', s.interpolation_chunk
737
+
738
+ s.raw = true
739
+ assert s.raw?
740
+ assert_equal 'Hello World', s.interpolation_chunk
741
+ end
742
+
743
+ def test_regexp_chunk_should_escape_specials
744
+ s = ROUTING::StaticSegment.new
745
+
746
+ s.value = 'Hello*World'
747
+ assert_equal 'Hello\*World', s.regexp_chunk
748
+
749
+ s.value = 'HelloWorld'
750
+ assert_equal 'HelloWorld', s.regexp_chunk
751
+ end
752
+
753
+ def test_regexp_chunk_should_add_question_mark_for_optionals
754
+ s = ROUTING::StaticSegment.new
755
+ s.value = "/"
756
+ s.is_optional = true
757
+ assert_equal "/?", s.regexp_chunk
758
+
759
+ s.value = "hello"
760
+ assert_equal "(?:hello)?", s.regexp_chunk
761
+ end
762
+
763
+ end
764
+
765
+ class DynamicSegmentTest < Test::Unit::TestCase
766
+
767
+ def segment
768
+ unless @segment
769
+ @segment = ROUTING::DynamicSegment.new
770
+ @segment.key = :a
771
+ end
772
+ @segment
773
+ end
774
+
775
+ def test_extract_value
776
+ s = ROUTING::DynamicSegment.new
777
+ s.key = :a
778
+
779
+ hash = {:a => '10', :b => '20'}
780
+ assert_equal '10', eval(s.extract_value)
781
+
782
+ hash = {:b => '20'}
783
+ assert_equal nil, eval(s.extract_value)
784
+
785
+ s.default = '20'
786
+ assert_equal '20', eval(s.extract_value)
787
+ end
788
+
789
+ def test_default_local_name
790
+ assert_equal 'a_value', segment.local_name,
791
+ "Unexpected name -- all value_check tests will fail!"
792
+ end
793
+
794
+ def test_presence_value_check
795
+ a_value = 10
796
+ assert eval(segment.value_check)
797
+ end
798
+
799
+ def test_regexp_value_check_rejects_nil
800
+ segment.regexp = /\d+/
801
+ a_value = nil
802
+ assert ! eval(segment.value_check)
803
+ end
804
+
805
+ def test_optional_regexp_value_check_should_accept_nil
806
+ segment.regexp = /\d+/
807
+ segment.is_optional = true
808
+ a_value = nil
809
+ assert eval(segment.value_check)
810
+ end
811
+
812
+ def test_regexp_value_check_rejects_no_match
813
+ segment.regexp = /\d+/
814
+
815
+ a_value = "Hello20World"
816
+ assert ! eval(segment.value_check)
817
+
818
+ a_value = "20Hi"
819
+ assert ! eval(segment.value_check)
820
+ end
821
+
822
+ def test_regexp_value_check_accepts_match
823
+ segment.regexp = /\d+/
824
+
825
+ a_value = "30"
826
+ assert eval(segment.value_check)
827
+ end
828
+
829
+ def test_value_check_fails_on_nil
830
+ a_value = nil
831
+ assert ! eval(segment.value_check)
832
+ end
833
+
834
+ def test_optional_value_needs_no_check
835
+ segment.is_optional = true
836
+ a_value = nil
837
+ assert_equal nil, segment.value_check
838
+ end
839
+
840
+ def test_regexp_value_check_should_accept_match_with_default
841
+ segment.regexp = /\d+/
842
+ segment.default = '200'
843
+
844
+ a_value = '100'
845
+ assert eval(segment.value_check)
846
+ end
847
+
848
+ def test_expiry_should_not_trigger_once_expired
849
+ expired = true
850
+ hash = merged = {:a => 2, :b => 3}
851
+ options = {:b => 3}
852
+ expire_on = Hash.new { raise 'No!!!' }
853
+
854
+ eval(segment.expiry_statement)
855
+ rescue RuntimeError
856
+ flunk "Expiry check should not have occurred!"
857
+ end
858
+
859
+ def test_expiry_should_occur_according_to_expire_on
860
+ expired = false
861
+ hash = merged = {:a => 2, :b => 3}
862
+ options = {:b => 3}
863
+
864
+ expire_on = {:b => true, :a => false}
865
+ eval(segment.expiry_statement)
866
+ assert !expired
867
+ assert_equal({:a => 2, :b => 3}, hash)
868
+
869
+ expire_on = {:b => true, :a => true}
870
+ eval(segment.expiry_statement)
871
+ assert expired
872
+ assert_equal({:b => 3}, hash)
873
+ end
874
+
875
+ def test_extraction_code_should_return_on_nil
876
+ hash = merged = {:b => 3}
877
+ options = {:b => 3}
878
+ a_value = nil
879
+
880
+ # Local jump because of return inside eval.
881
+ assert_raises(LocalJumpError) { eval(segment.extraction_code) }
882
+ end
883
+
884
+ def test_extraction_code_should_return_on_mismatch
885
+ segment.regexp = /\d+/
886
+ hash = merged = {:a => 'Hi', :b => '3'}
887
+ options = {:b => '3'}
888
+ a_value = nil
889
+
890
+ # Local jump because of return inside eval.
891
+ assert_raises(LocalJumpError) { eval(segment.extraction_code) }
892
+ end
893
+
894
+ def test_extraction_code_should_accept_value_and_set_local
895
+ hash = merged = {:a => 'Hi', :b => '3'}
896
+ options = {:b => '3'}
897
+ a_value = nil
898
+ expired = true
899
+
900
+ eval(segment.extraction_code)
901
+ assert_equal 'Hi', a_value
902
+ end
903
+
904
+ def test_extraction_should_work_without_value_check
905
+ segment.default = 'hi'
906
+ hash = merged = {:b => '3'}
907
+ options = {:b => '3'}
908
+ a_value = nil
909
+ expired = true
910
+
911
+ eval(segment.extraction_code)
912
+ assert_equal 'hi', a_value
913
+ end
914
+
915
+ def test_extraction_code_should_perform_expiry
916
+ expired = false
917
+ hash = merged = {:a => 'Hi', :b => '3'}
918
+ options = {:b => '3'}
919
+ expire_on = {:a => true}
920
+ a_value = nil
921
+
922
+ eval(segment.extraction_code)
923
+ assert_equal 'Hi', a_value
924
+ assert expired
925
+ assert_equal options, hash
926
+ end
927
+
928
+ def test_interpolation_chunk_should_replace_value
929
+ a_value = 'Hi'
930
+ assert_equal a_value, eval(%("#{segment.interpolation_chunk}"))
931
+ end
932
+
933
+ def test_interpolation_chunk_should_accept_nil
934
+ a_value = nil
935
+ assert_equal '', eval(%("#{segment.interpolation_chunk('a_value')}"))
936
+ end
937
+
938
+ def test_value_regexp_should_be_nil_without_regexp
939
+ assert_equal nil, segment.value_regexp
940
+ end
941
+
942
+ def test_value_regexp_should_match_exacly
943
+ segment.regexp = /\d+/
944
+ assert_no_match segment.value_regexp, "Hello 10 World"
945
+ assert_no_match segment.value_regexp, "Hello 10"
946
+ assert_no_match segment.value_regexp, "10 World"
947
+ assert_match segment.value_regexp, "10"
948
+ end
949
+
950
+ def test_regexp_chunk_should_return_string
951
+ segment.regexp = /\d+/
952
+ assert_kind_of String, segment.regexp_chunk
953
+ end
954
+
955
+ def test_build_pattern_non_optional_with_no_captures
956
+ # Non optional
957
+ a_segment = ROUTING::DynamicSegment.new
958
+ a_segment.regexp = /\d+/ #number_of_captures is 0
959
+ assert_equal "(\\d+)stuff", a_segment.build_pattern('stuff')
960
+ end
961
+
962
+ def test_build_pattern_non_optional_with_captures
963
+ # Non optional
964
+ a_segment = ROUTING::DynamicSegment.new
965
+ a_segment.regexp = /(\d+)(.*?)/ #number_of_captures is 2
966
+ assert_equal "((\\d+)(.*?))stuff", a_segment.build_pattern('stuff')
967
+ end
968
+
969
+ def test_optionality_implied
970
+ a_segment = ROUTING::DynamicSegment.new
971
+ a_segment.key = :id
972
+ assert a_segment.optionality_implied?
973
+
974
+ a_segment.key = :action
975
+ assert a_segment.optionality_implied?
976
+ end
977
+
978
+ def test_modifiers_must_be_handled_sensibly
979
+ a_segment = ROUTING::DynamicSegment.new
980
+ a_segment.regexp = /david|jamis/i
981
+ assert_equal "((?i-mx:david|jamis))stuff", a_segment.build_pattern('stuff')
982
+ a_segment.regexp = /david|jamis/x
983
+ assert_equal "((?x-mi:david|jamis))stuff", a_segment.build_pattern('stuff')
984
+ a_segment.regexp = /david|jamis/
985
+ assert_equal "(david|jamis)stuff", a_segment.build_pattern('stuff')
986
+ end
987
+ end
988
+
989
+ class ControllerSegmentTest < Test::Unit::TestCase
990
+
991
+ def test_regexp_should_only_match_possible_controllers
992
+ ActionController::Routing.with_controllers %w(admin/accounts admin/users account pages) do
993
+ cs = ROUTING::ControllerSegment.new :controller
994
+ regexp = %r{\A#{cs.regexp_chunk}\Z}
995
+
996
+ ActionController::Routing.possible_controllers.each do |name|
997
+ assert_match regexp, name
998
+ assert_no_match regexp, "#{name}_fake"
999
+
1000
+ match = regexp.match name
1001
+ assert_equal name, match[1]
1002
+ end
1003
+ end
1004
+ end
1005
+
1006
+ end
1007
+
1008
+ uses_mocha 'RouteTest' do
1009
+
1010
+ class MockController
1011
+ attr_accessor :routes
1012
+
1013
+ def initialize(routes)
1014
+ self.routes = routes
1015
+ end
1016
+
1017
+ def url_for(options)
1018
+ only_path = options.delete(:only_path)
1019
+
1020
+ port = options.delete(:port) || 80
1021
+ port_string = port == 80 ? '' : ":#{port}"
1022
+
1023
+ host = options.delete(:host) || "named.route.test"
1024
+ anchor = "##{options.delete(:anchor)}" if options.key?(:anchor)
1025
+
1026
+ path = routes.generate(options)
1027
+
1028
+ only_path ? "#{path}#{anchor}" : "http://#{host}#{port_string}#{path}#{anchor}"
1029
+ end
1030
+
1031
+ def request
1032
+ @request ||= MockRequest.new(:host => "named.route.test", :method => :get)
1033
+ end
1034
+
1035
+ def relative_url_root=(value)
1036
+ request.relative_url_root=value
1037
+ end
1038
+ end
1039
+
1040
+ class MockRequest
1041
+ attr_accessor :path, :path_parameters, :host, :subdomains, :domain,
1042
+ :method, :relative_url_root
1043
+
1044
+ def initialize(values={})
1045
+ values.each { |key, value| send("#{key}=", value) }
1046
+ if values[:host]
1047
+ subdomain, self.domain = values[:host].split(/\./, 2)
1048
+ self.subdomains = [subdomain]
1049
+ end
1050
+ end
1051
+
1052
+ def protocol
1053
+ "http://"
1054
+ end
1055
+
1056
+ def host_with_port
1057
+ (subdomains * '.') + '.' + domain
1058
+ end
1059
+ end
1060
+
1061
+ class RouteTest < Test::Unit::TestCase
1062
+
1063
+ def setup
1064
+ @route = ROUTING::Route.new
1065
+ end
1066
+
1067
+ def slash_segment(is_optional = false)
1068
+ returning ROUTING::DividerSegment.new('/') do |s|
1069
+ s.is_optional = is_optional
1070
+ end
1071
+ end
1072
+
1073
+ def default_route
1074
+ unless defined?(@default_route)
1075
+ @default_route = ROUTING::Route.new
1076
+
1077
+ @default_route.segments << (s = ROUTING::StaticSegment.new)
1078
+ s.value = '/'
1079
+ s.raw = true
1080
+
1081
+ @default_route.segments << (s = ROUTING::DynamicSegment.new)
1082
+ s.key = :controller
1083
+
1084
+ @default_route.segments << slash_segment(:optional)
1085
+ @default_route.segments << (s = ROUTING::DynamicSegment.new)
1086
+ s.key = :action
1087
+ s.default = 'index'
1088
+ s.is_optional = true
1089
+
1090
+ @default_route.segments << slash_segment(:optional)
1091
+ @default_route.segments << (s = ROUTING::DynamicSegment.new)
1092
+ s.key = :id
1093
+ s.is_optional = true
1094
+
1095
+ @default_route.segments << slash_segment(:optional)
1096
+ end
1097
+ @default_route
1098
+ end
1099
+
1100
+ def test_default_route_recognition
1101
+ expected = {:controller => 'accounts', :action => 'show', :id => '10'}
1102
+ assert_equal expected, default_route.recognize('/accounts/show/10')
1103
+ assert_equal expected, default_route.recognize('/accounts/show/10/')
1104
+
1105
+ expected[:id] = 'jamis'
1106
+ assert_equal expected, default_route.recognize('/accounts/show/jamis/')
1107
+
1108
+ expected.delete :id
1109
+ assert_equal expected, default_route.recognize('/accounts/show')
1110
+ assert_equal expected, default_route.recognize('/accounts/show/')
1111
+
1112
+ expected[:action] = 'index'
1113
+ assert_equal expected, default_route.recognize('/accounts/')
1114
+ assert_equal expected, default_route.recognize('/accounts')
1115
+
1116
+ assert_equal nil, default_route.recognize('/')
1117
+ assert_equal nil, default_route.recognize('/accounts/how/goood/it/is/to/be/free')
1118
+ end
1119
+
1120
+ def test_default_route_should_omit_default_action
1121
+ o = {:controller => 'accounts', :action => 'index'}
1122
+ assert_equal '/accounts', default_route.generate(o, o, {})
1123
+ end
1124
+
1125
+ def test_default_route_should_include_default_action_when_id_present
1126
+ o = {:controller => 'accounts', :action => 'index', :id => '20'}
1127
+ assert_equal '/accounts/index/20', default_route.generate(o, o, {})
1128
+ end
1129
+
1130
+ def test_default_route_should_work_with_action_but_no_id
1131
+ o = {:controller => 'accounts', :action => 'list_all'}
1132
+ assert_equal '/accounts/list_all', default_route.generate(o, o, {})
1133
+ end
1134
+
1135
+ def test_default_route_should_uri_escape_pluses
1136
+ expected = { :controller => 'accounts', :action => 'show', :id => 'hello world' }
1137
+ assert_equal expected, default_route.recognize('/accounts/show/hello world')
1138
+ assert_equal expected, default_route.recognize('/accounts/show/hello%20world')
1139
+ assert_equal '/accounts/show/hello%20world', default_route.generate(expected, expected, {})
1140
+
1141
+ expected[:id] = 'hello+world'
1142
+ assert_equal expected, default_route.recognize('/accounts/show/hello+world')
1143
+ assert_equal expected, default_route.recognize('/accounts/show/hello%2Bworld')
1144
+ assert_equal '/accounts/show/hello+world', default_route.generate(expected, expected, {})
1145
+ end
1146
+
1147
+ def test_matches_controller_and_action
1148
+ # requirement_for should only be called for the action and controller _once_
1149
+ @route.expects(:requirement_for).with(:controller).times(1).returns('pages')
1150
+ @route.expects(:requirement_for).with(:action).times(1).returns('show')
1151
+
1152
+ @route.requirements = {:controller => 'pages', :action => 'show'}
1153
+ assert @route.matches_controller_and_action?('pages', 'show')
1154
+ assert !@route.matches_controller_and_action?('not_pages', 'show')
1155
+ assert !@route.matches_controller_and_action?('pages', 'not_show')
1156
+ end
1157
+
1158
+ def test_parameter_shell
1159
+ page_url = ROUTING::Route.new
1160
+ page_url.requirements = {:controller => 'pages', :action => 'show', :id => /\d+/}
1161
+ assert_equal({:controller => 'pages', :action => 'show'}, page_url.parameter_shell)
1162
+ end
1163
+
1164
+ def test_defaults
1165
+ route = ROUTING::RouteBuilder.new.build '/users/:id.:format', :controller => "users", :action => "show", :format => "html"
1166
+ assert_equal(
1167
+ { :controller => "users", :action => "show", :format => "html" },
1168
+ route.defaults)
1169
+ end
1170
+
1171
+ def test_builder_complains_without_controller
1172
+ assert_raises(ArgumentError) do
1173
+ ROUTING::RouteBuilder.new.build '/contact', :contoller => "contact", :action => "index"
1174
+ end
1175
+ end
1176
+
1177
+ def test_significant_keys_for_default_route
1178
+ keys = default_route.significant_keys.sort_by {|k| k.to_s }
1179
+ assert_equal [:action, :controller, :id], keys
1180
+ end
1181
+
1182
+ def test_significant_keys
1183
+ user_url = ROUTING::Route.new
1184
+ user_url.segments << (s = ROUTING::StaticSegment.new)
1185
+ s.value = '/'
1186
+ s.raw = true
1187
+
1188
+ user_url.segments << (s = ROUTING::StaticSegment.new)
1189
+ s.value = 'user'
1190
+
1191
+ user_url.segments << (s = ROUTING::StaticSegment.new)
1192
+ s.value = '/'
1193
+ s.raw = true
1194
+ s.is_optional = true
1195
+
1196
+ user_url.segments << (s = ROUTING::DynamicSegment.new)
1197
+ s.key = :user
1198
+
1199
+ user_url.segments << (s = ROUTING::StaticSegment.new)
1200
+ s.value = '/'
1201
+ s.raw = true
1202
+ s.is_optional = true
1203
+
1204
+ user_url.requirements = {:controller => 'users', :action => 'show'}
1205
+
1206
+ keys = user_url.significant_keys.sort_by { |k| k.to_s }
1207
+ assert_equal [:action, :controller, :user], keys
1208
+ end
1209
+
1210
+ def test_build_empty_query_string
1211
+ assert_equal '', @route.build_query_string({})
1212
+ end
1213
+
1214
+ def test_build_query_string_with_nil_value
1215
+ assert_equal '', @route.build_query_string({:x => nil})
1216
+ end
1217
+
1218
+ def test_simple_build_query_string
1219
+ assert_equal '?x=1&y=2', order_query_string(@route.build_query_string(:x => '1', :y => '2'))
1220
+ end
1221
+
1222
+ def test_convert_ints_build_query_string
1223
+ assert_equal '?x=1&y=2', order_query_string(@route.build_query_string(:x => 1, :y => 2))
1224
+ end
1225
+
1226
+ def test_escape_spaces_build_query_string
1227
+ assert_equal '?x=hello+world&y=goodbye+world', order_query_string(@route.build_query_string(:x => 'hello world', :y => 'goodbye world'))
1228
+ end
1229
+
1230
+ def test_expand_array_build_query_string
1231
+ assert_equal '?x%5B%5D=1&x%5B%5D=2', order_query_string(@route.build_query_string(:x => [1, 2]))
1232
+ end
1233
+
1234
+ def test_escape_spaces_build_query_string_selected_keys
1235
+ assert_equal '?x=hello+world', order_query_string(@route.build_query_string({:x => 'hello world', :y => 'goodbye world'}, [:x]))
1236
+ end
1237
+
1238
+ private
1239
+ def order_query_string(qs)
1240
+ '?' + qs[1..-1].split('&').sort.join('&')
1241
+ end
1242
+ end
1243
+
1244
+ end # uses_mocha
1245
+
1246
+ class RouteBuilderTest < Test::Unit::TestCase
1247
+
1248
+ def builder
1249
+ @builder ||= ROUTING::RouteBuilder.new
1250
+ end
1251
+
1252
+ def build(path, options)
1253
+ builder.build(path, options)
1254
+ end
1255
+
1256
+ def test_options_should_not_be_modified
1257
+ requirements1 = { :id => /\w+/, :controller => /(?:[a-z](?:-?[a-z]+)*)/ }
1258
+ requirements2 = requirements1.dup
1259
+
1260
+ assert_equal requirements1, requirements2
1261
+
1262
+ with_options(:controller => 'folder',
1263
+ :requirements => requirements2) do |m|
1264
+ m.build 'folders/new', :action => 'new'
1265
+ end
1266
+
1267
+ assert_equal requirements1, requirements2
1268
+ end
1269
+
1270
+ def test_segment_for_static
1271
+ segment, rest = builder.segment_for 'ulysses'
1272
+ assert_equal '', rest
1273
+ assert_kind_of ROUTING::StaticSegment, segment
1274
+ assert_equal 'ulysses', segment.value
1275
+ end
1276
+
1277
+ def test_segment_for_action
1278
+ segment, rest = builder.segment_for ':action'
1279
+ assert_equal '', rest
1280
+ assert_kind_of ROUTING::DynamicSegment, segment
1281
+ assert_equal :action, segment.key
1282
+ assert_equal 'index', segment.default
1283
+ end
1284
+
1285
+ def test_segment_for_dynamic
1286
+ segment, rest = builder.segment_for ':login'
1287
+ assert_equal '', rest
1288
+ assert_kind_of ROUTING::DynamicSegment, segment
1289
+ assert_equal :login, segment.key
1290
+ assert_equal nil, segment.default
1291
+ assert ! segment.optional?
1292
+ end
1293
+
1294
+ def test_segment_for_with_rest
1295
+ segment, rest = builder.segment_for ':login/:action'
1296
+ assert_equal :login, segment.key
1297
+ assert_equal '/:action', rest
1298
+ segment, rest = builder.segment_for rest
1299
+ assert_equal '/', segment.value
1300
+ assert_equal ':action', rest
1301
+ segment, rest = builder.segment_for rest
1302
+ assert_equal :action, segment.key
1303
+ assert_equal '', rest
1304
+ end
1305
+
1306
+ def test_segments_for
1307
+ segments = builder.segments_for_route_path '/:controller/:action/:id'
1308
+
1309
+ assert_kind_of ROUTING::DividerSegment, segments[0]
1310
+ assert_equal '/', segments[2].value
1311
+
1312
+ assert_kind_of ROUTING::DynamicSegment, segments[1]
1313
+ assert_equal :controller, segments[1].key
1314
+
1315
+ assert_kind_of ROUTING::DividerSegment, segments[2]
1316
+ assert_equal '/', segments[2].value
1317
+
1318
+ assert_kind_of ROUTING::DynamicSegment, segments[3]
1319
+ assert_equal :action, segments[3].key
1320
+
1321
+ assert_kind_of ROUTING::DividerSegment, segments[4]
1322
+ assert_equal '/', segments[4].value
1323
+
1324
+ assert_kind_of ROUTING::DynamicSegment, segments[5]
1325
+ assert_equal :id, segments[5].key
1326
+ end
1327
+
1328
+ def test_segment_for_action
1329
+ s, r = builder.segment_for(':action/something/else')
1330
+ assert_equal '/something/else', r
1331
+ assert_equal :action, s.key
1332
+ end
1333
+
1334
+ def test_action_default_should_not_trigger_on_prefix
1335
+ s, r = builder.segment_for ':action_name/something/else'
1336
+ assert_equal '/something/else', r
1337
+ assert_equal :action_name, s.key
1338
+ assert_equal nil, s.default
1339
+ end
1340
+
1341
+ def test_divide_route_options
1342
+ segments = builder.segments_for_route_path '/cars/:action/:person/:car/'
1343
+ defaults, requirements = builder.divide_route_options(segments,
1344
+ :action => 'buy', :person => /\w+/, :car => /\w+/,
1345
+ :defaults => {:person => nil, :car => nil}
1346
+ )
1347
+
1348
+ assert_equal({:action => 'buy', :person => nil, :car => nil}, defaults)
1349
+ assert_equal({:person => /\w+/, :car => /\w+/}, requirements)
1350
+ end
1351
+
1352
+ def test_assign_route_options
1353
+ segments = builder.segments_for_route_path '/cars/:action/:person/:car/'
1354
+ defaults = {:action => 'buy', :person => nil, :car => nil}
1355
+ requirements = {:person => /\w+/, :car => /\w+/}
1356
+
1357
+ route_requirements = builder.assign_route_options(segments, defaults, requirements)
1358
+ assert_equal({}, route_requirements)
1359
+
1360
+ assert_equal :action, segments[3].key
1361
+ assert_equal 'buy', segments[3].default
1362
+
1363
+ assert_equal :person, segments[5].key
1364
+ assert_equal %r/\w+/, segments[5].regexp
1365
+ assert segments[5].optional?
1366
+
1367
+ assert_equal :car, segments[7].key
1368
+ assert_equal %r/\w+/, segments[7].regexp
1369
+ assert segments[7].optional?
1370
+ end
1371
+
1372
+ def test_assign_route_options_with_anchor_chars
1373
+ segments = builder.segments_for_route_path '/cars/:action/:person/:car/'
1374
+ defaults = {:action => 'buy', :person => nil, :car => nil}
1375
+ requirements = {:person => /\w+/, :car => /^\w+$/}
1376
+
1377
+ assert_raises ArgumentError do
1378
+ route_requirements = builder.assign_route_options(segments, defaults, requirements)
1379
+ end
1380
+
1381
+ requirements[:car] = /[^\/]+/
1382
+ route_requirements = builder.assign_route_options(segments, defaults, requirements)
1383
+ end
1384
+
1385
+
1386
+ def test_optional_segments_preceding_required_segments
1387
+ segments = builder.segments_for_route_path '/cars/:action/:person/:car/'
1388
+ defaults = {:action => 'buy', :person => nil, :car => "model-t"}
1389
+ assert builder.assign_route_options(segments, defaults, {}).empty?
1390
+
1391
+ 0.upto(1) { |i| assert !segments[i].optional?, "segment #{i} is optional and it shouldn't be" }
1392
+ assert segments[2].optional?
1393
+
1394
+ assert_equal nil, builder.warn_output # should only warn on the :person segment
1395
+ end
1396
+
1397
+ def test_segmentation_of_dot_path
1398
+ segments = builder.segments_for_route_path '/books/:action.rss'
1399
+ assert builder.assign_route_options(segments, {}, {}).empty?
1400
+ assert_equal 6, segments.length # "/", "books", "/", ":action", ".", "rss"
1401
+ assert !segments.any? { |seg| seg.optional? }
1402
+ end
1403
+
1404
+ def test_segmentation_of_dynamic_dot_path
1405
+ segments = builder.segments_for_route_path '/books/:action.:format'
1406
+ assert builder.assign_route_options(segments, {}, {}).empty?
1407
+ assert_equal 6, segments.length # "/", "books", "/", ":action", ".", ":format"
1408
+ assert !segments.any? { |seg| seg.optional? }
1409
+ assert_kind_of ROUTING::DynamicSegment, segments.last
1410
+ end
1411
+
1412
+ def test_assignment_of_default_options
1413
+ segments = builder.segments_for_route_path '/:controller/:action/:id/'
1414
+ action, id = segments[-4], segments[-2]
1415
+
1416
+ assert_equal :action, action.key
1417
+ assert_equal :id, id.key
1418
+ assert ! action.optional?
1419
+ assert ! id.optional?
1420
+
1421
+ builder.assign_default_route_options(segments)
1422
+
1423
+ assert_equal 'index', action.default
1424
+ assert action.optional?
1425
+ assert id.optional?
1426
+ end
1427
+
1428
+ def test_assignment_of_default_options_respects_existing_defaults
1429
+ segments = builder.segments_for_route_path '/:controller/:action/:id/'
1430
+ action, id = segments[-4], segments[-2]
1431
+
1432
+ assert_equal :action, action.key
1433
+ assert_equal :id, id.key
1434
+ action.default = 'show'
1435
+ action.is_optional = true
1436
+
1437
+ id.default = 'Welcome'
1438
+ id.is_optional = true
1439
+
1440
+ builder.assign_default_route_options(segments)
1441
+
1442
+ assert_equal 'show', action.default
1443
+ assert action.optional?
1444
+ assert_equal 'Welcome', id.default
1445
+ assert id.optional?
1446
+ end
1447
+
1448
+ def test_assignment_of_default_options_respects_regexps
1449
+ segments = builder.segments_for_route_path '/:controller/:action/:id/'
1450
+ action = segments[-4]
1451
+
1452
+ assert_equal :action, action.key
1453
+ action.regexp = /show|in/ # Use 'in' to check partial matches
1454
+
1455
+ builder.assign_default_route_options(segments)
1456
+
1457
+ assert_equal nil, action.default
1458
+ assert ! action.optional?
1459
+ end
1460
+
1461
+ def test_assignment_of_is_optional_when_default
1462
+ segments = builder.segments_for_route_path '/books/:action.rss'
1463
+ assert_equal segments[3].key, :action
1464
+ segments[3].default = 'changes'
1465
+ builder.ensure_required_segments(segments)
1466
+ assert ! segments[3].optional?
1467
+ end
1468
+
1469
+ def test_is_optional_is_assigned_to_default_segments
1470
+ segments = builder.segments_for_route_path '/books/:action'
1471
+ builder.assign_route_options(segments, {:action => 'index'}, {})
1472
+
1473
+ assert_equal segments[3].key, :action
1474
+ assert segments[3].optional?
1475
+ assert_kind_of ROUTING::DividerSegment, segments[2]
1476
+ assert segments[2].optional?
1477
+ end
1478
+
1479
+ # XXX is optional not being set right?
1480
+ # /blah/:defaulted_segment <-- is the second slash optional? it should be.
1481
+
1482
+ def test_route_build
1483
+ ActionController::Routing.with_controllers %w(users pages) do
1484
+ r = builder.build '/:controller/:action/:id/', :action => nil
1485
+
1486
+ [0, 2, 4].each do |i|
1487
+ assert_kind_of ROUTING::DividerSegment, r.segments[i]
1488
+ assert_equal '/', r.segments[i].value
1489
+ assert r.segments[i].optional? if i > 1
1490
+ end
1491
+
1492
+ assert_kind_of ROUTING::DynamicSegment, r.segments[1]
1493
+ assert_equal :controller, r.segments[1].key
1494
+ assert_equal nil, r.segments[1].default
1495
+
1496
+ assert_kind_of ROUTING::DynamicSegment, r.segments[3]
1497
+ assert_equal :action, r.segments[3].key
1498
+ assert_equal 'index', r.segments[3].default
1499
+
1500
+ assert_kind_of ROUTING::DynamicSegment, r.segments[5]
1501
+ assert_equal :id, r.segments[5].key
1502
+ assert r.segments[5].optional?
1503
+ end
1504
+ end
1505
+
1506
+ def test_slashes_are_implied
1507
+ routes = [
1508
+ builder.build('/:controller/:action/:id/', :action => nil),
1509
+ builder.build('/:controller/:action/:id', :action => nil),
1510
+ builder.build(':controller/:action/:id', :action => nil),
1511
+ builder.build('/:controller/:action/:id/', :action => nil)
1512
+ ]
1513
+ expected = routes.first.segments.length
1514
+ routes.each_with_index do |route, i|
1515
+ found = route.segments.length
1516
+ assert_equal expected, found, "Route #{i + 1} has #{found} segments, expected #{expected}"
1517
+ end
1518
+ end
1519
+
1520
+ end
1521
+
1522
+
1523
+
1524
+
1525
+ class RouteSetTest < Test::Unit::TestCase
1526
+
1527
+ def set
1528
+ @set ||= ROUTING::RouteSet.new
1529
+ end
1530
+
1531
+ def request
1532
+ @request ||= MockRequest.new(:host => "named.routes.test", :method => :get)
1533
+ end
1534
+
1535
+ def test_generate_extras
1536
+ set.draw { |m| m.connect ':controller/:action/:id' }
1537
+ path, extras = set.generate_extras(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world")
1538
+ assert_equal "/foo/bar/15", path
1539
+ assert_equal %w(that this), extras.map(&:to_s).sort
1540
+ end
1541
+
1542
+ def test_extra_keys
1543
+ set.draw { |m| m.connect ':controller/:action/:id' }
1544
+ extras = set.extra_keys(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world")
1545
+ assert_equal %w(that this), extras.map(&:to_s).sort
1546
+ end
1547
+
1548
+ def test_generate_extras_not_first
1549
+ set.draw do |map|
1550
+ map.connect ':controller/:action/:id.:format'
1551
+ map.connect ':controller/:action/:id'
1552
+ end
1553
+ path, extras = set.generate_extras(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world")
1554
+ assert_equal "/foo/bar/15", path
1555
+ assert_equal %w(that this), extras.map(&:to_s).sort
1556
+ end
1557
+
1558
+ def test_generate_not_first
1559
+ set.draw do |map|
1560
+ map.connect ':controller/:action/:id.:format'
1561
+ map.connect ':controller/:action/:id'
1562
+ end
1563
+ assert_equal "/foo/bar/15?this=hello", set.generate(:controller => "foo", :action => "bar", :id => 15, :this => "hello")
1564
+ end
1565
+
1566
+ def test_extra_keys_not_first
1567
+ set.draw do |map|
1568
+ map.connect ':controller/:action/:id.:format'
1569
+ map.connect ':controller/:action/:id'
1570
+ end
1571
+ extras = set.extra_keys(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world")
1572
+ assert_equal %w(that this), extras.map(&:to_s).sort
1573
+ end
1574
+
1575
+ def test_draw
1576
+ assert_equal 0, set.routes.size
1577
+ set.draw do |map|
1578
+ map.connect '/hello/world', :controller => 'a', :action => 'b'
1579
+ end
1580
+ assert_equal 1, set.routes.size
1581
+ end
1582
+
1583
+ def test_named_draw
1584
+ assert_equal 0, set.routes.size
1585
+ set.draw do |map|
1586
+ map.hello '/hello/world', :controller => 'a', :action => 'b'
1587
+ end
1588
+ assert_equal 1, set.routes.size
1589
+ assert_equal set.routes.first, set.named_routes[:hello]
1590
+ end
1591
+
1592
+ def test_later_named_routes_take_precedence
1593
+ set.draw do |map|
1594
+ map.hello '/hello/world', :controller => 'a', :action => 'b'
1595
+ map.hello '/hello', :controller => 'a', :action => 'b'
1596
+ end
1597
+ assert_equal set.routes.last, set.named_routes[:hello]
1598
+ end
1599
+
1600
+ def setup_named_route_test
1601
+ set.draw do |map|
1602
+ map.show '/people/:id', :controller => 'people', :action => 'show'
1603
+ map.index '/people', :controller => 'people', :action => 'index'
1604
+ map.multi '/people/go/:foo/:bar/joe/:id', :controller => 'people', :action => 'multi'
1605
+ map.users '/admin/users', :controller => 'admin/users', :action => 'index'
1606
+ end
1607
+
1608
+ klass = Class.new(MockController)
1609
+ set.install_helpers(klass)
1610
+ klass.new(set)
1611
+ end
1612
+
1613
+ def test_named_route_hash_access_method
1614
+ controller = setup_named_route_test
1615
+
1616
+ assert_equal(
1617
+ { :controller => 'people', :action => 'show', :id => 5, :use_route => :show, :only_path => false },
1618
+ controller.send(:hash_for_show_url, :id => 5))
1619
+
1620
+ assert_equal(
1621
+ { :controller => 'people', :action => 'index', :use_route => :index, :only_path => false },
1622
+ controller.send(:hash_for_index_url))
1623
+
1624
+ assert_equal(
1625
+ { :controller => 'people', :action => 'show', :id => 5, :use_route => :show, :only_path => true },
1626
+ controller.send(:hash_for_show_path, :id => 5)
1627
+ )
1628
+ end
1629
+
1630
+ def test_named_route_url_method
1631
+ controller = setup_named_route_test
1632
+
1633
+ assert_equal "http://named.route.test/people/5", controller.send(:show_url, :id => 5)
1634
+ assert_equal "/people/5", controller.send(:show_path, :id => 5)
1635
+
1636
+ assert_equal "http://named.route.test/people", controller.send(:index_url)
1637
+ assert_equal "/people", controller.send(:index_path)
1638
+
1639
+ assert_equal "http://named.route.test/admin/users", controller.send(:users_url)
1640
+ assert_equal '/admin/users', controller.send(:users_path)
1641
+ assert_equal '/admin/users', set.generate(controller.send(:hash_for_users_url), {:controller => 'users', :action => 'index'})
1642
+ end
1643
+
1644
+ def test_named_route_url_method_with_anchor
1645
+ controller = setup_named_route_test
1646
+
1647
+ assert_equal "http://named.route.test/people/5#location", controller.send(:show_url, :id => 5, :anchor => 'location')
1648
+ assert_equal "/people/5#location", controller.send(:show_path, :id => 5, :anchor => 'location')
1649
+
1650
+ assert_equal "http://named.route.test/people#location", controller.send(:index_url, :anchor => 'location')
1651
+ assert_equal "/people#location", controller.send(:index_path, :anchor => 'location')
1652
+
1653
+ assert_equal "http://named.route.test/admin/users#location", controller.send(:users_url, :anchor => 'location')
1654
+ assert_equal '/admin/users#location', controller.send(:users_path, :anchor => 'location')
1655
+
1656
+ assert_equal "http://named.route.test/people/go/7/hello/joe/5#location",
1657
+ controller.send(:multi_url, 7, "hello", 5, :anchor => 'location')
1658
+
1659
+ assert_equal "http://named.route.test/people/go/7/hello/joe/5?baz=bar#location",
1660
+ controller.send(:multi_url, 7, "hello", 5, :baz => "bar", :anchor => 'location')
1661
+
1662
+ assert_equal "http://named.route.test/people?baz=bar#location",
1663
+ controller.send(:index_url, :baz => "bar", :anchor => 'location')
1664
+ end
1665
+
1666
+ def test_named_route_url_method_with_port
1667
+ controller = setup_named_route_test
1668
+ assert_equal "http://named.route.test:8080/people/5", controller.send(:show_url, 5, :port=>8080)
1669
+ end
1670
+
1671
+ def test_named_route_url_method_with_host
1672
+ controller = setup_named_route_test
1673
+ assert_equal "http://some.example.com/people/5", controller.send(:show_url, 5, :host=>"some.example.com")
1674
+ end
1675
+
1676
+
1677
+ def test_named_route_url_method_with_ordered_parameters
1678
+ controller = setup_named_route_test
1679
+ assert_equal "http://named.route.test/people/go/7/hello/joe/5",
1680
+ controller.send(:multi_url, 7, "hello", 5)
1681
+ end
1682
+
1683
+ def test_named_route_url_method_with_ordered_parameters_and_hash
1684
+ controller = setup_named_route_test
1685
+ assert_equal "http://named.route.test/people/go/7/hello/joe/5?baz=bar",
1686
+ controller.send(:multi_url, 7, "hello", 5, :baz => "bar")
1687
+ end
1688
+
1689
+ def test_named_route_url_method_with_no_positional_arguments
1690
+ controller = setup_named_route_test
1691
+ assert_equal "http://named.route.test/people?baz=bar",
1692
+ controller.send(:index_url, :baz => "bar")
1693
+ end
1694
+
1695
+ def test_draw_default_route
1696
+ ActionController::Routing.with_controllers(['users']) do
1697
+ set.draw do |map|
1698
+ map.connect '/:controller/:action/:id'
1699
+ end
1700
+
1701
+ assert_equal 1, set.routes.size
1702
+ route = set.routes.first
1703
+
1704
+ assert route.segments.last.optional?
1705
+
1706
+ assert_equal '/users/show/10', set.generate(:controller => 'users', :action => 'show', :id => 10)
1707
+ assert_equal '/users/index/10', set.generate(:controller => 'users', :id => 10)
1708
+
1709
+ assert_equal({:controller => 'users', :action => 'index', :id => '10'}, set.recognize_path('/users/index/10'))
1710
+ assert_equal({:controller => 'users', :action => 'index', :id => '10'}, set.recognize_path('/users/index/10/'))
1711
+ end
1712
+ end
1713
+
1714
+ def test_draw_default_route_with_default_controller
1715
+ ActionController::Routing.with_controllers(['users']) do
1716
+ set.draw do |map|
1717
+ map.connect '/:controller/:action/:id', :controller => 'users'
1718
+ end
1719
+ assert_equal({:controller => 'users', :action => 'index'}, set.recognize_path('/'))
1720
+ end
1721
+ end
1722
+
1723
+ def test_route_with_parameter_shell
1724
+ ActionController::Routing.with_controllers(['users', 'pages']) do
1725
+ set.draw do |map|
1726
+ map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\d+/
1727
+ map.connect '/:controller/:action/:id'
1728
+ end
1729
+
1730
+ assert_equal({:controller => 'pages', :action => 'index'}, set.recognize_path('/pages'))
1731
+ assert_equal({:controller => 'pages', :action => 'index'}, set.recognize_path('/pages/index'))
1732
+ assert_equal({:controller => 'pages', :action => 'list'}, set.recognize_path('/pages/list'))
1733
+
1734
+ assert_equal({:controller => 'pages', :action => 'show', :id => '10'}, set.recognize_path('/pages/show/10'))
1735
+ assert_equal({:controller => 'pages', :action => 'show', :id => '10'}, set.recognize_path('/page/10'))
1736
+ end
1737
+ end
1738
+
1739
+ def test_route_requirements_with_anchor_chars_are_invalid
1740
+ assert_raises ArgumentError do
1741
+ set.draw do |map|
1742
+ map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /^\d+/
1743
+ end
1744
+ end
1745
+ assert_raises ArgumentError do
1746
+ set.draw do |map|
1747
+ map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\A\d+/
1748
+ end
1749
+ end
1750
+ assert_raises ArgumentError do
1751
+ set.draw do |map|
1752
+ map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\d+$/
1753
+ end
1754
+ end
1755
+ assert_raises ArgumentError do
1756
+ set.draw do |map|
1757
+ map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\d+\Z/
1758
+ end
1759
+ end
1760
+ assert_raises ArgumentError do
1761
+ set.draw do |map|
1762
+ map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\d+\z/
1763
+ end
1764
+ end
1765
+ assert_nothing_raised do
1766
+ set.draw do |map|
1767
+ map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\d+/, :name => /^(david|jamis)/
1768
+ end
1769
+ assert_raises ActionController::RoutingError do
1770
+ set.generate :controller => 'pages', :action => 'show', :id => 10
1771
+ end
1772
+ end
1773
+ end
1774
+
1775
+ def test_non_path_route_requirements_match_all
1776
+ set.draw do |map|
1777
+ map.connect 'page/37s', :controller => 'pages', :action => 'show', :name => /(jamis|david)/
1778
+ end
1779
+ assert_equal '/page/37s', set.generate(:controller => 'pages', :action => 'show', :name => 'jamis')
1780
+ assert_raises ActionController::RoutingError do
1781
+ set.generate(:controller => 'pages', :action => 'show', :name => 'not_jamis')
1782
+ end
1783
+ assert_raises ActionController::RoutingError do
1784
+ set.generate(:controller => 'pages', :action => 'show', :name => 'nor_jamis_and_david')
1785
+ end
1786
+ end
1787
+
1788
+ def test_recognize_with_encoded_id_and_regex
1789
+ set.draw do |map|
1790
+ map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /[a-zA-Z0-9\+]+/
1791
+ end
1792
+
1793
+ assert_equal({:controller => 'pages', :action => 'show', :id => '10'}, set.recognize_path('/page/10'))
1794
+ assert_equal({:controller => 'pages', :action => 'show', :id => 'hello+world'}, set.recognize_path('/page/hello+world'))
1795
+ end
1796
+
1797
+ def test_recognize_with_conditions
1798
+ Object.const_set(:PeopleController, Class.new)
1799
+
1800
+ set.draw do |map|
1801
+ map.with_options(:controller => "people") do |people|
1802
+ people.people "/people", :action => "index", :conditions => { :method => :get }
1803
+ people.connect "/people", :action => "create", :conditions => { :method => :post }
1804
+ people.person "/people/:id", :action => "show", :conditions => { :method => :get }
1805
+ people.connect "/people/:id", :action => "update", :conditions => { :method => :put }
1806
+ people.connect "/people/:id", :action => "destroy", :conditions => { :method => :delete }
1807
+ end
1808
+ end
1809
+
1810
+ request.path = "/people"
1811
+ request.method = :get
1812
+ assert_nothing_raised { set.recognize(request) }
1813
+ assert_equal("index", request.path_parameters[:action])
1814
+
1815
+ request.method = :post
1816
+ assert_nothing_raised { set.recognize(request) }
1817
+ assert_equal("create", request.path_parameters[:action])
1818
+
1819
+ request.method = :put
1820
+ assert_nothing_raised { set.recognize(request) }
1821
+ assert_equal("update", request.path_parameters[:action])
1822
+
1823
+ begin
1824
+ request.method = :bacon
1825
+ set.recognize(request)
1826
+ flunk 'Should have raised NotImplemented'
1827
+ rescue ActionController::NotImplemented => e
1828
+ assert_equal [:get, :post, :put, :delete], e.allowed_methods
1829
+ end
1830
+
1831
+ request.path = "/people/5"
1832
+ request.method = :get
1833
+ assert_nothing_raised { set.recognize(request) }
1834
+ assert_equal("show", request.path_parameters[:action])
1835
+ assert_equal("5", request.path_parameters[:id])
1836
+
1837
+ request.method = :put
1838
+ assert_nothing_raised { set.recognize(request) }
1839
+ assert_equal("update", request.path_parameters[:action])
1840
+ assert_equal("5", request.path_parameters[:id])
1841
+
1842
+ request.method = :delete
1843
+ assert_nothing_raised { set.recognize(request) }
1844
+ assert_equal("destroy", request.path_parameters[:action])
1845
+ assert_equal("5", request.path_parameters[:id])
1846
+
1847
+ begin
1848
+ request.method = :post
1849
+ set.recognize(request)
1850
+ flunk 'Should have raised MethodNotAllowed'
1851
+ rescue ActionController::MethodNotAllowed => e
1852
+ assert_equal [:get, :put, :delete], e.allowed_methods
1853
+ end
1854
+
1855
+ ensure
1856
+ Object.send(:remove_const, :PeopleController)
1857
+ end
1858
+
1859
+ def test_recognize_with_alias_in_conditions
1860
+ Object.const_set(:PeopleController, Class.new)
1861
+
1862
+ set.draw do |map|
1863
+ map.people "/people", :controller => 'people', :action => "index",
1864
+ :conditions => { :method => :get }
1865
+ map.root :people
1866
+ end
1867
+
1868
+ request.path = "/people"
1869
+ request.method = :get
1870
+ assert_nothing_raised { set.recognize(request) }
1871
+ assert_equal("people", request.path_parameters[:controller])
1872
+ assert_equal("index", request.path_parameters[:action])
1873
+
1874
+ request.path = "/"
1875
+ request.method = :get
1876
+ assert_nothing_raised { set.recognize(request) }
1877
+ assert_equal("people", request.path_parameters[:controller])
1878
+ assert_equal("index", request.path_parameters[:action])
1879
+ ensure
1880
+ Object.send(:remove_const, :PeopleController)
1881
+ end
1882
+
1883
+ def test_typo_recognition
1884
+ Object.const_set(:ArticlesController, Class.new)
1885
+
1886
+ set.draw do |map|
1887
+ map.connect 'articles/:year/:month/:day/:title',
1888
+ :controller => 'articles', :action => 'permalink',
1889
+ :year => /\d{4}/, :day => /\d{1,2}/, :month => /\d{1,2}/
1890
+ end
1891
+
1892
+ request.path = "/articles/2005/11/05/a-very-interesting-article"
1893
+ request.method = :get
1894
+ assert_nothing_raised { set.recognize(request) }
1895
+ assert_equal("permalink", request.path_parameters[:action])
1896
+ assert_equal("2005", request.path_parameters[:year])
1897
+ assert_equal("11", request.path_parameters[:month])
1898
+ assert_equal("05", request.path_parameters[:day])
1899
+ assert_equal("a-very-interesting-article", request.path_parameters[:title])
1900
+
1901
+ ensure
1902
+ Object.send(:remove_const, :ArticlesController)
1903
+ end
1904
+
1905
+ def test_routing_traversal_does_not_load_extra_classes
1906
+ assert !Object.const_defined?("Profiler__"), "Profiler should not be loaded"
1907
+ set.draw do |map|
1908
+ map.connect '/profile', :controller => 'profile'
1909
+ end
1910
+
1911
+ request.path = '/profile'
1912
+
1913
+ set.recognize(request) rescue nil
1914
+
1915
+ assert !Object.const_defined?("Profiler__"), "Profiler should not be loaded"
1916
+ end
1917
+
1918
+ def test_recognize_with_conditions_and_format
1919
+ Object.const_set(:PeopleController, Class.new)
1920
+
1921
+ set.draw do |map|
1922
+ map.with_options(:controller => "people") do |people|
1923
+ people.person "/people/:id", :action => "show", :conditions => { :method => :get }
1924
+ people.connect "/people/:id", :action => "update", :conditions => { :method => :put }
1925
+ people.connect "/people/:id.:_format", :action => "show", :conditions => { :method => :get }
1926
+ end
1927
+ end
1928
+
1929
+ request.path = "/people/5"
1930
+ request.method = :get
1931
+ assert_nothing_raised { set.recognize(request) }
1932
+ assert_equal("show", request.path_parameters[:action])
1933
+ assert_equal("5", request.path_parameters[:id])
1934
+
1935
+ request.method = :put
1936
+ assert_nothing_raised { set.recognize(request) }
1937
+ assert_equal("update", request.path_parameters[:action])
1938
+
1939
+ request.path = "/people/5.png"
1940
+ request.method = :get
1941
+ assert_nothing_raised { set.recognize(request) }
1942
+ assert_equal("show", request.path_parameters[:action])
1943
+ assert_equal("5", request.path_parameters[:id])
1944
+ assert_equal("png", request.path_parameters[:_format])
1945
+ ensure
1946
+ Object.send(:remove_const, :PeopleController)
1947
+ end
1948
+
1949
+ def test_generate_with_default_action
1950
+ set.draw do |map|
1951
+ map.connect "/people", :controller => "people"
1952
+ map.connect "/people/list", :controller => "people", :action => "list"
1953
+ end
1954
+
1955
+ url = set.generate(:controller => "people", :action => "list")
1956
+ assert_equal "/people/list", url
1957
+ end
1958
+
1959
+ def test_root_map
1960
+ Object.const_set(:PeopleController, Class.new)
1961
+
1962
+ set.draw { |map| map.root :controller => "people" }
1963
+
1964
+ request.path = ""
1965
+ request.method = :get
1966
+ assert_nothing_raised { set.recognize(request) }
1967
+ assert_equal("people", request.path_parameters[:controller])
1968
+ assert_equal("index", request.path_parameters[:action])
1969
+ ensure
1970
+ Object.send(:remove_const, :PeopleController)
1971
+ end
1972
+
1973
+
1974
+ def test_namespace
1975
+ Object.const_set(:Api, Module.new { |m| m.const_set(:ProductsController, Class.new) })
1976
+
1977
+ set.draw do |map|
1978
+
1979
+ map.namespace 'api' do |api|
1980
+ api.route 'inventory', :controller => "products", :action => 'inventory'
1981
+ end
1982
+
1983
+ end
1984
+
1985
+ request.path = "/api/inventory"
1986
+ request.method = :get
1987
+ assert_nothing_raised { set.recognize(request) }
1988
+ assert_equal("api/products", request.path_parameters[:controller])
1989
+ assert_equal("inventory", request.path_parameters[:action])
1990
+ ensure
1991
+ Object.send(:remove_const, :Api)
1992
+ end
1993
+
1994
+
1995
+ def test_namespaced_root_map
1996
+ Object.const_set(:Api, Module.new { |m| m.const_set(:ProductsController, Class.new) })
1997
+
1998
+ set.draw do |map|
1999
+
2000
+ map.namespace 'api' do |api|
2001
+ api.root :controller => "products"
2002
+ end
2003
+
2004
+ end
2005
+
2006
+ request.path = "/api"
2007
+ request.method = :get
2008
+ assert_nothing_raised { set.recognize(request) }
2009
+ assert_equal("api/products", request.path_parameters[:controller])
2010
+ assert_equal("index", request.path_parameters[:action])
2011
+ ensure
2012
+ Object.send(:remove_const, :Api)
2013
+ end
2014
+
2015
+ def test_namespace_with_path_prefix
2016
+ Object.const_set(:Api, Module.new { |m| m.const_set(:ProductsController, Class.new) })
2017
+
2018
+ set.draw do |map|
2019
+
2020
+ map.namespace 'api', :path_prefix => 'prefix' do |api|
2021
+ api.route 'inventory', :controller => "products", :action => 'inventory'
2022
+ end
2023
+
2024
+ end
2025
+
2026
+ request.path = "/prefix/inventory"
2027
+ request.method = :get
2028
+ assert_nothing_raised { set.recognize(request) }
2029
+ assert_equal("api/products", request.path_parameters[:controller])
2030
+ assert_equal("inventory", request.path_parameters[:action])
2031
+ ensure
2032
+ Object.send(:remove_const, :Api)
2033
+ end
2034
+
2035
+ def test_generate_finds_best_fit
2036
+ set.draw do |map|
2037
+ map.connect "/people", :controller => "people", :action => "index"
2038
+ map.connect "/ws/people", :controller => "people", :action => "index", :ws => true
2039
+ end
2040
+
2041
+ url = set.generate(:controller => "people", :action => "index", :ws => true)
2042
+ assert_equal "/ws/people", url
2043
+ end
2044
+
2045
+ def test_generate_changes_controller_module
2046
+ set.draw { |map| map.connect ':controller/:action/:id' }
2047
+ current = { :controller => "bling/bloop", :action => "bap", :id => 9 }
2048
+ url = set.generate({:controller => "foo/bar", :action => "baz", :id => 7}, current)
2049
+ assert_equal "/foo/bar/baz/7", url
2050
+ end
2051
+
2052
+ def test_id_is_not_impossibly_sticky
2053
+ set.draw do |map|
2054
+ map.connect 'foo/:number', :controller => "people", :action => "index"
2055
+ map.connect ':controller/:action/:id'
2056
+ end
2057
+
2058
+ url = set.generate({:controller => "people", :action => "index", :number => 3},
2059
+ {:controller => "people", :action => "index", :id => "21"})
2060
+ assert_equal "/foo/3", url
2061
+ end
2062
+
2063
+ def test_id_is_sticky_when_it_ought_to_be
2064
+ set.draw do |map|
2065
+ map.connect ':controller/:id/:action'
2066
+ end
2067
+
2068
+ url = set.generate({:action => "destroy"}, {:controller => "people", :action => "show", :id => "7"})
2069
+ assert_equal "/people/7/destroy", url
2070
+ end
2071
+
2072
+ def test_use_static_path_when_possible
2073
+ set.draw do |map|
2074
+ map.connect 'about', :controller => "welcome", :action => "about"
2075
+ map.connect ':controller/:action/:id'
2076
+ end
2077
+
2078
+ url = set.generate({:controller => "welcome", :action => "about"},
2079
+ {:controller => "welcome", :action => "get", :id => "7"})
2080
+ assert_equal "/about", url
2081
+ end
2082
+
2083
+ def test_generate
2084
+ set.draw { |map| map.connect ':controller/:action/:id' }
2085
+
2086
+ args = { :controller => "foo", :action => "bar", :id => "7", :x => "y" }
2087
+ assert_equal "/foo/bar/7?x=y", set.generate(args)
2088
+ assert_equal ["/foo/bar/7", [:x]], set.generate_extras(args)
2089
+ assert_equal [:x], set.extra_keys(args)
2090
+ end
2091
+
2092
+ def test_named_routes_are_never_relative_to_modules
2093
+ set.draw do |map|
2094
+ map.connect "/connection/manage/:action", :controller => 'connection/manage'
2095
+ map.connect "/connection/connection", :controller => "connection/connection"
2096
+ map.family_connection "/connection", :controller => "connection"
2097
+ end
2098
+
2099
+ url = set.generate({:controller => "connection"}, {:controller => 'connection/manage'})
2100
+ assert_equal "/connection/connection", url
2101
+
2102
+ url = set.generate({:use_route => :family_connection, :controller => "connection"}, {:controller => 'connection/manage'})
2103
+ assert_equal "/connection", url
2104
+ end
2105
+
2106
+ def test_action_left_off_when_id_is_recalled
2107
+ set.draw do |map|
2108
+ map.connect ':controller/:action/:id'
2109
+ end
2110
+ assert_equal '/post', set.generate(
2111
+ {:controller => 'post', :action => 'index'},
2112
+ {:controller => 'post', :action => 'show', :id => '10'}
2113
+ )
2114
+ end
2115
+
2116
+ def test_query_params_will_be_shown_when_recalled
2117
+ set.draw do |map|
2118
+ map.connect 'show_post/:parameter', :controller => 'post', :action => 'show'
2119
+ map.connect ':controller/:action/:id'
2120
+ end
2121
+ assert_equal '/post/edit?parameter=1', set.generate(
2122
+ {:action => 'edit', :parameter => 1},
2123
+ {:controller => 'post', :action => 'show', :parameter => 1}
2124
+ )
2125
+ end
2126
+
2127
+ def test_expiry_determination_should_consider_values_with_to_param
2128
+ set.draw { |map| map.connect 'projects/:project_id/:controller/:action' }
2129
+ assert_equal '/projects/1/post/show', set.generate(
2130
+ {:action => 'show', :project_id => 1},
2131
+ {:controller => 'post', :action => 'show', :project_id => '1'})
2132
+ end
2133
+
2134
+ def test_generate_all
2135
+ set.draw do |map|
2136
+ map.connect 'show_post/:id', :controller => 'post', :action => 'show'
2137
+ map.connect ':controller/:action/:id'
2138
+ end
2139
+ all = set.generate(
2140
+ {:action => 'show', :id => 10, :generate_all => true},
2141
+ {:controller => 'post', :action => 'show'}
2142
+ )
2143
+ assert_equal 2, all.length
2144
+ assert_equal '/show_post/10', all.first
2145
+ assert_equal '/post/show/10', all.last
2146
+ end
2147
+
2148
+ def test_named_route_in_nested_resource
2149
+ set.draw do |map|
2150
+ map.resources :projects do |project|
2151
+ project.milestones 'milestones', :controller => 'milestones', :action => 'index'
2152
+ end
2153
+ end
2154
+
2155
+ request.path = "/projects/1/milestones"
2156
+ request.method = :get
2157
+ assert_nothing_raised { set.recognize(request) }
2158
+ assert_equal("milestones", request.path_parameters[:controller])
2159
+ assert_equal("index", request.path_parameters[:action])
2160
+ end
2161
+
2162
+ def test_setting_root_in_namespace_using_symbol
2163
+ assert_nothing_raised do
2164
+ set.draw do |map|
2165
+ map.namespace :admin do |admin|
2166
+ admin.root :controller => 'home'
2167
+ end
2168
+ end
2169
+ end
2170
+ end
2171
+
2172
+ def test_setting_root_in_namespace_using_string
2173
+ assert_nothing_raised do
2174
+ set.draw do |map|
2175
+ map.namespace 'admin' do |admin|
2176
+ admin.root :controller => 'home'
2177
+ end
2178
+ end
2179
+ end
2180
+ end
2181
+
2182
+ def test_route_requirements_with_unsupported_regexp_options_must_error
2183
+ assert_raises ArgumentError do
2184
+ set.draw do |map|
2185
+ map.connect 'page/:name', :controller => 'pages',
2186
+ :action => 'show',
2187
+ :requirements => {:name => /(david|jamis)/m}
2188
+ end
2189
+ end
2190
+ end
2191
+
2192
+ def test_route_requirements_with_supported_options_must_not_error
2193
+ assert_nothing_raised do
2194
+ set.draw do |map|
2195
+ map.connect 'page/:name', :controller => 'pages',
2196
+ :action => 'show',
2197
+ :requirements => {:name => /(david|jamis)/i}
2198
+ end
2199
+ end
2200
+ assert_nothing_raised do
2201
+ set.draw do |map|
2202
+ map.connect 'page/:name', :controller => 'pages',
2203
+ :action => 'show',
2204
+ :requirements => {:name => / # Desperately overcommented regexp
2205
+ ( #Either
2206
+ david #The Creator
2207
+ | #Or
2208
+ jamis #The Deployer
2209
+ )/x}
2210
+ end
2211
+ end
2212
+ end
2213
+
2214
+ def test_route_requirement_recognize_with_ignore_case
2215
+ set.draw do |map|
2216
+ map.connect 'page/:name', :controller => 'pages',
2217
+ :action => 'show',
2218
+ :requirements => {:name => /(david|jamis)/i}
2219
+ end
2220
+ assert_equal({:controller => 'pages', :action => 'show', :name => 'jamis'}, set.recognize_path('/page/jamis'))
2221
+ assert_raises ActionController::RoutingError do
2222
+ set.recognize_path('/page/davidjamis')
2223
+ end
2224
+ assert_equal({:controller => 'pages', :action => 'show', :name => 'DAVID'}, set.recognize_path('/page/DAVID'))
2225
+ end
2226
+
2227
+ def test_route_requirement_generate_with_ignore_case
2228
+ set.draw do |map|
2229
+ map.connect 'page/:name', :controller => 'pages',
2230
+ :action => 'show',
2231
+ :requirements => {:name => /(david|jamis)/i}
2232
+ end
2233
+ url = set.generate({:controller => 'pages', :action => 'show', :name => 'david'})
2234
+ assert_equal "/page/david", url
2235
+ assert_raises ActionController::RoutingError do
2236
+ url = set.generate({:controller => 'pages', :action => 'show', :name => 'davidjamis'})
2237
+ end
2238
+ url = set.generate({:controller => 'pages', :action => 'show', :name => 'JAMIS'})
2239
+ assert_equal "/page/JAMIS", url
2240
+ end
2241
+
2242
+ def test_route_requirement_recognize_with_extended_syntax
2243
+ set.draw do |map|
2244
+ map.connect 'page/:name', :controller => 'pages',
2245
+ :action => 'show',
2246
+ :requirements => {:name => / # Desperately overcommented regexp
2247
+ ( #Either
2248
+ david #The Creator
2249
+ | #Or
2250
+ jamis #The Deployer
2251
+ )/x}
2252
+ end
2253
+ assert_equal({:controller => 'pages', :action => 'show', :name => 'jamis'}, set.recognize_path('/page/jamis'))
2254
+ assert_equal({:controller => 'pages', :action => 'show', :name => 'david'}, set.recognize_path('/page/david'))
2255
+ assert_raises ActionController::RoutingError do
2256
+ set.recognize_path('/page/david #The Creator')
2257
+ end
2258
+ assert_raises ActionController::RoutingError do
2259
+ set.recognize_path('/page/David')
2260
+ end
2261
+ end
2262
+
2263
+ def test_route_requirement_generate_with_extended_syntax
2264
+ set.draw do |map|
2265
+ map.connect 'page/:name', :controller => 'pages',
2266
+ :action => 'show',
2267
+ :requirements => {:name => / # Desperately overcommented regexp
2268
+ ( #Either
2269
+ david #The Creator
2270
+ | #Or
2271
+ jamis #The Deployer
2272
+ )/x}
2273
+ end
2274
+ url = set.generate({:controller => 'pages', :action => 'show', :name => 'david'})
2275
+ assert_equal "/page/david", url
2276
+ assert_raises ActionController::RoutingError do
2277
+ url = set.generate({:controller => 'pages', :action => 'show', :name => 'davidjamis'})
2278
+ end
2279
+ assert_raises ActionController::RoutingError do
2280
+ url = set.generate({:controller => 'pages', :action => 'show', :name => 'JAMIS'})
2281
+ end
2282
+ end
2283
+
2284
+ def test_route_requirement_generate_with_xi_modifiers
2285
+ set.draw do |map|
2286
+ map.connect 'page/:name', :controller => 'pages',
2287
+ :action => 'show',
2288
+ :requirements => {:name => / # Desperately overcommented regexp
2289
+ ( #Either
2290
+ david #The Creator
2291
+ | #Or
2292
+ jamis #The Deployer
2293
+ )/xi}
2294
+ end
2295
+ url = set.generate({:controller => 'pages', :action => 'show', :name => 'JAMIS'})
2296
+ assert_equal "/page/JAMIS", url
2297
+ end
2298
+
2299
+ def test_route_requirement_recognize_with_xi_modifiers
2300
+ set.draw do |map|
2301
+ map.connect 'page/:name', :controller => 'pages',
2302
+ :action => 'show',
2303
+ :requirements => {:name => / # Desperately overcommented regexp
2304
+ ( #Either
2305
+ david #The Creator
2306
+ | #Or
2307
+ jamis #The Deployer
2308
+ )/xi}
2309
+ end
2310
+ assert_equal({:controller => 'pages', :action => 'show', :name => 'JAMIS'}, set.recognize_path('/page/JAMIS'))
2311
+ end
2312
+
2313
+
2314
+ end
2315
+
2316
+ class RoutingTest < Test::Unit::TestCase
2317
+
2318
+ def test_possible_controllers
2319
+ true_controller_paths = ActionController::Routing.controller_paths
2320
+
2321
+ ActionController::Routing.use_controllers! nil
2322
+
2323
+ silence_warnings do
2324
+ Object.send(:const_set, :RAILS_ROOT, File.dirname(__FILE__) + '/controller_fixtures')
2325
+ end
2326
+
2327
+ ActionController::Routing.controller_paths = [
2328
+ RAILS_ROOT, RAILS_ROOT + '/app/controllers', RAILS_ROOT + '/vendor/plugins/bad_plugin/lib'
2329
+ ]
2330
+
2331
+ assert_equal ["admin/user", "plugin", "user"], ActionController::Routing.possible_controllers.sort
2332
+ ensure
2333
+ if true_controller_paths
2334
+ ActionController::Routing.controller_paths = true_controller_paths
2335
+ end
2336
+ ActionController::Routing.use_controllers! nil
2337
+ Object.send(:remove_const, :RAILS_ROOT) rescue nil
2338
+ end
2339
+
2340
+ def test_possible_controllers_are_reset_on_each_load
2341
+ true_possible_controllers = ActionController::Routing.possible_controllers
2342
+ true_controller_paths = ActionController::Routing.controller_paths
2343
+
2344
+ ActionController::Routing.use_controllers! nil
2345
+ root = File.dirname(__FILE__) + '/controller_fixtures'
2346
+
2347
+ ActionController::Routing.controller_paths = []
2348
+ assert_equal [], ActionController::Routing.possible_controllers
2349
+
2350
+ ActionController::Routing::Routes.load!
2351
+ ActionController::Routing.controller_paths = [
2352
+ root, root + '/app/controllers', root + '/vendor/plugins/bad_plugin/lib'
2353
+ ]
2354
+
2355
+ assert_equal ["admin/user", "plugin", "user"], ActionController::Routing.possible_controllers.sort
2356
+ ensure
2357
+ ActionController::Routing.controller_paths = true_controller_paths
2358
+ ActionController::Routing.use_controllers! true_possible_controllers
2359
+ Object.send(:remove_const, :RAILS_ROOT) rescue nil
2360
+
2361
+ ActionController::Routing::Routes.clear!
2362
+ ActionController::Routing::Routes.load_routes!
2363
+ end
2364
+
2365
+ def test_with_controllers
2366
+ c = %w(admin/accounts admin/users account pages)
2367
+ ActionController::Routing.with_controllers c do
2368
+ assert_equal c, ActionController::Routing.possible_controllers
2369
+ end
2370
+ end
2371
+
2372
+ def test_normalize_unix_paths
2373
+ load_paths = %w(. config/../app/controllers config/../app//helpers script/../config/../vendor/rails/actionpack/lib vendor/rails/railties/builtin/rails_info app/models lib script/../config/../foo/bar/../../app/models .foo/../.bar foo.bar/../config)
2374
+ paths = ActionController::Routing.normalize_paths(load_paths)
2375
+ assert_equal %w(vendor/rails/railties/builtin/rails_info vendor/rails/actionpack/lib app/controllers app/helpers app/models config .bar lib .), paths
2376
+ end
2377
+
2378
+ def test_normalize_windows_paths
2379
+ load_paths = %w(. config\\..\\app\\controllers config\\..\\app\\\\helpers script\\..\\config\\..\\vendor\\rails\\actionpack\\lib vendor\\rails\\railties\\builtin\\rails_info app\\models lib script\\..\\config\\..\\foo\\bar\\..\\..\\app\\models .foo\\..\\.bar foo.bar\\..\\config)
2380
+ paths = ActionController::Routing.normalize_paths(load_paths)
2381
+ assert_equal %w(vendor\\rails\\railties\\builtin\\rails_info vendor\\rails\\actionpack\\lib app\\controllers app\\helpers app\\models config .bar lib .), paths
2382
+ end
2383
+
2384
+ def test_routing_helper_module
2385
+ assert_kind_of Module, ActionController::Routing::Helpers
2386
+
2387
+ h = ActionController::Routing::Helpers
2388
+ c = Class.new
2389
+ assert ! c.ancestors.include?(h)
2390
+ ActionController::Routing::Routes.install_helpers c
2391
+ assert c.ancestors.include?(h)
2392
+ end
2393
+
2394
+ end
2395
+
2396
+ uses_mocha 'route loading' do
2397
+ class RouteLoadingTest < Test::Unit::TestCase
2398
+
2399
+ def setup
2400
+ routes.instance_variable_set '@routes_last_modified', nil
2401
+ silence_warnings { Object.const_set :RAILS_ROOT, '.' }
2402
+ ActionController::Routing::Routes.configuration_file = File.join(RAILS_ROOT, 'config', 'routes.rb')
2403
+
2404
+ @stat = stub_everything
2405
+ end
2406
+
2407
+ def teardown
2408
+ ActionController::Routing::Routes.configuration_file = nil
2409
+ Object.send :remove_const, :RAILS_ROOT
2410
+ end
2411
+
2412
+ def test_load
2413
+ File.expects(:stat).returns(@stat)
2414
+ routes.expects(:load).with(regexp_matches(/routes\.rb$/))
2415
+
2416
+ routes.reload
2417
+ end
2418
+
2419
+ def test_no_reload_when_not_modified
2420
+ @stat.expects(:mtime).times(2).returns(1)
2421
+ File.expects(:stat).times(2).returns(@stat)
2422
+ routes.expects(:load).with(regexp_matches(/routes\.rb$/)).at_most_once
2423
+
2424
+ 2.times { routes.reload }
2425
+ end
2426
+
2427
+ def test_reload_when_modified
2428
+ @stat.expects(:mtime).at_least(2).returns(1, 2)
2429
+ File.expects(:stat).at_least(2).returns(@stat)
2430
+ routes.expects(:load).with(regexp_matches(/routes\.rb$/)).times(2)
2431
+
2432
+ 2.times { routes.reload }
2433
+ end
2434
+
2435
+ def test_bang_forces_reload
2436
+ @stat.expects(:mtime).at_least(2).returns(1)
2437
+ File.expects(:stat).at_least(2).returns(@stat)
2438
+ routes.expects(:load).with(regexp_matches(/routes\.rb$/)).times(2)
2439
+
2440
+ 2.times { routes.reload! }
2441
+ end
2442
+
2443
+ def test_adding_inflections_forces_reload
2444
+ ActiveSupport::Inflector::Inflections.instance.expects(:uncountable).with('equipment')
2445
+ routes.expects(:reload!)
2446
+
2447
+ ActiveSupport::Inflector.inflections { |inflect| inflect.uncountable('equipment') }
2448
+ end
2449
+
2450
+ def test_load_with_configuration
2451
+ routes.configuration_file = "foobarbaz"
2452
+ File.expects(:stat).returns(@stat)
2453
+ routes.expects(:load).with("foobarbaz")
2454
+
2455
+ routes.reload
2456
+ end
2457
+
2458
+ private
2459
+ def routes
2460
+ ActionController::Routing::Routes
2461
+ end
2462
+
2463
+ end
2464
+ end