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