eactionpack 2.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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