routing_test.rb 68.3 KB
Newer Older
1
# encoding: utf-8
2 3
require 'abstract_unit'
require 'controller/fake_controllers'
4
require 'active_support/dependencies'
5

J
Jeremy Kemper 已提交
6 7 8 9 10 11
class MilestonesController < ActionController::Base
  def index() head :ok end
  alias_method :show, :index
  def rescue_action(e) raise e end
end

12
ROUTING = ActionController::Routing
13

14 15
class ROUTING::RouteBuilder
  attr_reader :warn_output
16

17 18
  def warn(msg)
    (@warn_output ||= []) << msg
19
  end
20
end
21

22
# See RFC 3986, section 3.3 for allowed path characters.
23 24 25 26 27
class UriReservedCharactersRoutingTest < Test::Unit::TestCase
  def setup
    ActionController::Routing.use_controllers! ['controller']
    @set = ActionController::Routing::RouteSet.new
    @set.draw do |map|
28
      map.connect ':controller/:action/:variable/*additional'
29
    end
30

31
    safe, unsafe = %w(: @ & = + $ , ;), %w(^ / ? # [ ])
32 33
    hex = unsafe.map { |char| '%' + char.unpack('H2').first.upcase }

34 35
    @segment = "#{safe.join}#{unsafe.join}".freeze
    @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 41
      @set.generate(:controller => "contr#{@segment}oller",
                    :action => "act#{@segment}ion",
42 43
                    :variable => "var#{@segment}iable",
                    :additional => ["add#{@segment}itional-1", "add#{@segment}itional-2"])
44
  end
45 46

  def test_route_recognition_unescapes_path_components
47
    options = { :controller => "content",
48
                :action => "act#{@segment}ion",
49 50
                :variable => "var#{@segment}iable",
                :additional => ["add#{@segment}itional-1", "add#{@segment}itional-2"] }
51
    assert_equal options, @set.recognize_path("/content/act#{@escaped}ion/var#{@escaped}iable/add#{@escaped}itional-1/add#{@escaped}itional-2")
52
  end
53 54 55 56 57 58 59

  def test_route_generation_allows_passing_non_string_values_to_generated_helper
    assert_equal "/controller/action/variable/1/2", @set.generate(:controller => "controller",
                                                                  :action => "action",
                                                                  :variable => "variable",
                                                                  :additional => [1, 2])
  end
60 61
end

62 63 64 65 66 67
class RoutingTest < Test::Unit::TestCase
  def test_normalize_unix_paths
    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)
    paths = ActionController::Routing.normalize_paths(load_paths)
    assert_equal %w(vendor/rails/railties/builtin/rails_info vendor/rails/actionpack/lib app/controllers app/helpers app/models config .bar lib .), paths
  end
68

69 70 71 72
  def test_normalize_windows_paths
    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)
    paths = ActionController::Routing.normalize_paths(load_paths)
    assert_equal %w(vendor\\rails\\railties\\builtin\\rails_info vendor\\rails\\actionpack\\lib app\\controllers app\\helpers app\\models config .bar lib .), paths
73 74
  end

75 76
  def test_routing_helper_module
    assert_kind_of Module, ActionController::Routing::Helpers
77

78 79 80 81 82
    h = ActionController::Routing::Helpers
    c = Class.new
    assert ! c.ancestors.include?(h)
    ActionController::Routing::Routes.install_helpers c
    assert c.ancestors.include?(h)
83
  end
84
end
85

86 87
class MockController
  attr_accessor :routes
88

89 90 91
  def initialize(routes)
    self.routes = routes
  end
92

93 94
  def url_for(options)
    only_path = options.delete(:only_path)
95

96 97
    port        = options.delete(:port) || 80
    port_string = port == 80 ? '' : ":#{port}"
98

99 100 101
    protocol = options.delete(:protocol) || "http"
    host     = options.delete(:host) || "test.host"
    anchor   = "##{options.delete(:anchor)}" if options.key?(:anchor)
102

103
    path = routes.generate(options)
104

105 106
    only_path ? "#{path}#{anchor}" : "#{protocol}://#{host}#{port_string}#{path}#{anchor}"
  end
107

108 109
  def request
    @request ||= ActionController::TestRequest.new
110
  end
111
end
112

113 114
class LegacyRouteSetTests < Test::Unit::TestCase
  attr_reader :rs
115

116 117 118 119 120 121 122 123
  def setup
    # These tests assume optimisation is on, so re-enable it.
    ActionController::Base.optimise_named_routes = true

    @rs = ::ActionController::Routing::RouteSet.new

    ActionController::Routing.use_controllers! %w(content admin/user admin/news_feed)
  end
J
Joshua Peek 已提交
124

125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
  def teardown
    @rs.clear!
  end

  def test_default_setup
    @rs.draw {|m| m.connect ':controller/:action/:id' }
    assert_equal({:controller => "content", :action => 'index'}, rs.recognize_path("/content"))
    assert_equal({:controller => "content", :action => 'list'}, rs.recognize_path("/content/list"))
    assert_equal({:controller => "content", :action => 'show', :id => '10'}, rs.recognize_path("/content/show/10"))

    assert_equal({:controller => "admin/user", :action => 'show', :id => '10'}, rs.recognize_path("/admin/user/show/10"))

    assert_equal '/admin/user/show/10', rs.generate(:controller => 'admin/user', :action => 'show', :id => 10)

    assert_equal '/admin/user/show', rs.generate({:action => 'show'}, {:controller => 'admin/user', :action => 'list', :id => '10'})
    assert_equal '/admin/user/list/10', rs.generate({}, {:controller => 'admin/user', :action => 'list', :id => '10'})

    assert_equal '/admin/stuff', rs.generate({:controller => 'stuff'}, {:controller => 'admin/user', :action => 'list', :id => '10'})
    assert_equal '/stuff', rs.generate({:controller => '/stuff'}, {:controller => 'admin/user', :action => 'list', :id => '10'})
  end

  def test_ignores_leading_slash
    @rs.clear!
    @rs.draw {|m| m.connect '/:controller/:action/:id'}
    test_default_setup
  end

  def test_time_recognition
    # We create many routes to make situation more realistic
    @rs = ::ActionController::Routing::RouteSet.new
    @rs.draw { |map|
      map.frontpage '', :controller => 'search', :action => 'new'
      map.resources :videos do |video|
        video.resources :comments
        video.resource  :file,      :controller => 'video_file'
        video.resource  :share,     :controller => 'video_shares'
        video.resource  :abuse,     :controller => 'video_abuses'
      end
      map.resources :abuses, :controller => 'video_abuses'
      map.resources :video_uploads
      map.resources :video_visits

      map.resources :users do |user|
        user.resource  :settings
        user.resources :videos
      end
      map.resources :channels do |channel|
        channel.resources :videos, :controller => 'channel_videos'
      end
      map.resource  :session
      map.resource  :lost_password
      map.search    'search', :controller => 'search'
      map.resources :pages
      map.connect ':controller/:action/:id'
    }
  end
181

182 183 184 185
  def test_route_with_colon_first
    rs.draw do |map|
      map.connect '/:controller/:action/:id', :action => 'index', :id => nil
      map.connect ':url', :controller => 'tiny_url', :action => 'translate'
186
    end
187 188 189 190 191 192
  end

  def test_route_with_regexp_for_controller
    rs.draw do |map|
      map.connect ':controller/:admintoken/:action/:id', :controller => /admin\/.+/
      map.connect ':controller/:action/:id'
193
    end
194 195 196 197 198 199
    assert_equal({:controller => "admin/user", :admintoken => "foo", :action => "index"},
        rs.recognize_path("/admin/user/foo"))
    assert_equal({:controller => "content", :action => "foo"}, rs.recognize_path("/content/foo"))
    assert_equal '/admin/user/foo', rs.generate(:controller => "admin/user", :admintoken => "foo", :action => "index")
    assert_equal '/content/foo', rs.generate(:controller => "content", :action => "foo")
  end
200

201 202 203 204 205 206
  def test_route_with_regexp_and_captures_for_controller
    rs.draw do |map|
      map.connect ':controller/:action/:id', :controller => /admin\/(accounts|users)/
    end
    assert_equal({:controller => "admin/accounts", :action => "index"}, rs.recognize_path("/admin/accounts"))
    assert_equal({:controller => "admin/users", :action => "index"}, rs.recognize_path("/admin/users"))
207
    assert_raise(ActionController::RoutingError) { rs.recognize_path("/admin/products") }
208 209
  end

210 211 212 213 214 215 216 217 218 219 220 221 222 223
  def test_route_with_regexp_and_dot
    rs.draw do |map|
      map.connect ':controller/:action/:file',
                        :controller => /admin|user/,
                        :action => /upload|download/,
                        :defaults => {:file => nil},
                        :requirements => {:file => %r{[^/]+(\.[^/]+)?}}
    end
    # Without a file extension
    assert_equal '/user/download/file',
      rs.generate(:controller => "user", :action => "download", :file => "file")
    assert_equal(
      {:controller => "user", :action => "download", :file => "file"},
      rs.recognize_path("/user/download/file"))
224

225 226 227 228 229 230 231 232
    # Now, let's try a file with an extension, really a dot (.)
    assert_equal '/user/download/file.jpg',
      rs.generate(
        :controller => "user", :action => "download", :file => "file.jpg")
    assert_equal(
      {:controller => "user", :action => "download", :file => "file.jpg"},
      rs.recognize_path("/user/download/file.jpg"))
  end
233

234
  def test_basic_named_route
235 236 237
    rs.draw do |map|
      map.home '', :controller => 'content', :action => 'list'
    end
238 239 240 241
    x = setup_for_named_route
    assert_equal("http://test.host/",
                 x.send(:home_url))
  end
242

243
  def test_named_route_with_option
244 245 246
    rs.draw do |map|
      map.page 'page/:title', :controller => 'content', :action => 'show_page'
    end
247 248 249 250
    x = setup_for_named_route
    assert_equal("http://test.host/page/new%20stuff",
                 x.send(:page_url, :title => 'new stuff'))
  end
251

252
  def test_named_route_with_default
253 254 255
    rs.draw do |map|
      map.page 'page/:title', :controller => 'content', :action => 'show_page', :title => 'AboutPage'
    end
256 257 258
    x = setup_for_named_route
    assert_equal("http://test.host/page/AboutRails",
                 x.send(:page_url, :title => "AboutRails"))
259

260
  end
261

262
  def test_named_route_with_name_prefix
263 264 265
    rs.draw do |map|
      map.page 'page', :controller => 'content', :action => 'show_page', :name_prefix => 'my_'
    end
266 267 268 269
    x = setup_for_named_route
    assert_equal("http://test.host/page",
                 x.send(:my_page_url))
  end
J
Joshua Peek 已提交
270

271
  def test_named_route_with_path_prefix
272 273 274
    rs.draw do |map|
      map.page 'page', :controller => 'content', :action => 'show_page', :path_prefix => 'my'
    end
275 276 277 278
    x = setup_for_named_route
    assert_equal("http://test.host/my/page",
                 x.send(:page_url))
  end
279

280
  def test_named_route_with_blank_path_prefix
281 282 283
    rs.draw do |map|
      map.page 'page', :controller => 'content', :action => 'show_page', :path_prefix => ''
    end
284 285 286 287 288
    x = setup_for_named_route
    assert_equal("http://test.host/page",
                 x.send(:page_url))
  end

289
  def test_named_route_with_nested_controller
290 291 292
    rs.draw do |map|
      map.users 'admin/user', :controller => 'admin/user', :action => 'index'
    end
293 294 295 296
    x = setup_for_named_route
    assert_equal("http://test.host/admin/user",
                 x.send(:users_url))
  end
297

298
  def test_optimised_named_route_with_host
299 300 301
    rs.draw do |map|
      map.pages 'pages', :controller => 'content', :action => 'show_page', :host => 'foo.com'
    end
302 303 304 305
    x = setup_for_named_route
    x.expects(:url_for).with(:host => 'foo.com', :only_path => false, :controller => 'content', :action => 'show_page', :use_route => :pages).once
    x.send(:pages_url)
  end
306

307 308 309 310 311
  def setup_for_named_route
    klass = Class.new(MockController)
    rs.install_helpers(klass)
    klass.new(rs)
  end
312

313 314 315
  def test_named_route_without_hash
    rs.draw do |map|
      map.normal ':controller/:action/:id'
316
    end
317
  end
318

319 320 321
  def test_named_route_root
    rs.draw do |map|
      map.root :controller => "hello"
322
    end
323 324 325 326
    x = setup_for_named_route
    assert_equal("http://test.host/", x.send(:root_url))
    assert_equal("/", x.send(:root_path))
  end
327

328 329 330 331 332
  def test_named_route_with_regexps
    rs.draw do |map|
      map.article 'page/:year/:month/:day/:title', :controller => 'page', :action => 'show',
        :year => /\d+/, :month => /\d+/, :day => /\d+/
      map.connect ':controller/:action/:id'
333
    end
334 335 336 337 338 339 340 341 342 343
    x = setup_for_named_route
    # assert_equal(
    #   {:controller => 'page', :action => 'show', :title => 'hi', :use_route => :article, :only_path => false},
    #   x.send(:article_url, :title => 'hi')
    # )
    assert_equal(
      "http://test.host/page/2005/6/10/hi",
      x.send(:article_url, :title => 'hi', :day => 10, :year => 2005, :month => 6)
    )
  end
344

345 346
  def test_changing_controller
    @rs.draw {|m| m.connect ':controller/:action/:id' }
347

348 349 350 351 352
    assert_equal '/admin/stuff/show/10', rs.generate(
      {:controller => 'stuff', :action => 'show', :id => 10},
      {:controller => 'admin/user', :action => 'index'}
    )
  end
353

354 355 356 357
  def test_paths_escaped
    rs.draw do |map|
      map.path 'file/*path', :controller => 'content', :action => 'show_file'
      map.connect ':controller/:action/:id'
358
    end
359

360 361 362 363
    # No + to space in URI escaping, only for query params.
    results = rs.recognize_path "/file/hello+world/how+are+you%3F"
    assert results, "Recognition should have succeeded"
    assert_equal ['hello+world', 'how+are+you?'], results[:path]
364

365 366 367 368
    # Use %20 for space instead.
    results = rs.recognize_path "/file/hello%20world/how%20are%20you%3F"
    assert results, "Recognition should have succeeded"
    assert_equal ['hello world', 'how are you?'], results[:path]
369

370 371 372 373
    results = rs.recognize_path "/file"
    assert results, "Recognition should have succeeded"
    assert_equal [], results[:path]
  end
374

375
  def test_paths_slashes_unescaped_with_ordered_parameters
376 377 378
    rs.draw do |map|
      map.path '/file/*path', :controller => 'content'
    end
379

380 381 382 383
    # No / to %2F in URI, only for query params.
    x = setup_for_named_route
    assert_equal("/file/hello/world", x.send(:path_path, 'hello/world'))
  end
384

385 386 387
  def test_non_controllers_cannot_be_matched
    rs.draw do |map|
      map.connect ':controller/:action/:id'
388
    end
389
    assert_raise(ActionController::RoutingError) { rs.recognize_path("/not_a/show/10") }
390
  end
391

392
  def test_paths_do_not_accept_defaults
393
    assert_raise(ActionController::RoutingError) do
394
      rs.draw do |map|
395 396
        map.path 'file/*path', :controller => 'content', :action => 'show_file', :path => %w(fake default)
        map.connect ':controller/:action/:id'
397 398 399
      end
    end

400 401 402
    rs.draw do |map|
      map.path 'file/*path', :controller => 'content', :action => 'show_file', :path => []
      map.connect ':controller/:action/:id'
403
    end
404
  end
405

406 407 408
  def test_should_list_options_diff_when_routing_requirements_dont_match
    rs.draw do |map|
      map.post 'post/:id', :controller=> 'post', :action=> 'show', :requirements => {:id => /\d+/}
409
    end
410 411 412 413 414 415
    exception = assert_raise(ActionController::RoutingError) { rs.generate(:controller => 'post', :action => 'show', :bad_param => "foo", :use_route => "post") }
    assert_match /^post_url failed to generate/, exception.message
    from_match = exception.message.match(/from \{[^\}]+\}/).to_s
    assert_match /:bad_param=>"foo"/,   from_match
    assert_match /:action=>"show"/,     from_match
    assert_match /:controller=>"post"/, from_match
416

417 418 419 420
    expected_match = exception.message.match(/expected: \{[^\}]+\}/).to_s
    assert_no_match /:bad_param=>"foo"/,   expected_match
    assert_match    /:action=>"show"/,     expected_match
    assert_match    /:controller=>"post"/, expected_match
421

422 423 424 425 426 427 428 429 430 431
    diff_match = exception.message.match(/diff: \{[^\}]+\}/).to_s
    assert_match    /:bad_param=>"foo"/,   diff_match
    assert_no_match /:action=>"show"/,     diff_match
    assert_no_match /:controller=>"post"/, diff_match
  end

  def test_dynamic_path_allowed
    rs.draw do |map|
      map.connect '*path', :controller => 'content', :action => 'show_file'
    end
432

433 434
    assert_equal '/pages/boo', rs.generate(:controller => 'content', :action => 'show_file', :path => %w(pages boo))
  end
435

436 437 438
  def test_dynamic_recall_paths_allowed
    rs.draw do |map|
      map.connect '*path', :controller => 'content', :action => 'show_file'
439 440
    end

441
    assert_equal '/pages/boo', rs.generate({}, :controller => 'content', :action => 'show_file', :path => %w(pages boo))
442
  end
443

444 445 446 447
  def test_backwards
    rs.draw do |map|
      map.connect 'page/:id/:action', :controller => 'pages', :action => 'show'
      map.connect ':controller/:action/:id'
448 449
    end

450 451 452 453 454 455 456 457 458
    assert_equal '/page/20', rs.generate({:id => 20}, {:controller => 'pages', :action => 'show'})
    assert_equal '/page/20', rs.generate(:controller => 'pages', :id => 20, :action => 'show')
    assert_equal '/pages/boo', rs.generate(:controller => 'pages', :action => 'boo')
  end

  def test_route_with_fixnum_default
    rs.draw do |map|
      map.connect 'page/:id', :controller => 'content', :action => 'show_page', :id => 1
      map.connect ':controller/:action/:id'
459 460
    end

461 462 463 464
    assert_equal '/page', rs.generate(:controller => 'content', :action => 'show_page')
    assert_equal '/page', rs.generate(:controller => 'content', :action => 'show_page', :id => 1)
    assert_equal '/page', rs.generate(:controller => 'content', :action => 'show_page', :id => '1')
    assert_equal '/page/10', rs.generate(:controller => 'content', :action => 'show_page', :id => 10)
465

466 467 468 469 470 471 472 473 474 475
    assert_equal({:controller => "content", :action => 'show_page', :id => '1'}, rs.recognize_path("/page"))
    assert_equal({:controller => "content", :action => 'show_page', :id => '1'}, rs.recognize_path("/page/1"))
    assert_equal({:controller => "content", :action => 'show_page', :id => '10'}, rs.recognize_path("/page/10"))
  end

  # For newer revision
  def test_route_with_text_default
    rs.draw do |map|
      map.connect 'page/:id', :controller => 'content', :action => 'show_page', :id => 1
      map.connect ':controller/:action/:id'
476 477
    end

478 479
    assert_equal '/page/foo', rs.generate(:controller => 'content', :action => 'show_page', :id => 'foo')
    assert_equal({:controller => "content", :action => 'show_page', :id => 'foo'}, rs.recognize_path("/page/foo"))
480

481 482
    token = "\321\202\320\265\320\272\321\201\321\202" # 'text' in russian
    escaped_token = CGI::escape(token)
483

484 485 486
    assert_equal '/page/' + escaped_token, rs.generate(:controller => 'content', :action => 'show_page', :id => token)
    assert_equal({:controller => "content", :action => 'show_page', :id => token}, rs.recognize_path("/page/#{escaped_token}"))
  end
487

488 489 490 491
  def test_action_expiry
    @rs.draw {|m| m.connect ':controller/:action/:id' }
    assert_equal '/content', rs.generate({:controller => 'content'}, {:controller => 'content', :action => 'show'})
  end
492

493 494 495 496 497 498 499 500 501 502
  def test_recognition_with_uppercase_controller_name
    @rs.draw {|m| m.connect ':controller/:action/:id' }
    assert_equal({:controller => "content", :action => 'index'}, rs.recognize_path("/Content"))
    assert_equal({:controller => "content", :action => 'list'}, rs.recognize_path("/ConTent/list"))
    assert_equal({:controller => "content", :action => 'show', :id => '10'}, rs.recognize_path("/CONTENT/show/10"))

    # these used to work, before the routes rewrite, but support for this was pulled in the new version...
    #assert_equal({'controller' => "admin/news_feed", 'action' => 'index'}, rs.recognize_path("Admin/NewsFeed"))
    #assert_equal({'controller' => "admin/news_feed", 'action' => 'index'}, rs.recognize_path("Admin/News_Feed"))
  end
503

504 505 506
  def test_requirement_should_prevent_optional_id
    rs.draw do |map|
      map.post 'post/:id', :controller=> 'post', :action=> 'show', :requirements => {:id => /\d+/}
507 508
    end

509
    assert_equal '/post/10', rs.generate(:controller => 'post', :action => 'show', :id => 10)
510

511
    assert_raise ActionController::RoutingError do
512
      rs.generate(:controller => 'post', :action => 'show')
513
    end
514
  end
515

516 517 518 519 520 521 522 523
  def test_both_requirement_and_optional
    rs.draw do |map|
      map.blog('test/:year', :controller => 'post', :action => 'show',
        :defaults => { :year => nil },
        :requirements => { :year => /\d{4}/ }
      )
      map.connect ':controller/:action/:id'
    end
524

525 526 527 528 529 530 531
    assert_equal '/test', rs.generate(:controller => 'post', :action => 'show')
    assert_equal '/test', rs.generate(:controller => 'post', :action => 'show', :year => nil)

    x = setup_for_named_route
    assert_equal("http://test.host/test",
                 x.send(:blog_url))
  end
532

533 534 535 536
  def test_set_to_nil_forgets
    rs.draw do |map|
      map.connect 'pages/:year/:month/:day', :controller => 'content', :action => 'list_pages', :month => nil, :day => nil
      map.connect ':controller/:action/:id'
537 538
    end

539 540 541 542 543 544
    assert_equal '/pages/2005',
      rs.generate(:controller => 'content', :action => 'list_pages', :year => 2005)
    assert_equal '/pages/2005/6',
      rs.generate(:controller => 'content', :action => 'list_pages', :year => 2005, :month => 6)
    assert_equal '/pages/2005/6/12',
      rs.generate(:controller => 'content', :action => 'list_pages', :year => 2005, :month => 6, :day => 12)
545

546 547
    assert_equal '/pages/2005/6/4',
      rs.generate({:day => 4}, {:controller => 'content', :action => 'list_pages', :year => '2005', :month => '6', :day => '12'})
548

549 550
    assert_equal '/pages/2005/6',
      rs.generate({:day => nil}, {:controller => 'content', :action => 'list_pages', :year => '2005', :month => '6', :day => '12'})
551

552 553 554
    assert_equal '/pages/2005',
      rs.generate({:day => nil, :month => nil}, {:controller => 'content', :action => 'list_pages', :year => '2005', :month => '6', :day => '12'})
  end
555

556 557 558 559
  def test_url_with_no_action_specified
    rs.draw do |map|
      map.connect '', :controller => 'content'
      map.connect ':controller/:action/:id'
560 561
    end

562 563 564
    assert_equal '/', rs.generate(:controller => 'content', :action => 'index')
    assert_equal '/', rs.generate(:controller => 'content')
  end
565

566 567 568 569
  def test_named_url_with_no_action_specified
    rs.draw do |map|
      map.home '', :controller => 'content'
      map.connect ':controller/:action/:id'
570 571
    end

572 573
    assert_equal '/', rs.generate(:controller => 'content', :action => 'index')
    assert_equal '/', rs.generate(:controller => 'content')
574

575 576 577 578
    x = setup_for_named_route
    assert_equal("http://test.host/",
                 x.send(:home_url))
  end
579

580 581
  def test_url_generated_when_forgetting_action
    [{:controller => 'content', :action => 'index'}, {:controller => 'content'}].each do |hash|
582
      rs.draw do |map|
583
        map.home '', hash
584 585
        map.connect ':controller/:action/:id'
      end
586 587 588 589 590
      assert_equal '/', rs.generate({:action => nil}, {:controller => 'content', :action => 'hello'})
      assert_equal '/', rs.generate({:controller => 'content'})
      assert_equal '/content/hi', rs.generate({:controller => 'content', :action => 'hi'})
    end
  end
591

592 593 594 595
  def test_named_route_method
    rs.draw do |map|
      map.categories 'categories', :controller => 'content', :action => 'categories'
      map.connect ':controller/:action/:id'
596 597
    end

598 599 600 601 602 603 604 605
    assert_equal '/categories', rs.generate(:controller => 'content', :action => 'categories')
    assert_equal '/content/hi', rs.generate({:controller => 'content', :action => 'hi'})
  end

  def test_named_routes_array
    test_named_route_method
    assert_equal [:categories], rs.named_routes.names
  end
606

607 608 609 610 611 612 613 614
  def test_nil_defaults
    rs.draw do |map|
      map.connect 'journal',
        :controller => 'content',
        :action => 'list_journal',
        :date => nil, :user_id => nil
      map.connect ':controller/:action/:id'
    end
615

616 617
    assert_equal '/journal', rs.generate(:controller => 'content', :action => 'list_journal', :date => nil, :user_id => nil)
  end
618

619 620 621 622
  def setup_request_method_routes_for(method)
    @request = ActionController::TestRequest.new
    @request.env["REQUEST_METHOD"] = method
    @request.request_uri = "/match"
623

624 625 626 627 628
    rs.draw do |r|
      r.connect '/match', :controller => 'books', :action => 'get', :conditions => { :method => :get }
      r.connect '/match', :controller => 'books', :action => 'post', :conditions => { :method => :post }
      r.connect '/match', :controller => 'books', :action => 'put', :conditions => { :method => :put }
      r.connect '/match', :controller => 'books', :action => 'delete', :conditions => { :method => :delete }
629
    end
630
  end
631

632 633
  %w(GET POST PUT DELETE).each do |request_method|
    define_method("test_request_method_recognized_with_#{request_method}") do
634 635 636
      setup_request_method_routes_for(request_method)
      assert_nothing_raised { rs.recognize(@request) }
      assert_equal request_method.downcase, @request.path_parameters[:action]
637 638
    end
  end
639

640 641 642 643
  def test_recognize_array_of_methods
    rs.draw do |r|
      r.connect '/match', :controller => 'books', :action => 'get_or_post', :conditions => { :method => [:get, :post] }
      r.connect '/match', :controller => 'books', :action => 'not_get_or_post'
644 645
    end

646 647 648 649 650
    @request = ActionController::TestRequest.new
    @request.env["REQUEST_METHOD"] = 'POST'
    @request.request_uri = "/match"
    assert_nothing_raised { rs.recognize(@request) }
    assert_equal 'get_or_post', @request.path_parameters[:action]
651

652 653 654 655 656 657 658
    # have to recreate or else the RouteSet uses a cached version:
    @request = ActionController::TestRequest.new
    @request.env["REQUEST_METHOD"] = 'PUT'
    @request.request_uri = "/match"
    assert_nothing_raised { rs.recognize(@request) }
    assert_equal 'not_get_or_post', @request.path_parameters[:action]
  end
659

660 661 662 663 664 665
  def test_subpath_recognized
    rs.draw do |r|
      r.connect '/books/:id/edit', :controller => 'subpath_books', :action => 'edit'
      r.connect '/items/:id/:action', :controller => 'subpath_books'
      r.connect '/posts/new/:action', :controller => 'subpath_books'
      r.connect '/posts/:id', :controller => 'subpath_books', :action => "show"
666 667
    end

668 669 670
    hash = rs.recognize_path "/books/17/edit"
    assert_not_nil hash
    assert_equal %w(subpath_books 17 edit), [hash[:controller], hash[:id], hash[:action]]
671

672 673 674 675 676 677 678 679 680 681 682 683
    hash = rs.recognize_path "/items/3/complete"
    assert_not_nil hash
    assert_equal %w(subpath_books 3 complete), [hash[:controller], hash[:id], hash[:action]]

    hash = rs.recognize_path "/posts/new/preview"
    assert_not_nil hash
    assert_equal %w(subpath_books preview), [hash[:controller], hash[:action]]

    hash = rs.recognize_path "/posts/7"
    assert_not_nil hash
    assert_equal %w(subpath_books show 7), [hash[:controller], hash[:action], hash[:id]]
  end
684

685 686 687 688 689
  def test_subpath_generated
    rs.draw do |r|
      r.connect '/books/:id/edit', :controller => 'subpath_books', :action => 'edit'
      r.connect '/items/:id/:action', :controller => 'subpath_books'
      r.connect '/posts/new/:action', :controller => 'subpath_books'
690 691
    end

692 693 694 695
    assert_equal "/books/7/edit", rs.generate(:controller => "subpath_books", :id => 7, :action => "edit")
    assert_equal "/items/15/complete", rs.generate(:controller => "subpath_books", :id => 15, :action => "complete")
    assert_equal "/posts/new/preview", rs.generate(:controller => "subpath_books", :action => "preview")
  end
696

697 698 699
  def test_failed_requirements_raises_exception_with_violated_requirements
    rs.draw do |r|
      r.foo_with_requirement 'foos/:id', :controller=>'foos', :requirements=>{:id=>/\d+/}
700 701
    end

702
    x = setup_for_named_route
703
    assert_raise(ActionController::RoutingError) do
704 705 706
      x.send(:foo_with_requirement_url, "I am Against the requirements")
    end
  end
707

708 709 710 711 712 713 714 715 716
  def test_routes_changed_correctly_after_clear
    ActionController::Base.optimise_named_routes = true
    rs = ::ActionController::Routing::RouteSet.new
    rs.draw do |r|
      r.connect 'ca', :controller => 'ca', :action => "aa"
      r.connect 'cb', :controller => 'cb', :action => "ab"
      r.connect 'cc', :controller => 'cc', :action => "ac"
      r.connect ':controller/:action/:id'
      r.connect ':controller/:action/:id.:format'
717 718
    end

719
    hash = rs.recognize_path "/cc"
720

721 722
    assert_not_nil hash
    assert_equal %w(cc ac), [hash[:controller], hash[:action]]
723

724 725 726 727 728
    rs.draw do |r|
      r.connect 'cb', :controller => 'cb', :action => "ab"
      r.connect 'cc', :controller => 'cc', :action => "ac"
      r.connect ':controller/:action/:id'
      r.connect ':controller/:action/:id.:format'
729 730
    end

731
    hash = rs.recognize_path "/cc"
732

733 734
    assert_not_nil hash
    assert_equal %w(cc ac), [hash[:controller], hash[:action]]
735

736 737
  end
end
738

739
class RouteSetTest < ActiveSupport::TestCase
740 741 742
  def set
    @set ||= ROUTING::RouteSet.new
  end
743

744 745 746
  def request
    @request ||= ActionController::TestRequest.new
  end
747

748 749
  def default_route_set
    @default_route_set ||= begin
J
Joshua Peek 已提交
750 751 752
      set = ROUTING::RouteSet.new
      set.draw do |map|
        map.connect '/:controller/:action/:id/'
753 754 755 756 757
      end
      set
    end
  end

758 759 760 761
  def test_generate_extras
    set.draw { |m| m.connect ':controller/:action/:id' }
    path, extras = set.generate_extras(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world")
    assert_equal "/foo/bar/15", path
762
    assert_equal %w(that this), extras.map { |e| e.to_s }.sort
763
  end
764

765 766 767
  def test_extra_keys
    set.draw { |m| m.connect ':controller/:action/:id' }
    extras = set.extra_keys(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world")
768
    assert_equal %w(that this), extras.map { |e| e.to_s }.sort
769
  end
770

771 772 773 774
  def test_generate_extras_not_first
    set.draw do |map|
      map.connect ':controller/:action/:id.:format'
      map.connect ':controller/:action/:id'
775
    end
776 777
    path, extras = set.generate_extras(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world")
    assert_equal "/foo/bar/15", path
778
    assert_equal %w(that this), extras.map { |e| e.to_s }.sort
779
  end
780

781 782 783 784
  def test_generate_not_first
    set.draw do |map|
      map.connect ':controller/:action/:id.:format'
      map.connect ':controller/:action/:id'
785
    end
786 787
    assert_equal "/foo/bar/15?this=hello", set.generate(:controller => "foo", :action => "bar", :id => 15, :this => "hello")
  end
788

789 790 791 792
  def test_extra_keys_not_first
    set.draw do |map|
      map.connect ':controller/:action/:id.:format'
      map.connect ':controller/:action/:id'
793
    end
794
    extras = set.extra_keys(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world")
795
    assert_equal %w(that this), extras.map { |e| e.to_s }.sort
796
  end
797

798 799 800 801
  def test_draw
    assert_equal 0, set.routes.size
    set.draw do |map|
      map.connect '/hello/world', :controller => 'a', :action => 'b'
802
    end
803 804
    assert_equal 1, set.routes.size
  end
805

806 807 808 809 810 811 812 813 814 815 816
  def test_draw_symbol_controller_name
    assert_equal 0, set.routes.size
    set.draw do |map|
      map.connect '/users/index', :controller => :users, :action => :index
    end
    @request = ActionController::TestRequest.new
    @request.request_uri = '/users/index'
    assert_nothing_raised { set.recognize(@request) }
    assert_equal 1, set.routes.size
  end

817 818 819 820
  def test_named_draw
    assert_equal 0, set.routes.size
    set.draw do |map|
      map.hello '/hello/world', :controller => 'a', :action => 'b'
821
    end
822 823 824
    assert_equal 1, set.routes.size
    assert_equal set.routes.first, set.named_routes[:hello]
  end
825

826 827 828 829
  def test_later_named_routes_take_precedence
    set.draw do |map|
      map.hello '/hello/world', :controller => 'a', :action => 'b'
      map.hello '/hello', :controller => 'a', :action => 'b'
830
    end
831 832
    assert_equal set.routes.last, set.named_routes[:hello]
  end
833

834 835 836 837 838 839
  def setup_named_route_test
    set.draw do |map|
      map.show '/people/:id', :controller => 'people', :action => 'show'
      map.index '/people', :controller => 'people', :action => 'index'
      map.multi '/people/go/:foo/:bar/joe/:id', :controller => 'people', :action => 'multi'
      map.users '/admin/users', :controller => 'admin/users', :action => 'index'
840 841
    end

842 843 844 845
    klass = Class.new(MockController)
    set.install_helpers(klass)
    klass.new(set)
  end
846

847 848 849 850 851 852 853 854 855 856 857 858 859 860 861
  def test_named_route_hash_access_method
    controller = setup_named_route_test

    assert_equal(
      { :controller => 'people', :action => 'show', :id => 5, :use_route => :show, :only_path => false },
      controller.send(:hash_for_show_url, :id => 5))

    assert_equal(
      { :controller => 'people', :action => 'index', :use_route => :index, :only_path => false },
      controller.send(:hash_for_index_url))

    assert_equal(
      { :controller => 'people', :action => 'show', :id => 5, :use_route => :show, :only_path => true },
      controller.send(:hash_for_show_path, :id => 5)
    )
862 863
  end

864 865
  def test_named_route_url_method
    controller = setup_named_route_test
866

867 868
    assert_equal "http://test.host/people/5", controller.send(:show_url, :id => 5)
    assert_equal "/people/5", controller.send(:show_path, :id => 5)
869

870 871
    assert_equal "http://test.host/people", controller.send(:index_url)
    assert_equal "/people", controller.send(:index_path)
872

873 874 875 876
    assert_equal "http://test.host/admin/users", controller.send(:users_url)
    assert_equal '/admin/users', controller.send(:users_path)
    assert_equal '/admin/users', set.generate(controller.send(:hash_for_users_url), {:controller => 'users', :action => 'index'})
  end
877

878 879
  def test_named_route_url_method_with_anchor
    controller = setup_named_route_test
880

881 882
    assert_equal "http://test.host/people/5#location", controller.send(:show_url, :id => 5, :anchor => 'location')
    assert_equal "/people/5#location", controller.send(:show_path, :id => 5, :anchor => 'location')
883

884 885
    assert_equal "http://test.host/people#location", controller.send(:index_url, :anchor => 'location')
    assert_equal "/people#location", controller.send(:index_path, :anchor => 'location')
886

887 888
    assert_equal "http://test.host/admin/users#location", controller.send(:users_url, :anchor => 'location')
    assert_equal '/admin/users#location', controller.send(:users_path, :anchor => 'location')
889

890 891
    assert_equal "http://test.host/people/go/7/hello/joe/5#location",
      controller.send(:multi_url, 7, "hello", 5, :anchor => 'location')
892

893 894
    assert_equal "http://test.host/people/go/7/hello/joe/5?baz=bar#location",
      controller.send(:multi_url, 7, "hello", 5, :baz => "bar", :anchor => 'location')
895

896 897 898
    assert_equal "http://test.host/people?baz=bar#location",
      controller.send(:index_url, :baz => "bar", :anchor => 'location')
  end
899

900 901 902 903
  def test_named_route_url_method_with_port
    controller = setup_named_route_test
    assert_equal "http://test.host:8080/people/5", controller.send(:show_url, 5, :port=>8080)
  end
904

905 906 907 908
  def test_named_route_url_method_with_host
    controller = setup_named_route_test
    assert_equal "http://some.example.com/people/5", controller.send(:show_url, 5, :host=>"some.example.com")
  end
909

910 911 912 913
  def test_named_route_url_method_with_protocol
    controller = setup_named_route_test
    assert_equal "https://test.host/people/5", controller.send(:show_url, 5, :protocol => "https")
  end
914

915 916 917 918 919
  def test_named_route_url_method_with_ordered_parameters
    controller = setup_named_route_test
    assert_equal "http://test.host/people/go/7/hello/joe/5",
      controller.send(:multi_url, 7, "hello", 5)
  end
920

921 922 923 924 925
  def test_named_route_url_method_with_ordered_parameters_and_hash
    controller = setup_named_route_test
    assert_equal "http://test.host/people/go/7/hello/joe/5?baz=bar",
      controller.send(:multi_url, 7, "hello", 5, :baz => "bar")
  end
926

927 928 929 930 931
  def test_named_route_url_method_with_ordered_parameters_and_empty_hash
    controller = setup_named_route_test
    assert_equal "http://test.host/people/go/7/hello/joe/5",
      controller.send(:multi_url, 7, "hello", 5, {})
  end
932

933 934 935 936 937
  def test_named_route_url_method_with_no_positional_arguments
    controller = setup_named_route_test
    assert_equal "http://test.host/people?baz=bar",
      controller.send(:index_url, :baz => "bar")
  end
938

939
  def test_draw_default_route
J
Joshua Peek 已提交
940 941 942
    set.draw do |map|
      map.connect '/:controller/:action/:id'
    end
943

J
Joshua Peek 已提交
944
    assert_equal 1, set.routes.size
945

J
Joshua Peek 已提交
946 947
    assert_equal '/users/show/10', set.generate(:controller => 'users', :action => 'show', :id => 10)
    assert_equal '/users/index/10', set.generate(:controller => 'users', :id => 10)
948

J
Joshua Peek 已提交
949 950
    assert_equal({:controller => 'users', :action => 'index', :id => '10'}, set.recognize_path('/users/index/10'))
    assert_equal({:controller => 'users', :action => 'index', :id => '10'}, set.recognize_path('/users/index/10/'))
951
  end
952

953
  def test_draw_default_route_with_default_controller
J
Joshua Peek 已提交
954 955
    set.draw do |map|
      map.connect '/:controller/:action/:id', :controller => 'users'
956
    end
J
Joshua Peek 已提交
957
    assert_equal({:controller => 'users', :action => 'index'}, set.recognize_path('/'))
958
  end
959

960
  def test_route_with_parameter_shell
J
Joshua Peek 已提交
961 962 963 964
    set.draw do |map|
      map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\d+/
      map.connect '/:controller/:action/:id'
    end
965

J
Joshua Peek 已提交
966 967 968
    assert_equal({:controller => 'pages', :action => 'index'}, set.recognize_path('/pages'))
    assert_equal({:controller => 'pages', :action => 'index'}, set.recognize_path('/pages/index'))
    assert_equal({:controller => 'pages', :action => 'list'}, set.recognize_path('/pages/list'))
969

J
Joshua Peek 已提交
970 971
    assert_equal({:controller => 'pages', :action => 'show', :id => '10'}, set.recognize_path('/pages/show/10'))
    assert_equal({:controller => 'pages', :action => 'show', :id => '10'}, set.recognize_path('/page/10'))
972
  end
973

974
  def test_route_requirements_with_anchor_chars_are_invalid
975
    assert_raise ArgumentError do
976 977
      set.draw do |map|
        map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /^\d+/
978
      end
979
    end
980
    assert_raise ArgumentError do
981 982
      set.draw do |map|
        map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\A\d+/
983 984
      end
    end
985
    assert_raise ArgumentError do
986 987
      set.draw do |map|
        map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\d+$/
988 989
      end
    end
990
    assert_raise ArgumentError do
991 992
      set.draw do |map|
        map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\d+\Z/
993 994
      end
    end
995
    assert_raise ArgumentError do
996
      set.draw do |map|
997
        map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /\d+\z/
998
      end
999 1000
    end
  end
1001

1002
  def test_route_requirements_with_invalid_http_method_is_invalid
1003
    assert_raise ArgumentError do
1004
      set.draw do |map|
1005
        map.connect 'valid/route', :controller => 'pages', :action => 'show', :conditions => {:method => :invalid}
1006 1007
      end
    end
1008
  end
1009

1010 1011 1012 1013 1014 1015 1016 1017
  def test_route_requirements_with_options_method_condition_is_valid
    assert_nothing_raised do
      set.draw do |map|
        map.connect 'valid/route', :controller => 'pages', :action => 'show', :conditions => {:method => :options}
      end
    end
  end

1018
  def test_route_requirements_with_head_method_condition_is_invalid
1019
    assert_raise ArgumentError do
1020
      set.draw do |map|
1021
        map.connect 'valid/route', :controller => 'pages', :action => 'show', :conditions => {:method => :head}
1022
      end
1023 1024
    end
  end
1025

1026 1027 1028 1029 1030
  def test_non_path_route_requirements_match_all
    set.draw do |map|
      map.connect 'page/37s', :controller => 'pages', :action => 'show', :name => /(jamis|david)/
    end
    assert_equal '/page/37s', set.generate(:controller => 'pages', :action => 'show', :name => 'jamis')
1031
    assert_raise ActionController::RoutingError do
1032 1033
      set.generate(:controller => 'pages', :action => 'show', :name => 'not_jamis')
    end
1034
    assert_raise ActionController::RoutingError do
1035 1036 1037
      set.generate(:controller => 'pages', :action => 'show', :name => 'nor_jamis_and_david')
    end
  end
1038

1039 1040 1041 1042
  def test_recognize_with_encoded_id_and_regex
    set.draw do |map|
      map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /[a-zA-Z0-9\+]+/
    end
1043

1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056
    assert_equal({:controller => 'pages', :action => 'show', :id => '10'}, set.recognize_path('/page/10'))
    assert_equal({:controller => 'pages', :action => 'show', :id => 'hello+world'}, set.recognize_path('/page/hello+world'))
  end

  def test_recognize_with_conditions
    set.draw do |map|
      map.with_options(:controller => "people") do |people|
        people.people  "/people",     :action => "index",   :conditions => { :method => :get }
        people.connect "/people",     :action => "create",  :conditions => { :method => :post }
        people.person  "/people/:id", :action => "show",    :conditions => { :method => :get }
        people.connect "/people/:id", :action => "update",  :conditions => { :method => :put }
        people.connect "/people/:id", :action => "destroy", :conditions => { :method => :delete }
      end
1057 1058
    end

1059
    request.request_uri = "/people"
1060 1061 1062 1063
    request.env["REQUEST_METHOD"] = "GET"
    assert_nothing_raised { set.recognize(request) }
    assert_equal("index", request.path_parameters[:action])
    request.recycle!
1064

1065 1066 1067 1068
    request.env["REQUEST_METHOD"] = "POST"
    assert_nothing_raised { set.recognize(request) }
    assert_equal("create", request.path_parameters[:action])
    request.recycle!
1069

1070 1071 1072 1073
    request.env["REQUEST_METHOD"] = "PUT"
    assert_nothing_raised { set.recognize(request) }
    assert_equal("update", request.path_parameters[:action])
    request.recycle!
1074

1075
    assert_raise(ActionController::UnknownHttpMethod) {
1076 1077 1078 1079
      request.env["REQUEST_METHOD"] = "BACON"
      set.recognize(request)
    }
    request.recycle!
1080

1081
    request.request_uri = "/people/5"
1082 1083 1084 1085 1086
    request.env["REQUEST_METHOD"] = "GET"
    assert_nothing_raised { set.recognize(request) }
    assert_equal("show", request.path_parameters[:action])
    assert_equal("5", request.path_parameters[:id])
    request.recycle!
1087

1088 1089 1090 1091 1092
    request.env["REQUEST_METHOD"] = "PUT"
    assert_nothing_raised { set.recognize(request) }
    assert_equal("update", request.path_parameters[:action])
    assert_equal("5", request.path_parameters[:id])
    request.recycle!
1093

1094 1095 1096 1097 1098
    request.env["REQUEST_METHOD"] = "DELETE"
    assert_nothing_raised { set.recognize(request) }
    assert_equal("destroy", request.path_parameters[:action])
    assert_equal("5", request.path_parameters[:id])
    request.recycle!
1099

1100 1101 1102 1103 1104 1105
    begin
      request.env["REQUEST_METHOD"] = "POST"
      set.recognize(request)
      flunk 'Should have raised MethodNotAllowed'
    rescue ActionController::MethodNotAllowed => e
      assert_equal [:get, :put, :delete], e.allowed_methods
1106
    end
1107 1108
    request.recycle!
  end
1109

1110 1111 1112 1113 1114
  def test_recognize_with_alias_in_conditions
    set.draw do |map|
      map.people "/people", :controller => 'people', :action => "index",
        :conditions => { :method => :get }
      map.root   :people
1115
    end
1116

1117 1118 1119 1120 1121
    request.path = "/people"
    request.env["REQUEST_METHOD"] = "GET"
    assert_nothing_raised { set.recognize(request) }
    assert_equal("people", request.path_parameters[:controller])
    assert_equal("index", request.path_parameters[:action])
1122

1123 1124 1125 1126 1127 1128
    request.path = "/"
    request.env["REQUEST_METHOD"] = "GET"
    assert_nothing_raised { set.recognize(request) }
    assert_equal("people", request.path_parameters[:controller])
    assert_equal("index", request.path_parameters[:action])
  end
1129

1130 1131 1132 1133 1134
  def test_typo_recognition
    set.draw do |map|
      map.connect 'articles/:year/:month/:day/:title',
             :controller => 'articles', :action => 'permalink',
             :year => /\d{4}/, :day => /\d{1,2}/, :month => /\d{1,2}/
1135
    end
1136

1137 1138 1139 1140 1141 1142 1143 1144 1145
    request.path = "/articles/2005/11/05/a-very-interesting-article"
    request.env["REQUEST_METHOD"] = "GET"
    assert_nothing_raised { set.recognize(request) }
    assert_equal("permalink", request.path_parameters[:action])
    assert_equal("2005", request.path_parameters[:year])
    assert_equal("11", request.path_parameters[:month])
    assert_equal("05", request.path_parameters[:day])
    assert_equal("a-very-interesting-article", request.path_parameters[:title])
  end
1146

1147 1148 1149 1150
  def test_routing_traversal_does_not_load_extra_classes
    assert !Object.const_defined?("Profiler__"), "Profiler should not be loaded"
    set.draw do |map|
      map.connect '/profile', :controller => 'profile'
1151 1152
    end

1153
    request.path = '/profile'
1154

1155
    set.recognize(request) rescue nil
1156

1157 1158 1159 1160 1161 1162 1163 1164 1165
    assert !Object.const_defined?("Profiler__"), "Profiler should not be loaded"
  end

  def test_recognize_with_conditions_and_format
    set.draw do |map|
      map.with_options(:controller => "people") do |people|
        people.person  "/people/:id", :action => "show",    :conditions => { :method => :get }
        people.connect "/people/:id", :action => "update",  :conditions => { :method => :put }
        people.connect "/people/:id.:_format", :action => "show", :conditions => { :method => :get }
1166
      end
1167 1168
    end

1169
    request.request_uri = "/people/5"
1170 1171 1172 1173 1174 1175 1176 1177 1178 1179
    request.env["REQUEST_METHOD"] = "GET"
    assert_nothing_raised { set.recognize(request) }
    assert_equal("show", request.path_parameters[:action])
    assert_equal("5", request.path_parameters[:id])
    request.recycle!

    request.env["REQUEST_METHOD"] = "PUT"
    assert_nothing_raised { set.recognize(request) }
    assert_equal("update", request.path_parameters[:action])
    request.recycle!
1180

1181
    request.request_uri = "/people/5.png"
1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192
    request.env["REQUEST_METHOD"] = "GET"
    assert_nothing_raised { set.recognize(request) }
    assert_equal("show", request.path_parameters[:action])
    assert_equal("5", request.path_parameters[:id])
    assert_equal("png", request.path_parameters[:_format])
  end

  def test_generate_with_default_action
    set.draw do |map|
      map.connect "/people", :controller => "people"
      map.connect "/people/list", :controller => "people", :action => "list"
1193 1194
    end

1195 1196 1197
    url = set.generate(:controller => "people", :action => "list")
    assert_equal "/people/list", url
  end
1198

1199 1200
  def test_root_map
    set.draw { |map| map.root :controller => "people" }
1201

1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213
    request.path = ""
    request.env["REQUEST_METHOD"] = "GET"
    assert_nothing_raised { set.recognize(request) }
    assert_equal("people", request.path_parameters[:controller])
    assert_equal("index", request.path_parameters[:action])
  end

  def test_namespace
    set.draw do |map|

      map.namespace 'api' do |api|
        api.route 'inventory', :controller => "products", :action => 'inventory'
1214
      end
1215

1216 1217
    end

1218 1219 1220 1221 1222 1223
    request.path = "/api/inventory"
    request.env["REQUEST_METHOD"] = "GET"
    assert_nothing_raised { set.recognize(request) }
    assert_equal("api/products", request.path_parameters[:controller])
    assert_equal("inventory", request.path_parameters[:action])
  end
1224

1225 1226
  def test_namespaced_root_map
    set.draw do |map|
1227

1228 1229
      map.namespace 'api' do |api|
        api.root :controller => "products"
1230 1231 1232 1233
      end

    end

1234 1235 1236 1237 1238 1239
    request.path = "/api"
    request.env["REQUEST_METHOD"] = "GET"
    assert_nothing_raised { set.recognize(request) }
    assert_equal("api/products", request.path_parameters[:controller])
    assert_equal("index", request.path_parameters[:action])
  end
1240

1241 1242 1243 1244
  def test_namespace_with_path_prefix
    set.draw do |map|
      map.namespace 'api', :path_prefix => 'prefix' do |api|
        api.route 'inventory', :controller => "products", :action => 'inventory'
1245
      end
1246 1247
    end

1248 1249 1250 1251 1252 1253
    request.path = "/prefix/inventory"
    request.env["REQUEST_METHOD"] = "GET"
    assert_nothing_raised { set.recognize(request) }
    assert_equal("api/products", request.path_parameters[:controller])
    assert_equal("inventory", request.path_parameters[:action])
  end
1254

1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268
  def test_namespace_with_blank_path_prefix
    set.draw do |map|
      map.namespace 'api', :path_prefix => '' do |api|
        api.route 'inventory', :controller => "products", :action => 'inventory'
      end
    end

    request.path = "/inventory"
    request.env["REQUEST_METHOD"] = "GET"
    assert_nothing_raised { set.recognize(request) }
    assert_equal("api/products", request.path_parameters[:controller])
    assert_equal("inventory", request.path_parameters[:action])
  end

1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279
  def test_generate_changes_controller_module
    set.draw { |map| map.connect ':controller/:action/:id' }
    current = { :controller => "bling/bloop", :action => "bap", :id => 9 }
    url = set.generate({:controller => "foo/bar", :action => "baz", :id => 7}, current)
    assert_equal "/foo/bar/baz/7", url
  end

  def test_id_is_not_impossibly_sticky
    set.draw do |map|
      map.connect 'foo/:number', :controller => "people", :action => "index"
      map.connect ':controller/:action/:id'
1280 1281
    end

1282 1283 1284 1285
    url = set.generate({:controller => "people", :action => "index", :number => 3},
      {:controller => "people", :action => "index", :id => "21"})
    assert_equal "/foo/3", url
  end
1286

1287 1288 1289
  def test_id_is_sticky_when_it_ought_to_be
    set.draw do |map|
      map.connect ':controller/:id/:action'
1290
    end
1291

1292 1293 1294
    url = set.generate({:action => "destroy"}, {:controller => "people", :action => "show", :id => "7"})
    assert_equal "/people/7/destroy", url
  end
1295

1296 1297 1298 1299
  def test_use_static_path_when_possible
    set.draw do |map|
      map.connect 'about', :controller => "welcome", :action => "about"
      map.connect ':controller/:action/:id'
1300 1301
    end

1302 1303 1304 1305
    url = set.generate({:controller => "welcome", :action => "about"},
      {:controller => "welcome", :action => "get", :id => "7"})
    assert_equal "/about", url
  end
1306

1307 1308
  def test_generate
    set.draw { |map| map.connect ':controller/:action/:id' }
1309

1310 1311 1312 1313 1314
    args = { :controller => "foo", :action => "bar", :id => "7", :x => "y" }
    assert_equal "/foo/bar/7?x=y", set.generate(args)
    assert_equal ["/foo/bar/7", [:x]], set.generate_extras(args)
    assert_equal [:x], set.extra_keys(args)
  end
1315

1316 1317
  def test_generate_with_path_prefix
    set.draw { |map| map.connect ':controller/:action/:id', :path_prefix => 'my' }
1318

1319 1320 1321 1322
    args = { :controller => "foo", :action => "bar", :id => "7", :x => "y" }
    assert_equal "/my/foo/bar/7?x=y", set.generate(args)
  end

1323 1324 1325 1326 1327 1328 1329
  def test_generate_with_blank_path_prefix
    set.draw { |map| map.connect ':controller/:action/:id', :path_prefix => '' }

    args = { :controller => "foo", :action => "bar", :id => "7", :x => "y" }
    assert_equal "/foo/bar/7?x=y", set.generate(args)
  end

1330 1331 1332 1333 1334
  def test_named_routes_are_never_relative_to_modules
    set.draw do |map|
      map.connect "/connection/manage/:action", :controller => 'connection/manage'
      map.connect "/connection/connection", :controller => "connection/connection"
      map.family_connection "/connection", :controller => "connection"
1335
    end
1336

1337 1338 1339 1340 1341 1342 1343 1344 1345 1346
    url = set.generate({:controller => "connection"}, {:controller => 'connection/manage'})
    assert_equal "/connection/connection", url

    url = set.generate({:use_route => :family_connection, :controller => "connection"}, {:controller => 'connection/manage'})
    assert_equal "/connection", url
  end

  def test_action_left_off_when_id_is_recalled
    set.draw do |map|
      map.connect ':controller/:action/:id'
1347
    end
1348 1349 1350 1351 1352
    assert_equal '/post', set.generate(
      {:controller => 'post', :action => 'index'},
      {:controller => 'post', :action => 'show', :id => '10'}
    )
  end
1353

1354 1355 1356 1357
  def test_query_params_will_be_shown_when_recalled
    set.draw do |map|
      map.connect 'show_post/:parameter', :controller => 'post', :action => 'show'
      map.connect ':controller/:action/:id'
1358
    end
1359 1360 1361 1362 1363
    assert_equal '/post/edit?parameter=1', set.generate(
      {:action => 'edit', :parameter => 1},
      {:controller => 'post', :action => 'show', :parameter => 1}
    )
  end
1364

1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380
  def test_format_is_not_inherit
    set.draw do |map|
      map.connect '/posts.:format', :controller => 'posts'
    end

    assert_equal '/posts', set.generate(
      {:controller => 'posts'},
      {:controller => 'posts', :action => 'index', :format => 'xml'}
    )

    assert_equal '/posts.xml', set.generate(
      {:controller => 'posts', :format => 'xml'},
      {:controller => 'posts', :action => 'index', :format => 'xml'}
    )
  end

1381 1382 1383 1384 1385 1386
  def test_expiry_determination_should_consider_values_with_to_param
    set.draw { |map| map.connect 'projects/:project_id/:controller/:action' }
    assert_equal '/projects/1/post/show', set.generate(
      {:action => 'show', :project_id => 1},
      {:controller => 'post', :action => 'show', :project_id => '1'})
  end
1387

1388 1389 1390 1391
  def test_named_route_in_nested_resource
    set.draw do |map|
      map.resources :projects do |project|
        project.milestones 'milestones', :controller => 'milestones', :action => 'index'
1392 1393
      end
    end
1394

1395 1396 1397 1398 1399 1400
    request.path = "/projects/1/milestones"
    request.env["REQUEST_METHOD"] = "GET"
    assert_nothing_raised { set.recognize(request) }
    assert_equal("milestones", request.path_parameters[:controller])
    assert_equal("index", request.path_parameters[:action])
  end
1401

1402 1403 1404 1405 1406
  def test_setting_root_in_namespace_using_symbol
    assert_nothing_raised do
      set.draw do |map|
        map.namespace :admin do |admin|
          admin.root :controller => 'home'
1407 1408 1409
        end
      end
    end
1410
  end
1411

1412 1413 1414 1415 1416
  def test_setting_root_in_namespace_using_string
    assert_nothing_raised do
      set.draw do |map|
        map.namespace 'admin' do |admin|
          admin.root :controller => 'home'
1417 1418 1419
        end
      end
    end
1420
  end
1421

1422
  def test_route_requirements_with_unsupported_regexp_options_must_error
1423
    assert_raise ArgumentError do
1424 1425 1426
      set.draw do |map|
        map.connect 'page/:name', :controller => 'pages',
          :action => 'show',
1427
          :requirements => {:name => /(david|jamis)/m}
1428
      end
1429
    end
1430
  end
1431

1432 1433
  def test_route_requirements_with_supported_options_must_not_error
    assert_nothing_raised do
1434 1435 1436 1437 1438 1439
      set.draw do |map|
        map.connect 'page/:name', :controller => 'pages',
          :action => 'show',
          :requirements => {:name => /(david|jamis)/i}
      end
    end
1440
    assert_nothing_raised do
1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451
      set.draw do |map|
        map.connect 'page/:name', :controller => 'pages',
          :action => 'show',
          :requirements => {:name => / # Desperately overcommented regexp
                                      ( #Either
                                       david #The Creator
                                      | #Or
                                        jamis #The Deployer
                                      )/x}
      end
    end
1452
  end
1453

1454 1455 1456 1457 1458 1459 1460
  def test_route_requirement_recognize_with_ignore_case
    set.draw do |map|
      map.connect 'page/:name', :controller => 'pages',
        :action => 'show',
        :requirements => {:name => /(david|jamis)/i}
    end
    assert_equal({:controller => 'pages', :action => 'show', :name => 'jamis'}, set.recognize_path('/page/jamis'))
1461
    assert_raise ActionController::RoutingError do
1462
      set.recognize_path('/page/davidjamis')
1463
    end
1464 1465
    assert_equal({:controller => 'pages', :action => 'show', :name => 'DAVID'}, set.recognize_path('/page/DAVID'))
  end
1466

1467 1468 1469 1470 1471 1472 1473 1474
  def test_route_requirement_generate_with_ignore_case
    set.draw do |map|
      map.connect 'page/:name', :controller => 'pages',
        :action => 'show',
        :requirements => {:name => /(david|jamis)/i}
    end
    url = set.generate({:controller => 'pages', :action => 'show', :name => 'david'})
    assert_equal "/page/david", url
1475
    assert_raise ActionController::RoutingError do
1476
      url = set.generate({:controller => 'pages', :action => 'show', :name => 'davidjamis'})
J
Jeremy Kemper 已提交
1477
    end
1478 1479 1480
    url = set.generate({:controller => 'pages', :action => 'show', :name => 'JAMIS'})
    assert_equal "/page/JAMIS", url
  end
J
Jeremy Kemper 已提交
1481

1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494
  def test_route_requirement_recognize_with_extended_syntax
    set.draw do |map|
      map.connect 'page/:name', :controller => 'pages',
        :action => 'show',
        :requirements => {:name => / # Desperately overcommented regexp
                                    ( #Either
                                     david #The Creator
                                    | #Or
                                      jamis #The Deployer
                                    )/x}
    end
    assert_equal({:controller => 'pages', :action => 'show', :name => 'jamis'}, set.recognize_path('/page/jamis'))
    assert_equal({:controller => 'pages', :action => 'show', :name => 'david'}, set.recognize_path('/page/david'))
1495
    assert_raise ActionController::RoutingError do
1496 1497
      set.recognize_path('/page/david #The Creator')
    end
1498
    assert_raise ActionController::RoutingError do
1499
      set.recognize_path('/page/David')
1500 1501
    end
  end
1502

1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515
  def test_route_requirement_generate_with_extended_syntax
    set.draw do |map|
      map.connect 'page/:name', :controller => 'pages',
        :action => 'show',
        :requirements => {:name => / # Desperately overcommented regexp
                                    ( #Either
                                     david #The Creator
                                    | #Or
                                      jamis #The Deployer
                                    )/x}
    end
    url = set.generate({:controller => 'pages', :action => 'show', :name => 'david'})
    assert_equal "/page/david", url
1516
    assert_raise ActionController::RoutingError do
1517 1518
      url = set.generate({:controller => 'pages', :action => 'show', :name => 'davidjamis'})
    end
1519
    assert_raise ActionController::RoutingError do
1520 1521 1522
      url = set.generate({:controller => 'pages', :action => 'show', :name => 'JAMIS'})
    end
  end
1523

1524 1525 1526 1527 1528 1529 1530 1531 1532 1533
  def test_route_requirement_generate_with_xi_modifiers
    set.draw do |map|
      map.connect 'page/:name', :controller => 'pages',
        :action => 'show',
        :requirements => {:name => / # Desperately overcommented regexp
                                    ( #Either
                                     david #The Creator
                                    | #Or
                                      jamis #The Deployer
                                    )/xi}
1534
    end
1535 1536 1537
    url = set.generate({:controller => 'pages', :action => 'show', :name => 'JAMIS'})
    assert_equal "/page/JAMIS", url
  end
1538

1539 1540 1541 1542 1543 1544 1545 1546 1547 1548
  def test_route_requirement_recognize_with_xi_modifiers
    set.draw do |map|
      map.connect 'page/:name', :controller => 'pages',
        :action => 'show',
        :requirements => {:name => / # Desperately overcommented regexp
                                    ( #Either
                                     david #The Creator
                                    | #Or
                                      jamis #The Deployer
                                    )/xi}
1549
    end
1550 1551
    assert_equal({:controller => 'pages', :action => 'show', :name => 'JAMIS'}, set.recognize_path('/page/JAMIS'))
  end
1552 1553 1554 1555 1556 1557 1558 1559 1560 1561

  def test_routes_with_symbols
    set.draw do |map|
      map.connect 'unnamed', :controller => :pages, :action => :show, :name => :as_symbol
      map.named   'named',   :controller => :pages, :action => :show, :name => :as_symbol
    end
    assert_equal({:controller => 'pages', :action => 'show', :name => :as_symbol}, set.recognize_path('/unnamed'))
    assert_equal({:controller => 'pages', :action => 'show', :name => :as_symbol}, set.recognize_path('/named'))
  end

1562
  def test_interpolation_chunk_should_respect_raw
J
Joshua Peek 已提交
1563 1564
    set.draw do |map|
      map.connect '/Hello World', :controller => 'hello'
1565
    end
J
Joshua Peek 已提交
1566 1567 1568 1569

    assert_equal '/Hello%20World', set.generate(:controller => 'hello')
    assert_equal({:controller => "hello", :action => "index"}, set.recognize_path('/Hello World'))
    assert_raise(ActionController::RoutingError) { set.recognize_path('/Hello%20World') }
1570 1571 1572
  end

  def test_value_should_not_be_double_unescaped
J
Joshua Peek 已提交
1573 1574
    set.draw do |map|
      map.connect '/Карта', :controller => 'foo'
1575
    end
J
Joshua Peek 已提交
1576 1577 1578 1579

    assert_equal '/%D0%9A%D0%B0%D1%80%D1%82%D0%B0', set.generate(:controller => 'foo')
    assert_equal({:controller => "foo", :action => "index"}, set.recognize_path('/Карта'))
    assert_raise(ActionController::RoutingError) { set.recognize_path('/%D0%9A%D0%B0%D1%80%D1%82%D0%B0') }
1580 1581 1582
  end

  def test_regexp_chunk_should_escape_specials
J
Joshua Peek 已提交
1583 1584 1585 1586
    set.draw do |map|
      map.connect '/Hello*World', :controller => 'foo'
      map.connect '/HelloWorld', :controller => 'bar'
    end
1587

J
Joshua Peek 已提交
1588 1589
    assert_equal '/Hello*World', set.generate(:controller => 'foo')
    assert_equal '/HelloWorld', set.generate(:controller => 'bar')
1590

J
Joshua Peek 已提交
1591 1592
    assert_equal({:controller => "foo", :action => "index"}, set.recognize_path('/Hello*World'))
    assert_equal({:controller => "bar", :action => "index"}, set.recognize_path('/HelloWorld'))
1593 1594 1595
  end

  def test_regexp_chunk_should_add_question_mark_for_optionals
J
Joshua Peek 已提交
1596 1597 1598 1599
    set.draw do |map|
      map.connect '/', :controller => 'foo'
      map.connect '/hello', :controller => 'bar'
    end
1600

J
Joshua Peek 已提交
1601 1602
    assert_equal '/', set.generate(:controller => 'foo')
    assert_equal '/hello', set.generate(:controller => 'bar')
1603

J
Joshua Peek 已提交
1604 1605
    assert_equal({:controller => "foo", :action => "index"}, set.recognize_path('/'))
    assert_equal({:controller => "bar", :action => "index"}, set.recognize_path('/hello'))
1606 1607 1608
  end

  def test_assign_route_options_with_anchor_chars
J
Joshua Peek 已提交
1609 1610 1611
    set.draw do |map|
      map.connect '/cars/:action/:person/:car/', :controller => 'cars'
    end
1612

J
Joshua Peek 已提交
1613
    assert_equal '/cars/buy/1/2', set.generate(:controller => 'cars', :action => 'buy', :person => '1', :car => '2')
1614

J
Joshua Peek 已提交
1615
    assert_equal({:controller => "cars", :action => "buy", :person => "1", :car => "2"}, set.recognize_path('/cars/buy/1/2'))
1616 1617 1618
  end

  def test_segmentation_of_dot_path
J
Joshua Peek 已提交
1619 1620 1621
    set.draw do |map|
      map.connect '/books/:action.rss', :controller => 'books'
    end
1622

J
Joshua Peek 已提交
1623
    assert_equal '/books/list.rss', set.generate(:controller => 'books', :action => 'list')
1624

J
Joshua Peek 已提交
1625
    assert_equal({:controller => "books", :action => "list"}, set.recognize_path('/books/list.rss'))
1626 1627 1628
  end

  def test_segmentation_of_dynamic_dot_path
J
Joshua Peek 已提交
1629 1630 1631
    set.draw do |map|
      map.connect '/books/:action.:format', :controller => 'books'
    end
1632

J
Joshua Peek 已提交
1633 1634 1635 1636
    assert_equal '/books/list.rss', set.generate(:controller => 'books', :action => 'list', :format => 'rss')
    assert_equal '/books/list.xml', set.generate(:controller => 'books', :action => 'list', :format => 'xml')
    assert_equal '/books/list', set.generate(:controller => 'books', :action => 'list')
    assert_equal '/books', set.generate(:controller => 'books', :action => 'index')
1637

J
Joshua Peek 已提交
1638 1639 1640 1641
    assert_equal({:controller => "books", :action => "list", :format => "rss"}, set.recognize_path('/books/list.rss'))
    assert_equal({:controller => "books", :action => "list", :format => "xml"}, set.recognize_path('/books/list.xml'))
    assert_equal({:controller => "books", :action => "list"}, set.recognize_path('/books/list'))
    assert_equal({:controller => "books", :action => "index"}, set.recognize_path('/books'))
1642 1643 1644
  end

  def test_slashes_are_implied
1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658
    ['/:controller/:action/:id/', '/:controller/:action/:id',
      ':controller/:action/:id', '/:controller/:action/:id/'
    ].each do |path|
      @set = nil
      set.draw { |map| map.connect(path) }

      assert_equal '/content', set.generate(:controller => 'content', :action => 'index')
      assert_equal '/content/list', set.generate(:controller => 'content', :action => 'list')
      assert_equal '/content/show/1', set.generate(:controller => 'content', :action => 'show', :id => '1')

      assert_equal({:controller => "content", :action => "index"}, set.recognize_path('/content'))
      assert_equal({:controller => "content", :action => "index"}, set.recognize_path('/content/index'))
      assert_equal({:controller => "content", :action => "list"}, set.recognize_path('/content/list'))
      assert_equal({:controller => "content", :action => "show", :id => "1"}, set.recognize_path('/content/show/1'))
1659 1660 1661 1662
    end
  end

  def test_default_route_recognition
J
Joshua Peek 已提交
1663 1664 1665
    expected = {:controller => 'pages', :action => 'show', :id => '10'}
    assert_equal expected, default_route_set.recognize_path('/pages/show/10')
    assert_equal expected, default_route_set.recognize_path('/pages/show/10/')
1666 1667

    expected[:id] = 'jamis'
J
Joshua Peek 已提交
1668
    assert_equal expected, default_route_set.recognize_path('/pages/show/jamis/')
1669 1670

    expected.delete :id
J
Joshua Peek 已提交
1671 1672
    assert_equal expected, default_route_set.recognize_path('/pages/show')
    assert_equal expected, default_route_set.recognize_path('/pages/show/')
1673 1674

    expected[:action] = 'index'
J
Joshua Peek 已提交
1675 1676
    assert_equal expected, default_route_set.recognize_path('/pages/')
    assert_equal expected, default_route_set.recognize_path('/pages')
1677 1678

    assert_raise(ActionController::RoutingError) { default_route_set.recognize_path('/') }
J
Joshua Peek 已提交
1679
    assert_raise(ActionController::RoutingError) { default_route_set.recognize_path('/pages/how/goood/it/is/to/be/free') }
1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694
  end

  def test_default_route_should_omit_default_action
    assert_equal '/accounts', default_route_set.generate({:controller => 'accounts', :action => 'index'})
  end

  def test_default_route_should_include_default_action_when_id_present
    assert_equal '/accounts/index/20', default_route_set.generate({:controller => 'accounts', :action => 'index', :id => '20'})
  end

  def test_default_route_should_work_with_action_but_no_id
    assert_equal '/accounts/list_all', default_route_set.generate({:controller => 'accounts', :action => 'list_all'})
  end

  def test_default_route_should_uri_escape_pluses
J
Joshua Peek 已提交
1695 1696 1697 1698
    expected = { :controller => 'pages', :action => 'show', :id => 'hello world' }
    assert_equal expected, default_route_set.recognize_path('/pages/show/hello world')
    assert_equal expected, default_route_set.recognize_path('/pages/show/hello%20world')
    assert_equal '/pages/show/hello%20world', default_route_set.generate(expected, expected)
1699 1700

    expected[:id] = 'hello+world'
J
Joshua Peek 已提交
1701 1702 1703
    assert_equal expected, default_route_set.recognize_path('/pages/show/hello+world')
    assert_equal expected, default_route_set.recognize_path('/pages/show/hello%2Bworld')
    assert_equal '/pages/show/hello+world', default_route_set.generate(expected, expected)
1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751
  end

  def test_parameter_shell
    page_url = ROUTING::Route.new
    page_url.requirements = {:controller => 'pages', :action => 'show', :id => /\d+/}
    assert_equal({:controller => 'pages', :action => 'show'}, page_url.parameter_shell)
  end

  def test_defaults
    route = ROUTING::RouteBuilder.new.build '/users/:id.:format', :controller => "users", :action => "show", :format => "html"
    assert_equal(
      { :controller => "users", :action => "show", :format => "html" },
      route.defaults)
  end

  def test_builder_complains_without_controller
    assert_raise(ArgumentError) do
      ROUTING::RouteBuilder.new.build '/contact', :contoller => "contact", :action => "index"
    end
  end

  def test_build_empty_query_string
    assert_equal '/foo', default_route_set.generate({:controller => 'foo'})
  end

  def test_build_query_string_with_nil_value
    assert_equal '/foo', default_route_set.generate({:controller => 'foo', :x => nil})
  end

  def test_simple_build_query_string
    assert_equal '/foo?x=1&y=2', default_route_set.generate({:controller => 'foo', :x => '1', :y => '2'})
  end

  def test_convert_ints_build_query_string
    assert_equal '/foo?x=1&y=2', default_route_set.generate({:controller => 'foo', :x => 1, :y => 2})
  end

  def test_escape_spaces_build_query_string
    assert_equal '/foo?x=hello+world&y=goodbye+world', default_route_set.generate({:controller => 'foo', :x => 'hello world', :y => 'goodbye world'})
  end

  def test_expand_array_build_query_string
    assert_equal '/foo?x%5B%5D=1&x%5B%5D=2', default_route_set.generate({:controller => 'foo', :x => [1, 2]})
  end

  def test_escape_spaces_build_query_string_selected_keys
    assert_equal '/foo?x=hello+world', default_route_set.generate({:controller => 'foo', :x => 'hello world'})
  end
1752
end
1753

1754 1755 1756
class RouteLoadingTest < Test::Unit::TestCase
  def setup
    routes.instance_variable_set '@routes_last_modified', nil
1757 1758
    Object.remove_const(:RAILS_ROOT) if defined?(::RAILS_ROOT)
    Object.const_set :RAILS_ROOT, '.'
1759
    routes.add_configuration_file(File.join(RAILS_ROOT, 'config', 'routes.rb'))
1760

1761 1762
    @stat = stub_everything
  end
1763

1764 1765 1766 1767
  def teardown
    ActionController::Routing::Routes.configuration_files.clear
    Object.send :remove_const, :RAILS_ROOT
  end
1768

1769 1770 1771
  def test_load
    File.expects(:stat).returns(@stat)
    routes.expects(:load).with(regexp_matches(/routes\.rb$/))
1772

1773 1774
    routes.reload
  end
1775

1776 1777 1778 1779
  def test_no_reload_when_not_modified
    @stat.expects(:mtime).times(2).returns(1)
    File.expects(:stat).times(2).returns(@stat)
    routes.expects(:load).with(regexp_matches(/routes\.rb$/)).at_most_once
1780

1781 1782
    2.times { routes.reload }
  end
1783

1784 1785 1786 1787
  def test_reload_when_modified
    @stat.expects(:mtime).at_least(2).returns(1, 2)
    File.expects(:stat).at_least(2).returns(@stat)
    routes.expects(:load).with(regexp_matches(/routes\.rb$/)).times(2)
1788

1789 1790
    2.times { routes.reload }
  end
1791

1792 1793 1794 1795
  def test_bang_forces_reload
    @stat.expects(:mtime).at_least(2).returns(1)
    File.expects(:stat).at_least(2).returns(@stat)
    routes.expects(:load).with(regexp_matches(/routes\.rb$/)).times(2)
1796

1797 1798
    2.times { routes.reload! }
  end
1799

1800 1801 1802
  def test_adding_inflections_forces_reload
    ActiveSupport::Inflector::Inflections.instance.expects(:uncountable).with('equipment')
    routes.expects(:reload!)
1803

1804 1805
    ActiveSupport::Inflector.inflections { |inflect| inflect.uncountable('equipment') }
  end
1806

1807 1808 1809 1810 1811
  def test_load_with_configuration
    routes.configuration_files.clear
    routes.add_configuration_file("foobarbaz")
    File.expects(:stat).returns(@stat)
    routes.expects(:load).with("foobarbaz")
1812

1813
    routes.reload
1814
  end
J
Joshua Peek 已提交
1815

1816 1817
  def test_load_multiple_configurations
    routes.add_configuration_file("engines.rb")
J
Joshua Peek 已提交
1818

1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830
    File.expects(:stat).at_least_once.returns(@stat)

    routes.expects(:load).with('./config/routes.rb')
    routes.expects(:load).with('engines.rb')

    routes.reload
  end

  private
    def routes
      ActionController::Routing::Routes
    end
1831
end