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,692 @@
1
+ require 'stringio'
2
+ require 'uri'
3
+ require 'active_support/test_case'
4
+ require 'action_controller/rack_lint_patch'
5
+
6
+ module ActionController
7
+ module Integration #:nodoc:
8
+ # An integration Session instance represents a set of requests and responses
9
+ # performed sequentially by some virtual user. Because you can instantiate
10
+ # multiple sessions and run them side-by-side, you can also mimic (to some
11
+ # limited extent) multiple simultaneous users interacting with your system.
12
+ #
13
+ # Typically, you will instantiate a new session using
14
+ # IntegrationTest#open_session, rather than instantiating
15
+ # Integration::Session directly.
16
+ class Session
17
+ include Test::Unit::Assertions
18
+ include ActionController::TestCase::Assertions
19
+ include ActionController::TestProcess
20
+
21
+ # Rack application to use
22
+ attr_accessor :application
23
+
24
+ # The integer HTTP status code of the last request.
25
+ attr_reader :status
26
+
27
+ # The status message that accompanied the status code of the last request.
28
+ attr_reader :status_message
29
+
30
+ # The body of the last request.
31
+ attr_reader :body
32
+
33
+ # The URI of the last request.
34
+ attr_reader :path
35
+
36
+ # The hostname used in the last request.
37
+ attr_accessor :host
38
+
39
+ # The remote_addr used in the last request.
40
+ attr_accessor :remote_addr
41
+
42
+ # The Accept header to send.
43
+ attr_accessor :accept
44
+
45
+ # A map of the cookies returned by the last response, and which will be
46
+ # sent with the next request.
47
+ attr_reader :cookies
48
+
49
+ # A map of the headers returned by the last response.
50
+ attr_reader :headers
51
+
52
+ # A reference to the controller instance used by the last request.
53
+ attr_reader :controller
54
+
55
+ # A reference to the request instance used by the last request.
56
+ attr_reader :request
57
+
58
+ # A reference to the response instance used by the last request.
59
+ attr_reader :response
60
+
61
+ # A running counter of the number of requests processed.
62
+ attr_accessor :request_count
63
+
64
+ class MultiPartNeededException < Exception
65
+ end
66
+
67
+ # Create and initialize a new Session instance.
68
+ def initialize(app = nil)
69
+ @application = app || ActionController::Dispatcher.new
70
+ reset!
71
+ end
72
+
73
+ # Resets the instance. This can be used to reset the state information
74
+ # in an existing session instance, so it can be used from a clean-slate
75
+ # condition.
76
+ #
77
+ # session.reset!
78
+ def reset!
79
+ @status = @path = @headers = nil
80
+ @result = @status_message = nil
81
+ @https = false
82
+ @cookies = {}
83
+ @controller = @request = @response = nil
84
+ @request_count = 0
85
+
86
+ self.host = "www.example.com"
87
+ self.remote_addr = "127.0.0.1"
88
+ self.accept = "text/xml,application/xml,application/xhtml+xml," +
89
+ "text/html;q=0.9,text/plain;q=0.8,image/png," +
90
+ "*/*;q=0.5"
91
+
92
+ unless defined? @named_routes_configured
93
+ # install the named routes in this session instance.
94
+ klass = class << self; self; end
95
+ Routing::Routes.install_helpers(klass)
96
+
97
+ # the helpers are made protected by default--we make them public for
98
+ # easier access during testing and troubleshooting.
99
+ klass.module_eval { public *Routing::Routes.named_routes.helpers }
100
+ @named_routes_configured = true
101
+ end
102
+ end
103
+
104
+ # Specify whether or not the session should mimic a secure HTTPS request.
105
+ #
106
+ # session.https!
107
+ # session.https!(false)
108
+ def https!(flag = true)
109
+ @https = flag
110
+ end
111
+
112
+ # Return +true+ if the session is mimicking a secure HTTPS request.
113
+ #
114
+ # if session.https?
115
+ # ...
116
+ # end
117
+ def https?
118
+ @https
119
+ end
120
+
121
+ # Set the host name to use in the next request.
122
+ #
123
+ # session.host! "www.example.com"
124
+ def host!(name)
125
+ @host = name
126
+ end
127
+
128
+ # Follow a single redirect response. If the last response was not a
129
+ # redirect, an exception will be raised. Otherwise, the redirect is
130
+ # performed on the location header.
131
+ def follow_redirect!
132
+ raise "not a redirect! #{@status} #{@status_message}" unless redirect?
133
+ get(interpret_uri(headers['location']))
134
+ status
135
+ end
136
+
137
+ # Performs a request using the specified method, following any subsequent
138
+ # redirect. Note that the redirects are followed until the response is
139
+ # not a redirect--this means you may run into an infinite loop if your
140
+ # redirect loops back to itself.
141
+ def request_via_redirect(http_method, path, parameters = nil, headers = nil)
142
+ send(http_method, path, parameters, headers)
143
+ follow_redirect! while redirect?
144
+ status
145
+ end
146
+
147
+ # Performs a GET request, following any subsequent redirect.
148
+ # See +request_via_redirect+ for more information.
149
+ def get_via_redirect(path, parameters = nil, headers = nil)
150
+ request_via_redirect(:get, path, parameters, headers)
151
+ end
152
+
153
+ # Performs a POST request, following any subsequent redirect.
154
+ # See +request_via_redirect+ for more information.
155
+ def post_via_redirect(path, parameters = nil, headers = nil)
156
+ request_via_redirect(:post, path, parameters, headers)
157
+ end
158
+
159
+ # Performs a PUT request, following any subsequent redirect.
160
+ # See +request_via_redirect+ for more information.
161
+ def put_via_redirect(path, parameters = nil, headers = nil)
162
+ request_via_redirect(:put, path, parameters, headers)
163
+ end
164
+
165
+ # Performs a DELETE request, following any subsequent redirect.
166
+ # See +request_via_redirect+ for more information.
167
+ def delete_via_redirect(path, parameters = nil, headers = nil)
168
+ request_via_redirect(:delete, path, parameters, headers)
169
+ end
170
+
171
+ # Returns +true+ if the last response was a redirect.
172
+ def redirect?
173
+ status/100 == 3
174
+ end
175
+
176
+ # Performs a GET request with the given parameters.
177
+ #
178
+ # - +path+: The URI (as a String) on which you want to perform a GET
179
+ # request.
180
+ # - +parameters+: The HTTP parameters that you want to pass. This may
181
+ # be +nil+,
182
+ # a Hash, or a String that is appropriately encoded
183
+ # (<tt>application/x-www-form-urlencoded</tt> or
184
+ # <tt>multipart/form-data</tt>).
185
+ # - +headers+: Additional HTTP headers to pass, as a Hash. The keys will
186
+ # automatically be upcased, with the prefix 'HTTP_' added if needed.
187
+ #
188
+ # This method returns an Response object, which one can use to
189
+ # inspect the details of the response. Furthermore, if this method was
190
+ # called from an ActionController::IntegrationTest object, then that
191
+ # object's <tt>@response</tt> instance variable will point to the same
192
+ # response object.
193
+ #
194
+ # You can also perform POST, PUT, DELETE, and HEAD requests with +post+,
195
+ # +put+, +delete+, and +head+.
196
+ def get(path, parameters = nil, headers = nil)
197
+ process :get, path, parameters, headers
198
+ end
199
+
200
+ # Performs a POST request with the given parameters. See get() for more
201
+ # details.
202
+ def post(path, parameters = nil, headers = nil)
203
+ process :post, path, parameters, headers
204
+ end
205
+
206
+ # Performs a PUT request with the given parameters. See get() for more
207
+ # details.
208
+ def put(path, parameters = nil, headers = nil)
209
+ process :put, path, parameters, headers
210
+ end
211
+
212
+ # Performs a DELETE request with the given parameters. See get() for
213
+ # more details.
214
+ def delete(path, parameters = nil, headers = nil)
215
+ process :delete, path, parameters, headers
216
+ end
217
+
218
+ # Performs a HEAD request with the given parameters. See get() for more
219
+ # details.
220
+ def head(path, parameters = nil, headers = nil)
221
+ process :head, path, parameters, headers
222
+ end
223
+
224
+ # Performs an XMLHttpRequest request with the given parameters, mirroring
225
+ # a request from the Prototype library.
226
+ #
227
+ # The request_method is :get, :post, :put, :delete or :head; the
228
+ # parameters are +nil+, a hash, or a url-encoded or multipart string;
229
+ # the headers are a hash. Keys are automatically upcased and prefixed
230
+ # with 'HTTP_' if not already.
231
+ def xml_http_request(request_method, path, parameters = nil, headers = nil)
232
+ headers ||= {}
233
+ headers['X-Requested-With'] = 'XMLHttpRequest'
234
+ headers['Accept'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
235
+ process(request_method, path, parameters, headers)
236
+ end
237
+ alias xhr :xml_http_request
238
+
239
+ # Returns the URL for the given options, according to the rules specified
240
+ # in the application's routes.
241
+ def url_for(options)
242
+ controller ?
243
+ controller.url_for(options) :
244
+ generic_url_rewriter.rewrite(options)
245
+ end
246
+
247
+ private
248
+ # Tailors the session based on the given URI, setting the HTTPS value
249
+ # and the hostname.
250
+ def interpret_uri(path)
251
+ location = URI.parse(path)
252
+ https! URI::HTTPS === location if location.scheme
253
+ host! location.host if location.host
254
+ location.query ? "#{location.path}?#{location.query}" : location.path
255
+ end
256
+
257
+ # Performs the actual request.
258
+ def process(method, path, parameters = nil, headers = nil)
259
+ data = requestify(parameters)
260
+ path = interpret_uri(path) if path =~ %r{://}
261
+ path = "/#{path}" unless path[0] == ?/
262
+ @path = path
263
+ env = {}
264
+
265
+ if method == :get
266
+ env["QUERY_STRING"] = data
267
+ data = nil
268
+ end
269
+
270
+ env["QUERY_STRING"] ||= ""
271
+
272
+ data ||= ''
273
+ data.force_encoding(Encoding::ASCII_8BIT) if data.respond_to?(:force_encoding)
274
+ data = data.is_a?(IO) ? data : StringIO.new(data)
275
+
276
+ env.update(
277
+ "REQUEST_METHOD" => method.to_s.upcase,
278
+ "SERVER_NAME" => host,
279
+ "SERVER_PORT" => (https? ? "443" : "80"),
280
+ "HTTPS" => https? ? "on" : "off",
281
+ "rack.url_scheme" => https? ? "https" : "http",
282
+ "SCRIPT_NAME" => "",
283
+
284
+ "REQUEST_URI" => path,
285
+ "PATH_INFO" => path,
286
+ "HTTP_HOST" => host,
287
+ "REMOTE_ADDR" => remote_addr,
288
+ "CONTENT_TYPE" => "application/x-www-form-urlencoded",
289
+ "CONTENT_LENGTH" => data ? data.length.to_s : nil,
290
+ "HTTP_COOKIE" => encode_cookies,
291
+ "HTTP_ACCEPT" => accept,
292
+
293
+ "rack.version" => [0,1],
294
+ "rack.input" => data,
295
+ "rack.errors" => StringIO.new,
296
+ "rack.multithread" => true,
297
+ "rack.multiprocess" => true,
298
+ "rack.run_once" => false
299
+ )
300
+
301
+ (headers || {}).each do |key, value|
302
+ key = key.to_s.upcase.gsub(/-/, "_")
303
+ key = "HTTP_#{key}" unless env.has_key?(key) || key =~ /^HTTP_/
304
+ env[key] = value
305
+ end
306
+
307
+ [ControllerCapture, ActionController::ProcessWithTest].each do |mod|
308
+ unless ActionController::Base < mod
309
+ ActionController::Base.class_eval { include mod }
310
+ end
311
+ end
312
+
313
+ ActionController::Base.clear_last_instantiation!
314
+
315
+ app = Rack::Lint.new(@application)
316
+ status, headers, body = app.call(env)
317
+ @request_count += 1
318
+
319
+ @html_document = nil
320
+
321
+ @status = status.to_i
322
+ @status_message = StatusCodes::STATUS_CODES[@status]
323
+
324
+ @headers = Rack::Utils::HeaderHash.new(headers)
325
+
326
+ (@headers['Set-Cookie'] || "").split("\n").each do |cookie|
327
+ name, value = cookie.match(/^([^=]*)=([^;]*);/)[1,2]
328
+ @cookies[name] = value
329
+ end
330
+
331
+ @body = ""
332
+ if body.respond_to?(:to_str)
333
+ @body << body
334
+ else
335
+ body.each { |part| @body << part }
336
+ end
337
+
338
+ if @controller = ActionController::Base.last_instantiation
339
+ @request = @controller.request
340
+ @response = @controller.response
341
+ @controller.send(:set_test_assigns)
342
+ else
343
+ # Decorate responses from Rack Middleware and Rails Metal
344
+ # as an Response for the purposes of integration testing
345
+ @response = Response.new
346
+ @response.status = status.to_s
347
+ @response.headers.replace(@headers)
348
+ @response.body = @body
349
+ end
350
+
351
+ # Decorate the response with the standard behavior of the
352
+ # TestResponse so that things like assert_response can be
353
+ # used in integration tests.
354
+ @response.extend(TestResponseBehavior)
355
+
356
+ return @status
357
+ rescue MultiPartNeededException
358
+ boundary = "----------XnJLe9ZIbbGUYtzPQJ16u1"
359
+ status = process(method, path,
360
+ multipart_body(parameters, boundary),
361
+ (headers || {}).merge(
362
+ {"CONTENT_TYPE" => "multipart/form-data; boundary=#{boundary}"}))
363
+ return status
364
+ end
365
+
366
+ # Encode the cookies hash in a format suitable for passing to a
367
+ # request.
368
+ def encode_cookies
369
+ cookies.inject("") do |string, (name, value)|
370
+ string << "#{name}=#{value}; "
371
+ end
372
+ end
373
+
374
+ # Get a temporary URL writer object
375
+ def generic_url_rewriter
376
+ env = {
377
+ 'REQUEST_METHOD' => "GET",
378
+ 'QUERY_STRING' => "",
379
+ "REQUEST_URI" => "/",
380
+ "HTTP_HOST" => host,
381
+ "SERVER_PORT" => https? ? "443" : "80",
382
+ "HTTPS" => https? ? "on" : "off"
383
+ }
384
+ UrlRewriter.new(Request.new(env), {})
385
+ end
386
+
387
+ def name_with_prefix(prefix, name)
388
+ prefix ? "#{prefix}[#{name}]" : name.to_s
389
+ end
390
+
391
+ # Convert the given parameters to a request string. The parameters may
392
+ # be a string, +nil+, or a Hash.
393
+ def requestify(parameters, prefix=nil)
394
+ if TestUploadedFile === parameters
395
+ raise MultiPartNeededException
396
+ elsif Hash === parameters
397
+ return nil if parameters.empty?
398
+ parameters.map { |k,v|
399
+ requestify(v, name_with_prefix(prefix, k))
400
+ }.join("&")
401
+ elsif Array === parameters
402
+ parameters.map { |v|
403
+ requestify(v, name_with_prefix(prefix, ""))
404
+ }.join("&")
405
+ elsif prefix.nil?
406
+ parameters
407
+ else
408
+ "#{CGI.escape(prefix)}=#{CGI.escape(parameters.to_s)}"
409
+ end
410
+ end
411
+
412
+ def multipart_requestify(params, first=true)
413
+ returning Hash.new do |p|
414
+ params.each do |key, value|
415
+ k = first ? key.to_s : "[#{key.to_s}]"
416
+ if Hash === value
417
+ multipart_requestify(value, false).each do |subkey, subvalue|
418
+ p[k + subkey] = subvalue
419
+ end
420
+ else
421
+ p[k] = value
422
+ end
423
+ end
424
+ end
425
+ end
426
+
427
+ def multipart_body(params, boundary)
428
+ multipart_requestify(params).map do |key, value|
429
+ if value.respond_to?(:original_filename)
430
+ File.open(value.path, "rb") do |f|
431
+ f.set_encoding(Encoding::BINARY) if f.respond_to?(:set_encoding)
432
+
433
+ <<-EOF
434
+ --#{boundary}\r
435
+ Content-Disposition: form-data; name="#{key}"; filename="#{CGI.escape(value.original_filename)}"\r
436
+ Content-Type: #{value.content_type}\r
437
+ Content-Length: #{File.stat(value.path).size}\r
438
+ \r
439
+ #{f.read}\r
440
+ EOF
441
+ end
442
+ else
443
+ <<-EOF
444
+ --#{boundary}\r
445
+ Content-Disposition: form-data; name="#{key}"\r
446
+ \r
447
+ #{value}\r
448
+ EOF
449
+ end
450
+ end.join("")+"--#{boundary}--\r"
451
+ end
452
+ end
453
+
454
+ # A module used to extend ActionController::Base, so that integration tests
455
+ # can capture the controller used to satisfy a request.
456
+ module ControllerCapture #:nodoc:
457
+ def self.included(base)
458
+ base.extend(ClassMethods)
459
+ base.class_eval do
460
+ class << self
461
+ alias_method_chain :new, :capture
462
+ end
463
+ end
464
+ end
465
+
466
+ module ClassMethods #:nodoc:
467
+ mattr_accessor :last_instantiation
468
+
469
+ def clear_last_instantiation!
470
+ self.last_instantiation = nil
471
+ end
472
+
473
+ def new_with_capture(*args)
474
+ controller = new_without_capture(*args)
475
+ self.last_instantiation ||= controller
476
+ controller
477
+ end
478
+ end
479
+ end
480
+
481
+ module Runner
482
+ def initialize(*args)
483
+ super
484
+ @integration_session = nil
485
+ end
486
+
487
+ # Reset the current session. This is useful for testing multiple sessions
488
+ # in a single test case.
489
+ def reset!
490
+ @integration_session = open_session
491
+ end
492
+
493
+ %w(get post put head delete cookies assigns
494
+ xml_http_request xhr get_via_redirect post_via_redirect).each do |method|
495
+ define_method(method) do |*args|
496
+ reset! unless @integration_session
497
+ # reset the html_document variable, but only for new get/post calls
498
+ @html_document = nil unless %w(cookies assigns).include?(method)
499
+ returning @integration_session.__send__(method, *args) do
500
+ copy_session_variables!
501
+ end
502
+ end
503
+ end
504
+
505
+ # Open a new session instance. If a block is given, the new session is
506
+ # yielded to the block before being returned.
507
+ #
508
+ # session = open_session do |sess|
509
+ # sess.extend(CustomAssertions)
510
+ # end
511
+ #
512
+ # By default, a single session is automatically created for you, but you
513
+ # can use this method to open multiple sessions that ought to be tested
514
+ # simultaneously.
515
+ def open_session(application = nil)
516
+ session = Integration::Session.new(application)
517
+
518
+ # delegate the fixture accessors back to the test instance
519
+ extras = Module.new { attr_accessor :delegate, :test_result }
520
+ if self.class.respond_to?(:fixture_table_names)
521
+ self.class.fixture_table_names.each do |table_name|
522
+ name = table_name.tr(".", "_")
523
+ next unless respond_to?(name)
524
+ extras.__send__(:define_method, name) { |*args|
525
+ delegate.send(name, *args)
526
+ }
527
+ end
528
+ end
529
+
530
+ # delegate add_assertion to the test case
531
+ extras.__send__(:define_method, :add_assertion) {
532
+ test_result.add_assertion
533
+ }
534
+ session.extend(extras)
535
+ session.delegate = self
536
+ session.test_result = @_result
537
+
538
+ yield session if block_given?
539
+ session
540
+ end
541
+
542
+ # Copy the instance variables from the current session instance into the
543
+ # test instance.
544
+ def copy_session_variables! #:nodoc:
545
+ return unless @integration_session
546
+ %w(controller response request).each do |var|
547
+ instance_variable_set("@#{var}", @integration_session.__send__(var))
548
+ end
549
+ end
550
+
551
+ # Delegate unhandled messages to the current session instance.
552
+ def method_missing(sym, *args, &block)
553
+ reset! unless @integration_session
554
+ if @integration_session.respond_to?(sym)
555
+ returning @integration_session.__send__(sym, *args, &block) do
556
+ copy_session_variables!
557
+ end
558
+ else
559
+ super
560
+ end
561
+ end
562
+ end
563
+ end
564
+
565
+ # An IntegrationTest is one that spans multiple controllers and actions,
566
+ # tying them all together to ensure they work together as expected. It tests
567
+ # more completely than either unit or functional tests do, exercising the
568
+ # entire stack, from the dispatcher to the database.
569
+ #
570
+ # At its simplest, you simply extend IntegrationTest and write your tests
571
+ # using the get/post methods:
572
+ #
573
+ # require "#{File.dirname(__FILE__)}/test_helper"
574
+ #
575
+ # class ExampleTest < ActionController::IntegrationTest
576
+ # fixtures :people
577
+ #
578
+ # def test_login
579
+ # # get the login page
580
+ # get "/login"
581
+ # assert_equal 200, status
582
+ #
583
+ # # post the login and follow through to the home page
584
+ # post "/login", :username => people(:jamis).username,
585
+ # :password => people(:jamis).password
586
+ # follow_redirect!
587
+ # assert_equal 200, status
588
+ # assert_equal "/home", path
589
+ # end
590
+ # end
591
+ #
592
+ # However, you can also have multiple session instances open per test, and
593
+ # even extend those instances with assertions and methods to create a very
594
+ # powerful testing DSL that is specific for your application. You can even
595
+ # reference any named routes you happen to have defined!
596
+ #
597
+ # require "#{File.dirname(__FILE__)}/test_helper"
598
+ #
599
+ # class AdvancedTest < ActionController::IntegrationTest
600
+ # fixtures :people, :rooms
601
+ #
602
+ # def test_login_and_speak
603
+ # jamis, david = login(:jamis), login(:david)
604
+ # room = rooms(:office)
605
+ #
606
+ # jamis.enter(room)
607
+ # jamis.speak(room, "anybody home?")
608
+ #
609
+ # david.enter(room)
610
+ # david.speak(room, "hello!")
611
+ # end
612
+ #
613
+ # private
614
+ #
615
+ # module CustomAssertions
616
+ # def enter(room)
617
+ # # reference a named route, for maximum internal consistency!
618
+ # get(room_url(:id => room.id))
619
+ # assert(...)
620
+ # ...
621
+ # end
622
+ #
623
+ # def speak(room, message)
624
+ # xml_http_request "/say/#{room.id}", :message => message
625
+ # assert(...)
626
+ # ...
627
+ # end
628
+ # end
629
+ #
630
+ # def login(who)
631
+ # open_session do |sess|
632
+ # sess.extend(CustomAssertions)
633
+ # who = people(who)
634
+ # sess.post "/login", :username => who.username,
635
+ # :password => who.password
636
+ # assert(...)
637
+ # end
638
+ # end
639
+ # end
640
+ class IntegrationTest < ActiveSupport::TestCase
641
+ include Integration::Runner
642
+
643
+ # Work around a bug in test/unit caused by the default test being named
644
+ # as a symbol (:default_test), which causes regex test filters
645
+ # (like "ruby test.rb -n /foo/") to fail because =~ doesn't work on
646
+ # symbols.
647
+ def initialize(name) #:nodoc:
648
+ super(name.to_s)
649
+ end
650
+
651
+ # Work around test/unit's requirement that every subclass of TestCase have
652
+ # at least one test method. Note that this implementation extends to all
653
+ # subclasses, as well, so subclasses of IntegrationTest may also exist
654
+ # without any test methods.
655
+ def run(*args) #:nodoc:
656
+ return if @method_name == "default_test"
657
+ super
658
+ end
659
+
660
+ # Because of how use_instantiated_fixtures and use_transactional_fixtures
661
+ # are defined, we need to treat them as special cases. Otherwise, users
662
+ # would potentially have to set their values for both Test::Unit::TestCase
663
+ # ActionController::IntegrationTest, since by the time the value is set on
664
+ # TestCase, IntegrationTest has already been defined and cannot inherit
665
+ # changes to those variables. So, we make those two attributes
666
+ # copy-on-write.
667
+
668
+ class << self
669
+ def use_transactional_fixtures=(flag) #:nodoc:
670
+ @_use_transactional_fixtures = true
671
+ @use_transactional_fixtures = flag
672
+ end
673
+
674
+ def use_instantiated_fixtures=(flag) #:nodoc:
675
+ @_use_instantiated_fixtures = true
676
+ @use_instantiated_fixtures = flag
677
+ end
678
+
679
+ def use_transactional_fixtures #:nodoc:
680
+ @_use_transactional_fixtures ?
681
+ @use_transactional_fixtures :
682
+ superclass.use_transactional_fixtures
683
+ end
684
+
685
+ def use_instantiated_fixtures #:nodoc:
686
+ @_use_instantiated_fixtures ?
687
+ @use_instantiated_fixtures :
688
+ superclass.use_instantiated_fixtures
689
+ end
690
+ end
691
+ end
692
+ end