actionpack_csi 2.3.5.p6

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