actionpack_csi 2.3.5.p6

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