mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
2177 lines
76 KiB
Ruby
2177 lines
76 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "abstract_unit"
|
|
require "controller/fake_controllers"
|
|
require "active_support/core_ext/object/with_options"
|
|
require "active_support/core_ext/object/json"
|
|
|
|
class MilestonesController < ActionController::Base
|
|
def index() head :ok end
|
|
alias_method :show, :index
|
|
end
|
|
|
|
# See RFC 3986, section 3.3 for allowed path characters.
|
|
class UriReservedCharactersRoutingTest < ActiveSupport::TestCase
|
|
include RoutingTestHelpers
|
|
|
|
def setup
|
|
@set = ActionDispatch::Routing::RouteSet.new
|
|
@set.draw do
|
|
ActiveSupport::Deprecation.silence do
|
|
get ":controller/:action/:variable/*additional"
|
|
end
|
|
end
|
|
|
|
safe, unsafe = %w(: @ & = + $ , ;), %w(^ ? # [ ])
|
|
hex = unsafe.map { |char| "%" + char.unpack1("H2").upcase }
|
|
|
|
@segment = "#{safe.join}#{unsafe.join}"
|
|
@escaped = "#{safe.join}#{hex.join}"
|
|
end
|
|
|
|
def test_route_generation_escapes_unsafe_path_characters
|
|
assert_equal "/content/act#{@escaped}ion/var#{@escaped}iable/add#{@escaped}itional-1/add#{@escaped}itional-2",
|
|
url_for(@set,
|
|
controller: "content",
|
|
action: "act#{@segment}ion",
|
|
variable: "var#{@segment}iable",
|
|
additional: ["add#{@segment}itional-1", "add#{@segment}itional-2"])
|
|
end
|
|
|
|
def test_route_recognition_unescapes_path_components
|
|
options = { controller: "content",
|
|
action: "act#{@segment}ion",
|
|
variable: "var#{@segment}iable",
|
|
additional: "add#{@segment}itional-1/add#{@segment}itional-2" }
|
|
assert_equal options, @set.recognize_path("/content/act#{@escaped}ion/var#{@escaped}iable/add#{@escaped}itional-1/add#{@escaped}itional-2")
|
|
end
|
|
|
|
def test_route_generation_allows_passing_non_string_values_to_generated_helper
|
|
assert_equal "/content/action/variable/1/2",
|
|
url_for(@set,
|
|
controller: "content",
|
|
action: "action",
|
|
variable: "variable",
|
|
additional: [1, 2])
|
|
end
|
|
end
|
|
|
|
class MockController
|
|
def self.build(helpers, additional_options = {})
|
|
Class.new do
|
|
define_method :url_options do
|
|
options = super()
|
|
options[:protocol] ||= "http"
|
|
options[:host] ||= "test.host"
|
|
options.merge(additional_options)
|
|
end
|
|
|
|
include helpers
|
|
end
|
|
end
|
|
end
|
|
|
|
class LegacyRouteSetTests < ActiveSupport::TestCase
|
|
include RoutingTestHelpers
|
|
include ActionDispatch::RoutingVerbs
|
|
|
|
attr_reader :rs
|
|
attr_accessor :controller
|
|
alias :routes :rs
|
|
|
|
def setup
|
|
@rs = make_set
|
|
@response = nil
|
|
end
|
|
|
|
def test_symbols_with_dashes
|
|
rs.draw do
|
|
get "/:artist/:song-omg", to: lambda { |env|
|
|
resp = ActiveSupport::JSON.encode ActionDispatch::Request.new(env).path_parameters
|
|
[200, {}, [resp]]
|
|
}
|
|
end
|
|
|
|
hash = ActiveSupport::JSON.decode get(URI("http://example.org/journey/faithfully-omg"))
|
|
assert_equal({ "artist" => "journey", "song" => "faithfully" }, hash)
|
|
end
|
|
|
|
def test_id_encoding
|
|
rs.draw do
|
|
get "/journey/:id", to: lambda { |env|
|
|
param = ActionDispatch::Request.new(env).path_parameters
|
|
resp = ActiveSupport::JSON.encode param
|
|
[200, {}, [resp]]
|
|
}
|
|
end
|
|
|
|
# The encoding of the URL in production is *binary*, so we add a
|
|
# .b here.
|
|
hash = ActiveSupport::JSON.decode get(URI("http://example.org/journey/%E5%A4%AA%E9%83%8E".b))
|
|
assert_equal({ "id" => "太郎" }, hash)
|
|
assert_equal ::Encoding::UTF_8, hash["id"].encoding
|
|
end
|
|
|
|
def test_id_with_dash
|
|
rs.draw do
|
|
get "/journey/:id", to: lambda { |env|
|
|
resp = ActiveSupport::JSON.encode ActionDispatch::Request.new(env).path_parameters
|
|
[200, {}, [resp]]
|
|
}
|
|
end
|
|
|
|
hash = ActiveSupport::JSON.decode get(URI("http://example.org/journey/faithfully-omg"))
|
|
assert_equal({ "id" => "faithfully-omg" }, hash)
|
|
end
|
|
|
|
def test_dash_with_custom_regexp
|
|
rs.draw do
|
|
get "/:artist/:song-omg", constraints: { song: /\d+/ }, to: lambda { |env|
|
|
resp = ActiveSupport::JSON.encode ActionDispatch::Request.new(env).path_parameters
|
|
[200, {}, [resp]]
|
|
}
|
|
end
|
|
|
|
hash = ActiveSupport::JSON.decode get(URI("http://example.org/journey/123-omg"))
|
|
assert_equal({ "artist" => "journey", "song" => "123" }, hash)
|
|
assert_equal "Not Found", get(URI("http://example.org/journey/faithfully-omg"))
|
|
end
|
|
|
|
def test_pre_dash
|
|
rs.draw do
|
|
get "/:artist/omg-:song", to: lambda { |env|
|
|
resp = ActiveSupport::JSON.encode ActionDispatch::Request.new(env).path_parameters
|
|
[200, {}, [resp]]
|
|
}
|
|
end
|
|
|
|
hash = ActiveSupport::JSON.decode get(URI("http://example.org/journey/omg-faithfully"))
|
|
assert_equal({ "artist" => "journey", "song" => "faithfully" }, hash)
|
|
end
|
|
|
|
def test_pre_dash_with_custom_regexp
|
|
rs.draw do
|
|
get "/:artist/omg-:song", constraints: { song: /\d+/ }, to: lambda { |env|
|
|
resp = ActiveSupport::JSON.encode ActionDispatch::Request.new(env).path_parameters
|
|
[200, {}, [resp]]
|
|
}
|
|
end
|
|
|
|
hash = ActiveSupport::JSON.decode get(URI("http://example.org/journey/omg-123"))
|
|
assert_equal({ "artist" => "journey", "song" => "123" }, hash)
|
|
assert_equal "Not Found", get(URI("http://example.org/journey/omg-faithfully"))
|
|
end
|
|
|
|
def test_star_paths_are_greedy
|
|
rs.draw do
|
|
get "/*path", to: lambda { |env|
|
|
x = env["action_dispatch.request.path_parameters"][:path]
|
|
[200, {}, [x]]
|
|
}, format: false
|
|
end
|
|
|
|
u = URI("http://example.org/foo/bar.html")
|
|
assert_equal u.path.delete_prefix("/"), get(u)
|
|
end
|
|
|
|
def test_star_paths_are_greedy_but_not_too_much
|
|
rs.draw do
|
|
get "/*path", to: lambda { |env|
|
|
x = ActiveSupport::JSON.encode env["action_dispatch.request.path_parameters"]
|
|
[200, {}, [x]]
|
|
}
|
|
end
|
|
|
|
expected = { "path" => "foo/bar", "format" => "html" }
|
|
u = URI("http://example.org/foo/bar.html")
|
|
assert_equal expected, ActiveSupport::JSON.decode(get(u))
|
|
end
|
|
|
|
def test_optional_star_paths_are_greedy
|
|
rs.draw do
|
|
get "/(*filters)", to: lambda { |env|
|
|
x = env["action_dispatch.request.path_parameters"][:filters]
|
|
[200, {}, [x]]
|
|
}, format: false
|
|
end
|
|
|
|
u = URI("http://example.org/ne_27.065938,-80.6092/sw_25.489856,-82.542794")
|
|
assert_equal u.path.delete_prefix("/"), get(u)
|
|
end
|
|
|
|
def test_optional_star_paths_are_greedy_but_not_too_much
|
|
rs.draw do
|
|
get "/(*filters)", to: lambda { |env|
|
|
x = ActiveSupport::JSON.encode env["action_dispatch.request.path_parameters"]
|
|
[200, {}, [x]]
|
|
}
|
|
end
|
|
|
|
expected = { "filters" => "ne_27.065938,-80.6092/sw_25.489856,-82",
|
|
"format" => "542794" }
|
|
u = URI("http://example.org/ne_27.065938,-80.6092/sw_25.489856,-82.542794")
|
|
assert_equal expected, ActiveSupport::JSON.decode(get(u))
|
|
end
|
|
|
|
def test_regexp_precedence
|
|
rs.draw do
|
|
get "/whois/:domain", constraints: {
|
|
domain: /\w+\.[\w.]+/ },
|
|
to: lambda { |env| [200, {}, %w{regexp}] }
|
|
|
|
get "/whois/:id", to: lambda { |env| [200, {}, %w{id}] }
|
|
end
|
|
|
|
assert_equal "regexp", get(URI("http://example.org/whois/example.org"))
|
|
assert_equal "id", get(URI("http://example.org/whois/123"))
|
|
end
|
|
|
|
def test_class_and_lambda_constraints
|
|
subdomain = Class.new {
|
|
def matches?(request)
|
|
request.subdomain.present? && request.subdomain != "clients"
|
|
end
|
|
}
|
|
|
|
rs.draw do
|
|
get "/", constraints: subdomain.new,
|
|
to: lambda { |env| [200, {}, %w{default}] }
|
|
get "/", constraints: { subdomain: "clients" },
|
|
to: lambda { |env| [200, {}, %w{clients}] }
|
|
end
|
|
|
|
assert_equal "default", get(URI("http://www.example.org/"))
|
|
assert_equal "clients", get(URI("http://clients.example.org/"))
|
|
end
|
|
|
|
def test_format_symbol_constraints
|
|
rs.draw do
|
|
get "/api", constraints: { format: :json },
|
|
to: lambda { |env| [200, {}, %w{json}] }
|
|
get "/api", constraints: { format: :xml },
|
|
to: lambda { |env| [200, {}, %w{xml}] }
|
|
end
|
|
|
|
assert_equal "json", get(URI("http://www.example.org/api.json"))
|
|
assert_equal "xml", get(URI("http://clients.example.org/api.xml"))
|
|
end
|
|
|
|
def test_lambda_constraints
|
|
rs.draw do
|
|
get "/", constraints: lambda { |req|
|
|
req.subdomain.present? && req.subdomain != "clients" },
|
|
to: lambda { |env| [200, {}, %w{default}] }
|
|
|
|
get "/", constraints: lambda { |req|
|
|
req.subdomain.present? && req.subdomain == "clients" },
|
|
to: lambda { |env| [200, {}, %w{clients}] }
|
|
end
|
|
|
|
assert_equal "default", get(URI("http://www.example.org/"))
|
|
assert_equal "clients", get(URI("http://clients.example.org/"))
|
|
end
|
|
|
|
def test_scoped_lambda
|
|
scope_called = false
|
|
rs.draw do
|
|
scope "/foo", constraints: lambda { |req| scope_called = true } do
|
|
get "/", to: lambda { |env| [200, {}, %w{default}] }
|
|
end
|
|
end
|
|
|
|
assert_equal "default", get(URI("http://www.example.org/foo/"))
|
|
assert scope_called, "scope constraint should be called"
|
|
end
|
|
|
|
def test_scoped_lambda_with_get_lambda
|
|
inner_called = false
|
|
|
|
rs.draw do
|
|
scope "/foo", constraints: lambda { |req| flunk "should not be called" } do
|
|
get "/", constraints: lambda { |req| inner_called = true },
|
|
to: lambda { |env| [200, {}, %w{default}] }
|
|
end
|
|
end
|
|
|
|
assert_equal "default", get(URI("http://www.example.org/foo/"))
|
|
assert inner_called, "inner constraint should be called"
|
|
end
|
|
|
|
def test_empty_string_match
|
|
rs.draw do
|
|
get "/:username", constraints: { username: /[^\/]+/ },
|
|
to: lambda { |e| [200, {}, ["foo"]] }
|
|
end
|
|
assert_equal "Not Found", get(URI("http://example.org/"))
|
|
assert_equal "foo", get(URI("http://example.org/hello"))
|
|
end
|
|
|
|
def test_non_greedy_glob_regexp
|
|
params = nil
|
|
rs.draw do
|
|
get "/posts/:id(/*filters)", constraints: { filters: /.+?/ },
|
|
to: lambda { |e|
|
|
params = e["action_dispatch.request.path_parameters"]
|
|
[200, {}, ["foo"]]
|
|
}
|
|
end
|
|
assert_equal "foo", get(URI("http://example.org/posts/1/foo.js"))
|
|
assert_equal({ id: "1", filters: "foo", format: "js" }, params)
|
|
end
|
|
|
|
def test_specific_controller_action_failure
|
|
rs.draw do
|
|
mount lambda { } => "/foo"
|
|
end
|
|
|
|
assert_raises(ActionController::UrlGenerationError) do
|
|
url_for(rs, controller: "omg", action: "lol")
|
|
end
|
|
end
|
|
|
|
def test_default_setup
|
|
rs.draw { ActiveSupport::Deprecation.silence { get "/: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", url_for(rs, controller: "admin/user", action: "show", id: 10)
|
|
|
|
get URI("http://test.host/admin/user/list/10")
|
|
|
|
assert_equal({ controller: "admin/user", action: "list", id: "10" },
|
|
controller.request.path_parameters)
|
|
|
|
assert_equal "/admin/user/show", controller.url_for(action: "show", only_path: true)
|
|
assert_equal "/admin/user/list/10", controller.url_for(only_path: true)
|
|
|
|
assert_equal "/admin/stuff", controller.url_for(controller: "stuff", only_path: true)
|
|
assert_equal "/stuff", controller.url_for(controller: "/stuff", only_path: true)
|
|
end
|
|
|
|
def test_route_with_colon_first
|
|
rs.draw do
|
|
ActiveSupport::Deprecation.silence do
|
|
get "/:controller/:action/:id", action: "index", id: nil
|
|
end
|
|
|
|
get ":url", controller: "content", action: "translate"
|
|
end
|
|
|
|
assert_equal({ controller: "content", action: "translate", url: "example" }, rs.recognize_path("/example"))
|
|
end
|
|
|
|
def test_route_with_regexp_for_action
|
|
rs.draw { ActiveSupport::Deprecation.silence { get "/:controller/:action", action: /auth[-|_].+/ } }
|
|
|
|
assert_equal({ action: "auth_google", controller: "content" }, rs.recognize_path("/content/auth_google"))
|
|
assert_equal({ action: "auth-twitter", controller: "content" }, rs.recognize_path("/content/auth-twitter"))
|
|
|
|
assert_equal "/content/auth_google", url_for(rs, controller: "content", action: "auth_google")
|
|
assert_equal "/content/auth-twitter", url_for(rs, controller: "content", action: "auth-twitter")
|
|
end
|
|
|
|
def test_route_with_regexp_for_controller
|
|
rs.draw do
|
|
ActiveSupport::Deprecation.silence do
|
|
get ":controller/:admintoken(/:action(/:id))", controller: /admin\/.+/
|
|
get "/:controller(/:action(/:id))"
|
|
end
|
|
end
|
|
|
|
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", url_for(rs, controller: "admin/user", admintoken: "foo", action: "index")
|
|
assert_equal "/content/foo", url_for(rs, controller: "content", action: "foo")
|
|
end
|
|
|
|
def test_route_with_regexp_and_captures_for_controller
|
|
rs.draw do
|
|
ActiveSupport::Deprecation.silence do
|
|
get "/:controller(/:action(/:id))", controller: /admin\/(accounts|users)/
|
|
end
|
|
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"))
|
|
assert_raise(ActionController::RoutingError) { rs.recognize_path("/admin/products") }
|
|
end
|
|
|
|
def test_route_with_regexp_and_dot
|
|
rs.draw do
|
|
ActiveSupport::Deprecation.silence do
|
|
get ":controller/:action/:file",
|
|
controller: /admin|user/,
|
|
action: /upload|download/,
|
|
defaults: { file: nil },
|
|
constraints: { file: %r{[^/]+(\.[^/]+)?} }
|
|
end
|
|
end
|
|
# Without a file extension
|
|
assert_equal "/user/download/file",
|
|
url_for(rs, controller: "user", action: "download", file: "file")
|
|
|
|
assert_equal({ controller: "user", action: "download", file: "file" },
|
|
rs.recognize_path("/user/download/file"))
|
|
|
|
# Now, let's try a file with an extension, really a dot (.)
|
|
assert_equal "/user/download/file.jpg",
|
|
url_for(rs, controller: "user", action: "download", file: "file.jpg")
|
|
|
|
assert_equal({ controller: "user", action: "download", file: "file.jpg" },
|
|
rs.recognize_path("/user/download/file.jpg"))
|
|
end
|
|
|
|
def test_basic_named_route
|
|
rs.draw do
|
|
root to: "content#list", as: "home"
|
|
end
|
|
assert_equal("http://test.host/", setup_for_named_route.home_url)
|
|
end
|
|
|
|
def test_named_route_with_option
|
|
rs.draw do
|
|
get "page/:title" => "content#show_page", :as => "page"
|
|
end
|
|
|
|
assert_equal("http://test.host/page/new%20stuff",
|
|
setup_for_named_route.page_url(title: "new stuff"))
|
|
end
|
|
|
|
def test_named_route_with_default
|
|
rs.draw do
|
|
get "page/:title" => "content#show_page", :title => "AboutPage", :as => "page"
|
|
end
|
|
|
|
assert_equal("http://test.host/page/AboutRails",
|
|
setup_for_named_route.page_url(title: "AboutRails"))
|
|
end
|
|
|
|
def test_named_route_with_path_prefix
|
|
rs.draw do
|
|
scope "my" do
|
|
get "page" => "content#show_page", :as => "page"
|
|
end
|
|
end
|
|
|
|
assert_equal("http://test.host/my/page", setup_for_named_route.page_url)
|
|
end
|
|
|
|
def test_named_route_with_blank_path_prefix
|
|
rs.draw do
|
|
scope "" do
|
|
get "page" => "content#show_page", :as => "page"
|
|
end
|
|
end
|
|
|
|
assert_equal("http://test.host/page", setup_for_named_route.page_url)
|
|
end
|
|
|
|
def test_named_route_with_nested_controller
|
|
rs.draw do
|
|
get "admin/user" => "admin/user#index", :as => "users"
|
|
end
|
|
|
|
assert_equal("http://test.host/admin/user", setup_for_named_route.users_url)
|
|
end
|
|
|
|
def test_optimised_named_route_with_host
|
|
rs.draw do
|
|
get "page" => "content#show_page", :as => "pages", :host => "foo.com"
|
|
end
|
|
routes = setup_for_named_route
|
|
assert_equal "http://foo.com/page", routes.pages_url
|
|
end
|
|
|
|
def setup_for_named_route(options = {})
|
|
MockController.build(rs.url_helpers, options).new
|
|
end
|
|
|
|
def test_named_route_without_hash
|
|
rs.draw do
|
|
ActiveSupport::Deprecation.silence do
|
|
get ":controller/:action/:id", as: "normal"
|
|
end
|
|
end
|
|
end
|
|
|
|
def test_named_route_root
|
|
rs.draw do
|
|
root to: "hello#index"
|
|
end
|
|
routes = setup_for_named_route
|
|
assert_equal("http://test.host/", routes.root_url)
|
|
assert_equal("/", routes.root_path)
|
|
end
|
|
|
|
def test_named_route_root_without_hash
|
|
rs.draw do
|
|
root "hello#index"
|
|
end
|
|
routes = setup_for_named_route
|
|
assert_equal("http://test.host/", routes.root_url)
|
|
assert_equal("/", routes.root_path)
|
|
end
|
|
|
|
def test_named_route_root_with_hash
|
|
rs.draw do
|
|
root "hello#index", as: :index
|
|
end
|
|
|
|
routes = setup_for_named_route
|
|
assert_equal("http://test.host/", routes.index_url)
|
|
assert_equal("/", routes.index_path)
|
|
end
|
|
|
|
def test_root_without_path_raises_argument_error
|
|
assert_raises ArgumentError do
|
|
rs.draw { root nil }
|
|
end
|
|
end
|
|
|
|
def test_named_route_root_with_trailing_slash
|
|
rs.draw do
|
|
root "hello#index"
|
|
end
|
|
|
|
routes = setup_for_named_route(trailing_slash: true)
|
|
assert_equal("http://test.host/", routes.root_url)
|
|
assert_equal("http://test.host/?foo=bar", routes.root_url(foo: :bar))
|
|
end
|
|
|
|
def test_named_route_with_regexps
|
|
rs.draw do
|
|
get "page/:year/:month/:day/:title" => "page#show", :as => "article",
|
|
:year => /\d+/, :month => /\d+/, :day => /\d+/
|
|
|
|
ActiveSupport::Deprecation.silence do
|
|
get ":controller/:action/:id"
|
|
end
|
|
end
|
|
|
|
routes = setup_for_named_route
|
|
|
|
assert_equal "http://test.host/page/2005/6/10/hi",
|
|
routes.article_url(title: "hi", day: 10, year: 2005, month: 6)
|
|
end
|
|
|
|
def test_changing_controller
|
|
rs.draw { ActiveSupport::Deprecation.silence { get ":controller/:action/:id" } }
|
|
|
|
get URI("http://test.host/admin/user/index/10")
|
|
|
|
assert_equal "/admin/stuff/show/10",
|
|
controller.url_for(controller: "stuff", action: "show", id: 10, only_path: true)
|
|
end
|
|
|
|
def test_paths_escaped
|
|
rs.draw do
|
|
get "file/*path" => "content#show_file", :as => "path"
|
|
|
|
ActiveSupport::Deprecation.silence do
|
|
get ":controller/:action/:id"
|
|
end
|
|
end
|
|
|
|
# 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]
|
|
|
|
# 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]
|
|
end
|
|
|
|
def test_paths_slashes_unescaped_with_ordered_parameters
|
|
rs.draw do
|
|
get "/file/*path" => "content#index", :as => "path"
|
|
end
|
|
|
|
# No / to %2F in URI, only for query params.
|
|
assert_equal("/file/hello/world", setup_for_named_route.path_path(["hello", "world"]))
|
|
end
|
|
|
|
def test_non_controllers_cannot_be_matched
|
|
rs.draw do
|
|
ActiveSupport::Deprecation.silence do
|
|
get ":controller/:action/:id"
|
|
end
|
|
end
|
|
assert_raise(ActionController::RoutingError) { rs.recognize_path("/not_a/show/10") }
|
|
end
|
|
|
|
def test_should_list_options_diff_when_routing_constraints_dont_match
|
|
rs.draw do
|
|
get "post/:id" => "post#show", :constraints => { id: /\d+/ }, :as => "post"
|
|
end
|
|
assert_raise(ActionController::UrlGenerationError) do
|
|
url_for(rs, controller: "post", action: "show", bad_param: "foo", use_route: "post")
|
|
end
|
|
end
|
|
|
|
def test_dynamic_path_allowed
|
|
rs.draw do
|
|
get "*path" => "content#show_file"
|
|
end
|
|
|
|
assert_equal "/pages/boo",
|
|
url_for(rs, controller: "content", action: "show_file", path: %w(pages boo))
|
|
end
|
|
|
|
def test_escapes_newline_character_for_dynamic_path
|
|
rs.draw do
|
|
get "/dynamic/:dynamic_segment" => "subpath_books#show", as: :dynamic
|
|
|
|
ActiveSupport::Deprecation.silence do
|
|
get ":controller/:action/:id"
|
|
end
|
|
end
|
|
|
|
results = rs.recognize_path("/dynamic/a%0Anewline")
|
|
assert(results, "Recognition should have succeeded")
|
|
assert_equal("a\nnewline", results[:dynamic_segment])
|
|
end
|
|
|
|
def test_escapes_newline_character_for_wildcard_path
|
|
rs.draw do
|
|
get "/wildcard/*wildcard_segment" => "subpath_books#show", as: :wildcard
|
|
|
|
ActiveSupport::Deprecation.silence do
|
|
get ":controller/:action/:id"
|
|
end
|
|
end
|
|
|
|
results = rs.recognize_path("/wildcard/a%0Anewline")
|
|
assert(results, "Recognition should have succeeded")
|
|
assert_equal("a\nnewline", results[:wildcard_segment])
|
|
end
|
|
|
|
def test_dynamic_recall_paths_allowed
|
|
rs.draw do
|
|
get "*path" => "content#show_file"
|
|
end
|
|
|
|
get URI("http://test.host/pages/boo")
|
|
assert_equal({ controller: "content", action: "show_file", path: "pages/boo" },
|
|
controller.request.path_parameters)
|
|
|
|
assert_equal "/pages/boo",
|
|
controller.url_for(only_path: true)
|
|
end
|
|
|
|
def test_backwards
|
|
rs.draw do
|
|
ActiveSupport::Deprecation.silence do
|
|
get "page/:id(/:action)" => "pages#show"
|
|
get ":controller(/:action(/:id))"
|
|
end
|
|
end
|
|
|
|
get URI("http://test.host/pages/show")
|
|
assert_equal "/page/20", controller.url_for(id: 20, only_path: true)
|
|
assert_equal "/page/20", url_for(rs, controller: "pages", id: 20, action: "show")
|
|
assert_equal "/pages/boo", url_for(rs, controller: "pages", action: "boo")
|
|
end
|
|
|
|
def test_route_with_integer_default
|
|
rs.draw do
|
|
get "page(/:id)" => "content#show_page", :id => 1
|
|
|
|
ActiveSupport::Deprecation.silence do
|
|
get ":controller/:action/:id"
|
|
end
|
|
end
|
|
|
|
assert_equal "/page", url_for(rs, controller: "content", action: "show_page")
|
|
assert_equal "/page", url_for(rs, controller: "content", action: "show_page", id: 1)
|
|
assert_equal "/page", url_for(rs, controller: "content", action: "show_page", id: "1")
|
|
assert_equal "/page/10", url_for(rs, controller: "content", action: "show_page", id: 10)
|
|
|
|
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
|
|
get "page/:id" => "content#show_page", :id => 1
|
|
|
|
ActiveSupport::Deprecation.silence do
|
|
get ":controller/:action/:id"
|
|
end
|
|
end
|
|
|
|
assert_equal "/page/foo", url_for(rs, controller: "content", action: "show_page", id: "foo")
|
|
assert_equal({ controller: "content", action: "show_page", id: "foo" }, rs.recognize_path("/page/foo"))
|
|
|
|
token = +"\321\202\320\265\320\272\321\201\321\202" # 'text' in Russian
|
|
token.force_encoding(Encoding::BINARY)
|
|
escaped_token = CGI.escape(token)
|
|
|
|
assert_equal "/page/" + escaped_token, url_for(rs, controller: "content", action: "show_page", id: token)
|
|
assert_equal({ controller: "content", action: "show_page", id: token }, rs.recognize_path("/page/#{escaped_token}"))
|
|
end
|
|
|
|
def test_action_expiry
|
|
rs.draw { ActiveSupport::Deprecation.silence { get ":controller(/:action(/:id))" } }
|
|
get URI("http://test.host/content/show")
|
|
assert_equal "/content", controller.url_for(controller: "content", only_path: true)
|
|
end
|
|
|
|
def test_requirement_should_prevent_optional_id
|
|
rs.draw do
|
|
get "post/:id" => "post#show", :constraints => { id: /\d+/ }, :as => "post"
|
|
end
|
|
|
|
assert_equal "/post/10", url_for(rs, controller: "post", action: "show", id: 10)
|
|
|
|
assert_raise(ActionController::UrlGenerationError) do
|
|
url_for(rs, controller: "post", action: "show")
|
|
end
|
|
end
|
|
|
|
def test_both_requirement_and_optional
|
|
rs.draw do
|
|
get("test(/:year)" => "post#show", :as => "blog",
|
|
:defaults => { year: nil },
|
|
:constraints => { year: /\d{4}/ }
|
|
)
|
|
|
|
ActiveSupport::Deprecation.silence do
|
|
get ":controller/:action/:id"
|
|
end
|
|
end
|
|
|
|
assert_equal "/test", url_for(rs, controller: "post", action: "show")
|
|
assert_equal "/test", url_for(rs, controller: "post", action: "show", year: nil)
|
|
|
|
assert_equal("http://test.host/test", setup_for_named_route.blog_url)
|
|
end
|
|
|
|
def test_set_to_nil_forgets
|
|
rs.draw do
|
|
get "pages(/:year(/:month(/:day)))" => "content#list_pages", :month => nil, :day => nil
|
|
|
|
ActiveSupport::Deprecation.silence do
|
|
get ":controller/:action/:id"
|
|
end
|
|
end
|
|
|
|
assert_equal "/pages/2005",
|
|
url_for(rs, controller: "content", action: "list_pages", year: 2005)
|
|
assert_equal "/pages/2005/6",
|
|
url_for(rs, controller: "content", action: "list_pages", year: 2005, month: 6)
|
|
assert_equal "/pages/2005/6/12",
|
|
url_for(rs, controller: "content", action: "list_pages", year: 2005, month: 6, day: 12)
|
|
|
|
get URI("http://test.host/pages/2005/6/12")
|
|
assert_equal({ controller: "content", action: "list_pages", year: "2005", month: "6", day: "12" },
|
|
controller.request.path_parameters)
|
|
|
|
assert_equal "/pages/2005/6/4",
|
|
controller.url_for(day: 4, only_path: true)
|
|
|
|
assert_equal "/pages/2005/6",
|
|
controller.url_for(day: nil, only_path: true)
|
|
|
|
assert_equal "/pages/2005",
|
|
controller.url_for(day: nil, month: nil, only_path: true)
|
|
end
|
|
|
|
def test_root_url_generation_with_controller_and_action
|
|
rs.draw do
|
|
root to: "content#index"
|
|
end
|
|
|
|
assert_equal "/", url_for(rs, controller: "content", action: "index")
|
|
assert_equal "/", url_for(rs, controller: "content")
|
|
end
|
|
|
|
def test_named_root_url_generation_with_controller_and_action
|
|
rs.draw do
|
|
root to: "content#index", as: "home"
|
|
end
|
|
|
|
assert_equal "/", url_for(rs, controller: "content", action: "index")
|
|
assert_equal "/", url_for(rs, controller: "content")
|
|
|
|
assert_equal("http://test.host/", setup_for_named_route.home_url)
|
|
end
|
|
|
|
def test_named_route_method
|
|
rs.draw do
|
|
get "categories" => "content#categories", :as => "categories"
|
|
|
|
ActiveSupport::Deprecation.silence do
|
|
get ":controller(/:action(/:id))"
|
|
end
|
|
end
|
|
|
|
assert_equal "/categories", url_for(rs, controller: "content", action: "categories")
|
|
assert_equal "/content/hi", url_for(rs, controller: "content", action: "hi")
|
|
end
|
|
|
|
def test_named_routes_array
|
|
test_named_route_method
|
|
assert_equal [:categories], rs.named_routes.names
|
|
end
|
|
|
|
def test_nil_defaults
|
|
rs.draw do
|
|
get "journal" => "content#list_journal",
|
|
:date => nil, :user_id => nil
|
|
|
|
ActiveSupport::Deprecation.silence do
|
|
get ":controller/:action/:id"
|
|
end
|
|
end
|
|
|
|
assert_equal "/journal", url_for(rs,
|
|
controller: "content",
|
|
action: "list_journal",
|
|
date: nil,
|
|
user_id: nil)
|
|
end
|
|
|
|
def setup_request_method_routes_for(method)
|
|
rs.draw do
|
|
match "/match" => "books##{method}", :via => method.to_sym
|
|
end
|
|
end
|
|
|
|
%w(GET PATCH POST PUT DELETE).each do |request_method|
|
|
define_method("test_request_method_recognized_with_#{request_method}") do
|
|
setup_request_method_routes_for(request_method.downcase)
|
|
params = rs.recognize_path("/match", method: request_method)
|
|
assert_equal request_method.downcase, params[:action]
|
|
end
|
|
end
|
|
|
|
def test_recognize_array_of_methods
|
|
rs.draw do
|
|
match "/match" => "books#get_or_post", :via => [:get, :post]
|
|
put "/match" => "books#not_get_or_post"
|
|
end
|
|
|
|
params = rs.recognize_path("/match", method: :post)
|
|
assert_equal "get_or_post", params[:action]
|
|
|
|
params = rs.recognize_path("/match", method: :put)
|
|
assert_equal "not_get_or_post", params[:action]
|
|
end
|
|
|
|
def test_subpath_recognized
|
|
rs.draw do
|
|
ActiveSupport::Deprecation.silence do
|
|
get "/books/:id/edit" => "subpath_books#edit"
|
|
get "/items/:id/:action" => "subpath_books"
|
|
get "/posts/new/:action" => "subpath_books"
|
|
get "/posts/:id" => "subpath_books#show"
|
|
end
|
|
end
|
|
|
|
hash = rs.recognize_path "/books/17/edit"
|
|
assert_not_nil hash
|
|
assert_equal %w(subpath_books 17 edit), [hash[:controller], hash[:id], hash[:action]]
|
|
|
|
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
|
|
|
|
def test_subpath_generated
|
|
rs.draw do
|
|
ActiveSupport::Deprecation.silence do
|
|
get "/books/:id/edit" => "subpath_books#edit"
|
|
get "/items/:id/:action" => "subpath_books"
|
|
get "/posts/new/:action" => "subpath_books"
|
|
end
|
|
end
|
|
|
|
assert_equal "/books/7/edit", url_for(rs, controller: "subpath_books", id: 7, action: "edit")
|
|
assert_equal "/items/15/complete", url_for(rs, controller: "subpath_books", id: 15, action: "complete")
|
|
assert_equal "/posts/new/preview", url_for(rs, controller: "subpath_books", action: "preview")
|
|
end
|
|
|
|
def test_failed_constraints_raises_exception_with_violated_constraints
|
|
rs.draw do
|
|
get "foos/:id" => "foos#show", :as => "foo_with_requirement", :constraints => { id: /\d+/ }
|
|
end
|
|
|
|
assert_raise(ActionController::UrlGenerationError) do
|
|
setup_for_named_route.foo_with_requirement_url("I am Against the constraints")
|
|
end
|
|
end
|
|
|
|
def test_routes_changed_correctly_after_clear
|
|
rs = ::ActionDispatch::Routing::RouteSet.new
|
|
rs.draw do
|
|
get "ca" => "ca#aa"
|
|
get "cb" => "cb#ab"
|
|
get "cc" => "cc#ac"
|
|
|
|
ActiveSupport::Deprecation.silence do
|
|
get ":controller/:action/:id"
|
|
get ":controller/:action/:id.:format"
|
|
end
|
|
end
|
|
|
|
hash = rs.recognize_path "/cc"
|
|
|
|
assert_not_nil hash
|
|
assert_equal %w(cc ac), [hash[:controller], hash[:action]]
|
|
|
|
rs.draw do
|
|
get "cb" => "cb#ab"
|
|
get "cc" => "cc#ac"
|
|
|
|
ActiveSupport::Deprecation.silence do
|
|
get ":controller/:action/:id"
|
|
get ":controller/:action/:id.:format"
|
|
end
|
|
end
|
|
|
|
hash = rs.recognize_path "/cc"
|
|
|
|
assert_not_nil hash
|
|
assert_equal %w(cc ac), [hash[:controller], hash[:action]]
|
|
end
|
|
|
|
def test_drawing_more_routes_after_eager_loading
|
|
rs = ::ActionDispatch::Routing::RouteSet.new
|
|
rs.disable_clear_and_finalize = true
|
|
|
|
rs.draw do
|
|
get "/plain" => "c#plain"
|
|
get "/:symbol" => "c#symbol"
|
|
get "/glob/*" => "c#glob"
|
|
get "/with#anchor" => "c#with_anchor"
|
|
end
|
|
|
|
hash = rs.recognize_path "/symbol"
|
|
assert_not_nil hash
|
|
assert_equal %w(c symbol), [hash[:controller], hash[:action]]
|
|
|
|
rs.eager_load!
|
|
|
|
rs.draw do
|
|
get "/more/plain" => "c#plain"
|
|
get "/more/:symbol" => "c#symbol"
|
|
get "/more/glob/*" => "c#glob"
|
|
get "/more/with#anchor" => "c#with_anchor"
|
|
end
|
|
|
|
hash = rs.recognize_path "/symbol"
|
|
assert_not_nil hash
|
|
assert_equal %w(c symbol), [hash[:controller], hash[:action]]
|
|
|
|
hash = rs.recognize_path "/more/symbol"
|
|
assert_not_nil hash
|
|
assert_equal %w(c symbol), [hash[:controller], hash[:action]]
|
|
end
|
|
end
|
|
|
|
class RouteSetTest < ActiveSupport::TestCase
|
|
include RoutingTestHelpers
|
|
include ActionDispatch::RoutingVerbs
|
|
|
|
attr_reader :set
|
|
alias :routes :set
|
|
attr_accessor :controller
|
|
|
|
def setup
|
|
super
|
|
@set = make_set
|
|
end
|
|
|
|
def request
|
|
@request ||= ActionController::TestRequest.new
|
|
end
|
|
|
|
def default_route_set
|
|
@default_route_set ||= begin
|
|
set = ActionDispatch::Routing::RouteSet.new
|
|
set.draw do
|
|
ActiveSupport::Deprecation.silence do
|
|
get "/:controller(/:action(/:id))"
|
|
end
|
|
end
|
|
set
|
|
end
|
|
end
|
|
|
|
def test_generate_extras
|
|
set.draw { ActiveSupport::Deprecation.silence { get ":controller/(:action(/:id))" } }
|
|
path, extras = set.generate_extras(controller: "foo", action: "bar", id: 15, this: "hello", that: "world")
|
|
assert_equal "/foo/bar/15", path
|
|
assert_equal %w(that this), extras.map(&:to_s).sort
|
|
end
|
|
|
|
def test_extra_keys
|
|
set.draw { ActiveSupport::Deprecation.silence { get ":controller/:action/:id" } }
|
|
extras = set.extra_keys(controller: "foo", action: "bar", id: 15, this: "hello", that: "world")
|
|
assert_equal %w(that this), extras.map(&:to_s).sort
|
|
end
|
|
|
|
def test_generate_extras_not_first
|
|
set.draw do
|
|
ActiveSupport::Deprecation.silence do
|
|
get ":controller/:action/:id.:format"
|
|
get ":controller/:action/:id"
|
|
end
|
|
end
|
|
path, extras = set.generate_extras(controller: "foo", action: "bar", id: 15, this: "hello", that: "world")
|
|
assert_equal "/foo/bar/15", path
|
|
assert_equal %w(that this), extras.map(&:to_s).sort
|
|
end
|
|
|
|
def test_generate_not_first
|
|
set.draw do
|
|
ActiveSupport::Deprecation.silence do
|
|
get ":controller/:action/:id.:format"
|
|
get ":controller/:action/:id"
|
|
end
|
|
end
|
|
assert_equal "/foo/bar/15?this=hello",
|
|
url_for(set, controller: "foo", action: "bar", id: 15, this: "hello")
|
|
end
|
|
|
|
def test_extra_keys_not_first
|
|
set.draw do
|
|
ActiveSupport::Deprecation.silence do
|
|
get ":controller/:action/:id.:format"
|
|
get ":controller/:action/:id"
|
|
end
|
|
end
|
|
extras = set.extra_keys(controller: "foo", action: "bar", id: 15, this: "hello", that: "world")
|
|
assert_equal %w(that this), extras.map(&:to_s).sort
|
|
end
|
|
|
|
def test_draw
|
|
assert_equal 0, set.routes.size
|
|
set.draw do
|
|
get "/hello/world" => "a#b"
|
|
end
|
|
assert_equal 1, set.routes.size
|
|
end
|
|
|
|
def test_draw_symbol_controller_name
|
|
assert_equal 0, set.routes.size
|
|
set.draw do
|
|
get "/users/index" => "users#index"
|
|
end
|
|
set.recognize_path("/users/index", method: :get)
|
|
assert_equal 1, set.routes.size
|
|
end
|
|
|
|
def test_named_draw
|
|
assert_equal 0, set.routes.size
|
|
set.draw do
|
|
get "/hello/world" => "a#b", :as => "hello"
|
|
end
|
|
assert_equal 1, set.routes.size
|
|
assert_equal set.routes.first, set.named_routes[:hello]
|
|
end
|
|
|
|
def test_duplicate_named_route_raises_rather_than_pick_precedence
|
|
assert_raise ArgumentError do
|
|
set.draw do
|
|
get "/hello/world" => "a#b", :as => "hello"
|
|
get "/hello" => "a#b", :as => "hello"
|
|
end
|
|
end
|
|
end
|
|
|
|
def setup_named_route_test
|
|
set.draw do
|
|
get "/people(/:id)" => "people#show", :as => "show"
|
|
get "/people" => "people#index", :as => "index"
|
|
get "/people/go/:foo/:bar/joe(/:id)" => "people#multi", :as => "multi"
|
|
get "/admin/users" => "admin/users#index", :as => "users"
|
|
end
|
|
|
|
get URI("http://test.host/people")
|
|
controller
|
|
end
|
|
|
|
def test_named_route_url_method
|
|
controller = setup_named_route_test
|
|
|
|
assert_equal "http://test.host/people/5", controller.show_url(id: 5)
|
|
assert_equal "/people/5", controller.show_path(id: 5)
|
|
|
|
assert_equal "http://test.host/people", controller.index_url
|
|
assert_equal "/people", controller.index_path
|
|
|
|
assert_equal "http://test.host/admin/users", controller.users_url
|
|
assert_equal "/admin/users", controller.users_path
|
|
end
|
|
|
|
def test_named_route_url_method_with_anchor
|
|
controller = setup_named_route_test
|
|
|
|
assert_equal "http://test.host/people/5#location", controller.show_url(id: 5, anchor: "location")
|
|
assert_equal "/people/5#location", controller.show_path(id: 5, anchor: "location")
|
|
|
|
assert_equal "http://test.host/people#location", controller.index_url(anchor: "location")
|
|
assert_equal "/people#location", controller.index_path(anchor: "location")
|
|
|
|
assert_equal "http://test.host/admin/users#location", controller.users_url(anchor: "location")
|
|
assert_equal "/admin/users#location", controller.users_path(anchor: "location")
|
|
|
|
assert_equal "http://test.host/people/go/7/hello/joe/5#location",
|
|
controller.multi_url(7, "hello", 5, anchor: "location")
|
|
|
|
assert_equal "http://test.host/people/go/7/hello/joe/5?baz=bar#location",
|
|
controller.multi_url(7, "hello", 5, baz: "bar", anchor: "location")
|
|
|
|
assert_equal "http://test.host/people?baz=bar#location",
|
|
controller.index_url(baz: "bar", anchor: "location")
|
|
|
|
assert_equal "http://test.host/people", controller.index_url(anchor: nil)
|
|
assert_equal "http://test.host/people", controller.index_url(anchor: false)
|
|
end
|
|
|
|
def test_named_route_url_method_with_port
|
|
controller = setup_named_route_test
|
|
assert_equal "http://test.host:8080/people/5", controller.show_url(5, port: 8080)
|
|
end
|
|
|
|
def test_named_route_url_method_with_host
|
|
controller = setup_named_route_test
|
|
assert_equal "http://some.example.com/people/5", controller.show_url(5, host: "some.example.com")
|
|
end
|
|
|
|
def test_named_route_url_method_with_protocol
|
|
controller = setup_named_route_test
|
|
assert_equal "https://test.host/people/5", controller.show_url(5, protocol: "https")
|
|
end
|
|
|
|
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.multi_url(7, "hello", 5)
|
|
end
|
|
|
|
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.multi_url(7, "hello", 5, baz: "bar")
|
|
end
|
|
|
|
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.multi_url(7, "hello", 5, {})
|
|
end
|
|
|
|
def test_named_route_url_method_with_no_positional_arguments
|
|
controller = setup_named_route_test
|
|
assert_equal "http://test.host/people?baz=bar",
|
|
controller.index_url(baz: "bar")
|
|
end
|
|
|
|
def test_draw_default_route
|
|
set.draw do
|
|
ActiveSupport::Deprecation.silence do
|
|
get ":controller/:action/:id"
|
|
end
|
|
end
|
|
|
|
assert_equal 1, set.routes.size
|
|
|
|
assert_equal "/users/show/10", url_for(set, controller: "users", action: "show", id: 10)
|
|
assert_equal "/users/index/10", url_for(set, controller: "users", id: 10)
|
|
|
|
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/"))
|
|
end
|
|
|
|
def test_route_with_parameter_shell
|
|
set.draw do
|
|
get "page/:id" => "pages#show", :id => /\d+/
|
|
|
|
ActiveSupport::Deprecation.silence do
|
|
get "/:controller(/:action(/:id))"
|
|
end
|
|
end
|
|
|
|
assert_equal({ controller: "pages", action: "index" }, request_path_params("/pages"))
|
|
assert_equal({ controller: "pages", action: "index" }, request_path_params("/pages/index"))
|
|
assert_equal({ controller: "pages", action: "list" }, request_path_params("/pages/list"))
|
|
|
|
assert_equal({ controller: "pages", action: "show", id: "10" }, request_path_params("/pages/show/10"))
|
|
assert_equal({ controller: "pages", action: "show", id: "10" }, request_path_params("/page/10"))
|
|
end
|
|
|
|
def test_route_constraints_on_request_object_with_anchors_are_valid
|
|
assert_nothing_raised do
|
|
set.draw do
|
|
get "page/:id" => "pages#show", :constraints => { host: /^foo$/ }
|
|
end
|
|
end
|
|
end
|
|
|
|
def test_route_constraints_with_anchor_chars_are_invalid
|
|
assert_raise ArgumentError do
|
|
set.draw do
|
|
get "page/:id" => "pages#show", :id => /^\d+/
|
|
end
|
|
end
|
|
assert_raise ArgumentError do
|
|
set.draw do
|
|
get "page/:id" => "pages#show", :id => /\A\d+/
|
|
end
|
|
end
|
|
assert_raise ArgumentError do
|
|
set.draw do
|
|
get "page/:id" => "pages#show", :id => /\d+$/
|
|
end
|
|
end
|
|
assert_raise ArgumentError do
|
|
set.draw do
|
|
get "page/:id" => "pages#show", :id => /\d+\Z/
|
|
end
|
|
end
|
|
assert_raise ArgumentError do
|
|
set.draw do
|
|
get "page/:id" => "pages#show", :id => /\d+\z/
|
|
end
|
|
end
|
|
end
|
|
|
|
def test_route_constraints_with_options_method_condition_is_valid
|
|
assert_nothing_raised do
|
|
set.draw do
|
|
match "valid/route" => "pages#show", :via => :options
|
|
end
|
|
end
|
|
end
|
|
|
|
def test_route_error_with_missing_controller
|
|
set.draw do
|
|
get "/people" => "missing#index"
|
|
end
|
|
|
|
assert_raises(ActionController::RoutingError) { request_path_params "/people" }
|
|
end
|
|
|
|
def test_recognize_with_encoded_id_and_regex
|
|
set.draw do
|
|
get "page/:id" => "pages#show", :id => /[a-zA-Z0-9+]+/
|
|
end
|
|
|
|
assert_equal({ controller: "pages", action: "show", id: "10" }, request_path_params("/page/10"))
|
|
assert_equal({ controller: "pages", action: "show", id: "hello+world" }, request_path_params("/page/hello+world"))
|
|
end
|
|
|
|
def test_recognize_with_http_methods
|
|
set.draw do
|
|
get "/people" => "people#index", :as => "people"
|
|
post "/people" => "people#create"
|
|
get "/people/:id" => "people#show", :as => "person"
|
|
put "/people/:id" => "people#update"
|
|
patch "/people/:id" => "people#update"
|
|
delete "/people/:id" => "people#destroy"
|
|
end
|
|
|
|
params = request_path_params("/people", method: :get)
|
|
assert_equal("index", params[:action])
|
|
|
|
params = request_path_params("/people", method: :post)
|
|
assert_equal("create", params[:action])
|
|
|
|
params = request_path_params("/people/5", method: :put)
|
|
assert_equal("update", params[:action])
|
|
|
|
params = request_path_params("/people/5", method: :patch)
|
|
assert_equal("update", params[:action])
|
|
|
|
assert_raise(ActionController::UnknownHttpMethod) {
|
|
request_path_params("/people", method: :bacon)
|
|
}
|
|
|
|
params = request_path_params("/people/5", method: :get)
|
|
assert_equal("show", params[:action])
|
|
assert_equal("5", params[:id])
|
|
|
|
params = request_path_params("/people/5", method: :put)
|
|
assert_equal("update", params[:action])
|
|
assert_equal("5", params[:id])
|
|
|
|
params = request_path_params("/people/5", method: :patch)
|
|
assert_equal("update", params[:action])
|
|
assert_equal("5", params[:id])
|
|
|
|
params = request_path_params("/people/5", method: :delete)
|
|
assert_equal("destroy", params[:action])
|
|
assert_equal("5", params[:id])
|
|
|
|
assert_raise(ActionController::RoutingError) {
|
|
request_path_params("/people/5", method: :post)
|
|
}
|
|
end
|
|
|
|
def test_recognize_with_alias_in_conditions
|
|
set.draw do
|
|
match "/people" => "people#index", :as => "people", :via => :get
|
|
root to: "people#index"
|
|
end
|
|
|
|
params = request_path_params("/people", method: :get)
|
|
assert_equal("people", params[:controller])
|
|
assert_equal("index", params[:action])
|
|
|
|
params = request_path_params("/", method: :get)
|
|
assert_equal("people", params[:controller])
|
|
assert_equal("index", params[:action])
|
|
end
|
|
|
|
def test_typo_recognition
|
|
set.draw do
|
|
get "articles/:year/:month/:day/:title" => "articles#permalink",
|
|
:year => /\d{4}/, :day => /\d{1,2}/, :month => /\d{1,2}/
|
|
end
|
|
|
|
params = request_path_params("/articles/2005/11/05/a-very-interesting-article", method: :get)
|
|
assert_equal("permalink", params[:action])
|
|
assert_equal("2005", params[:year])
|
|
assert_equal("11", params[:month])
|
|
assert_equal("05", params[:day])
|
|
assert_equal("a-very-interesting-article", params[:title])
|
|
end
|
|
|
|
def test_routing_traversal_does_not_load_extra_classes
|
|
assert_not Object.const_defined?("Profiler__"), "Profiler should not be loaded"
|
|
set.draw do
|
|
get "/profile" => "profile#index"
|
|
end
|
|
|
|
request_path_params("/profile") rescue nil
|
|
|
|
assert_not Object.const_defined?("Profiler__"), "Profiler should not be loaded"
|
|
end
|
|
|
|
def test_recognize_with_conditions_and_format
|
|
set.draw do
|
|
get "people/:id" => "people#show", :as => "person"
|
|
put "people/:id" => "people#update"
|
|
patch "people/:id" => "people#update"
|
|
get "people/:id(.:format)" => "people#show"
|
|
end
|
|
|
|
params = request_path_params("/people/5", method: :get)
|
|
assert_equal("show", params[:action])
|
|
assert_equal("5", params[:id])
|
|
|
|
params = request_path_params("/people/5", method: :put)
|
|
assert_equal("update", params[:action])
|
|
|
|
params = request_path_params("/people/5", method: :patch)
|
|
assert_equal("update", params[:action])
|
|
|
|
params = request_path_params("/people/5.png", method: :get)
|
|
assert_equal("show", params[:action])
|
|
assert_equal("5", params[:id])
|
|
assert_equal("png", params[:format])
|
|
end
|
|
|
|
def test_generate_with_default_action
|
|
set.draw do
|
|
get "/people", controller: "people", action: "index"
|
|
get "/people/list", controller: "people", action: "list"
|
|
end
|
|
|
|
url = url_for(set, controller: "people", action: "list")
|
|
assert_equal "/people/list", url
|
|
end
|
|
|
|
def test_root_map
|
|
set.draw { root to: "people#index" }
|
|
|
|
params = request_path_params("", method: :get)
|
|
assert_equal("people", params[:controller])
|
|
assert_equal("index", params[:action])
|
|
end
|
|
|
|
def test_namespace
|
|
set.draw do
|
|
namespace "api" do
|
|
get "inventory" => "products#inventory"
|
|
end
|
|
end
|
|
|
|
params = request_path_params("/api/inventory", method: :get)
|
|
assert_equal("api/products", params[:controller])
|
|
assert_equal("inventory", params[:action])
|
|
end
|
|
|
|
def test_namespaced_root_map
|
|
set.draw do
|
|
namespace "api" do
|
|
root to: "products#index"
|
|
end
|
|
end
|
|
|
|
params = request_path_params("/api", method: :get)
|
|
assert_equal("api/products", params[:controller])
|
|
assert_equal("index", params[:action])
|
|
end
|
|
|
|
def test_namespace_with_path_prefix
|
|
set.draw do
|
|
scope module: "api", path: "prefix" do
|
|
get "inventory" => "products#inventory"
|
|
end
|
|
end
|
|
|
|
params = request_path_params("/prefix/inventory", method: :get)
|
|
assert_equal("api/products", params[:controller])
|
|
assert_equal("inventory", params[:action])
|
|
end
|
|
|
|
def test_namespace_with_blank_path_prefix
|
|
set.draw do
|
|
scope module: "api", path: "" do
|
|
get "inventory" => "products#inventory"
|
|
end
|
|
end
|
|
|
|
params = request_path_params("/inventory", method: :get)
|
|
assert_equal("api/products", params[:controller])
|
|
assert_equal("inventory", params[:action])
|
|
end
|
|
|
|
def test_id_is_sticky_when_it_ought_to_be
|
|
@set = make_set false
|
|
|
|
set.draw do
|
|
ActiveSupport::Deprecation.silence do
|
|
get ":controller/:id/:action"
|
|
end
|
|
end
|
|
|
|
get URI("http://test.host/people/7/show")
|
|
|
|
assert_equal "/people/7/destroy", controller.url_for(action: "destroy", only_path: true)
|
|
end
|
|
|
|
def test_use_static_path_when_possible
|
|
@set = make_set false
|
|
|
|
set.draw do
|
|
get "about" => "welcome#about"
|
|
|
|
ActiveSupport::Deprecation.silence do
|
|
get ":controller/:id/:action"
|
|
end
|
|
end
|
|
|
|
get URI("http://test.host/welcom/get/7")
|
|
|
|
assert_equal "/about", controller.url_for(controller: "welcome",
|
|
action: "about",
|
|
only_path: true)
|
|
end
|
|
|
|
def test_generate
|
|
set.draw { ActiveSupport::Deprecation.silence { get ":controller/:action/:id" } }
|
|
|
|
args = { controller: "foo", action: "bar", id: "7", x: "y" }
|
|
assert_equal "/foo/bar/7?x=y", url_for(set, args)
|
|
assert_equal ["/foo/bar/7", [:x]], set.generate_extras(args)
|
|
assert_equal [:x], set.extra_keys(args)
|
|
end
|
|
|
|
def test_generate_with_path_prefix
|
|
set.draw do
|
|
scope "my" do
|
|
ActiveSupport::Deprecation.silence do
|
|
get ":controller(/:action(/:id))"
|
|
end
|
|
end
|
|
end
|
|
|
|
args = { controller: "foo", action: "bar", id: "7", x: "y" }
|
|
assert_equal "/my/foo/bar/7?x=y", url_for(set, args)
|
|
end
|
|
|
|
def test_generate_with_blank_path_prefix
|
|
set.draw do
|
|
scope "" do
|
|
ActiveSupport::Deprecation.silence do
|
|
get ":controller(/:action(/:id))"
|
|
end
|
|
end
|
|
end
|
|
|
|
args = { controller: "foo", action: "bar", id: "7", x: "y" }
|
|
assert_equal "/foo/bar/7?x=y", url_for(set, args)
|
|
end
|
|
|
|
def test_named_routes_are_never_relative_to_modules
|
|
@set = make_set false
|
|
|
|
set.draw do
|
|
ActiveSupport::Deprecation.silence do
|
|
get "/connection/manage(/:action)" => "connection/manage#index"
|
|
get "/connection/connection" => "connection/connection#index"
|
|
get "/connection" => "connection#index", :as => "family_connection"
|
|
end
|
|
end
|
|
|
|
assert_equal({ controller: "connection/manage",
|
|
action: "index", }, request_path_params("/connection/manage"))
|
|
|
|
url = controller.url_for(controller: "connection", only_path: true)
|
|
assert_equal "/connection/connection", url
|
|
|
|
url = controller.url_for(use_route: "family_connection",
|
|
controller: "connection", only_path: true)
|
|
assert_equal "/connection", url
|
|
end
|
|
|
|
def test_action_left_off_when_id_is_recalled
|
|
@set = make_set false
|
|
|
|
set.draw do
|
|
ActiveSupport::Deprecation.silence do
|
|
get ":controller(/:action(/:id))"
|
|
end
|
|
end
|
|
|
|
get URI("http://test.host/books/show/10")
|
|
|
|
assert_equal "/books", controller.url_for(controller: "books",
|
|
only_path: true,
|
|
action: "index")
|
|
end
|
|
|
|
def test_query_params_will_be_shown_when_recalled
|
|
@set = make_set false
|
|
|
|
set.draw do
|
|
get "show_weblog/:parameter" => "weblog#show"
|
|
|
|
ActiveSupport::Deprecation.silence do
|
|
get ":controller(/:action(/:id))"
|
|
end
|
|
end
|
|
|
|
get URI("http://test.host/weblog/show/1")
|
|
|
|
assert_equal "/weblog/edit?parameter=1", controller.url_for(
|
|
action: "edit", parameter: 1, only_path: true)
|
|
end
|
|
|
|
def test_format_is_not_inherit
|
|
set.draw do
|
|
get "/posts(.:format)" => "posts#index"
|
|
end
|
|
|
|
get URI("http://test.host/posts.xml")
|
|
assert_equal({ controller: "posts", action: "index", format: "xml" },
|
|
controller.request.path_parameters)
|
|
|
|
assert_equal "/posts", controller.url_for(
|
|
controller: "posts", only_path: true)
|
|
|
|
assert_equal "/posts.xml", controller.url_for(
|
|
controller: "posts", format: "xml", only_path: true)
|
|
end
|
|
|
|
def test_expiry_determination_should_consider_values_with_to_param
|
|
@set = make_set false
|
|
|
|
set.draw { ActiveSupport::Deprecation.silence { get "projects/:project_id/:controller/:action" } }
|
|
|
|
get URI("http://test.host/projects/1/weblog/show")
|
|
|
|
assert_equal(
|
|
{ controller: "weblog", action: "show", project_id: "1" },
|
|
controller.request.path_parameters)
|
|
|
|
assert_equal "/projects/1/weblog/show",
|
|
controller.url_for(action: "show", project_id: 1, only_path: true)
|
|
end
|
|
|
|
def test_named_route_in_nested_resource
|
|
set.draw do
|
|
resources :projects do
|
|
member do
|
|
get "milestones" => "milestones#index", :as => "milestones"
|
|
end
|
|
end
|
|
end
|
|
|
|
params = set.recognize_path("/projects/1/milestones", method: :get)
|
|
assert_equal("milestones", params[:controller])
|
|
assert_equal("index", params[:action])
|
|
end
|
|
|
|
def test_setting_root_in_namespace_using_symbol
|
|
assert_nothing_raised do
|
|
set.draw do
|
|
namespace :admin do
|
|
root to: "home#index"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def test_setting_root_in_namespace_using_string
|
|
assert_nothing_raised do
|
|
set.draw do
|
|
namespace "admin" do
|
|
root to: "home#index"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def test_route_constraints_with_unsupported_regexp_options_must_error
|
|
assert_raise ArgumentError do
|
|
set.draw do
|
|
get "page/:name" => "pages#show",
|
|
:constraints => { name: /(david|jamis)/m }
|
|
end
|
|
end
|
|
end
|
|
|
|
def test_route_constraints_with_supported_options_must_not_error
|
|
assert_nothing_raised do
|
|
set.draw do
|
|
get "page/:name" => "pages#show",
|
|
:constraints => { name: /(david|jamis)/i }
|
|
end
|
|
end
|
|
assert_nothing_raised do
|
|
set.draw do
|
|
get "page/:name" => "pages#show",
|
|
:constraints => { name: / # Desperately overcommented regexp
|
|
( #Either
|
|
david #The Creator
|
|
| #Or
|
|
jamis #The Deployer
|
|
)/x }
|
|
end
|
|
end
|
|
end
|
|
|
|
def test_route_with_subdomain_and_constraints_must_receive_params
|
|
name_param = nil
|
|
set.draw do
|
|
get "page/:name" => "pages#show", :constraints => lambda { |request|
|
|
name_param = request.params[:name]
|
|
return true
|
|
}
|
|
end
|
|
assert_equal({ controller: "pages", action: "show", name: "mypage" },
|
|
set.recognize_path("http://subdomain.example.org/page/mypage"))
|
|
assert_equal(name_param, "mypage")
|
|
end
|
|
|
|
def test_route_requirement_recognize_with_ignore_case
|
|
set.draw do
|
|
get "page/:name" => "pages#show",
|
|
:constraints => { name: /(david|jamis)/i }
|
|
end
|
|
assert_equal({ controller: "pages", action: "show", name: "jamis" }, set.recognize_path("/page/jamis"))
|
|
assert_raise ActionController::RoutingError do
|
|
set.recognize_path("/page/davidjamis")
|
|
end
|
|
assert_equal({ controller: "pages", action: "show", name: "DAVID" }, set.recognize_path("/page/DAVID"))
|
|
end
|
|
|
|
def test_route_requirement_generate_with_ignore_case
|
|
set.draw do
|
|
get "page/:name" => "pages#show",
|
|
:constraints => { name: /(david|jamis)/i }
|
|
end
|
|
|
|
url = url_for(set, controller: "pages", action: "show", name: "david")
|
|
assert_equal "/page/david", url
|
|
assert_raise(ActionController::UrlGenerationError) do
|
|
url_for(set, controller: "pages", action: "show", name: "davidjamis")
|
|
end
|
|
url = url_for(set, controller: "pages", action: "show", name: "JAMIS")
|
|
assert_equal "/page/JAMIS", url
|
|
end
|
|
|
|
def test_route_requirement_recognize_with_extended_syntax
|
|
set.draw do
|
|
get "page/:name" => "pages#show",
|
|
:constraints => { 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"))
|
|
assert_raise ActionController::RoutingError do
|
|
set.recognize_path("/page/david #The Creator")
|
|
end
|
|
assert_raise ActionController::RoutingError do
|
|
set.recognize_path("/page/David")
|
|
end
|
|
end
|
|
|
|
def test_route_requirement_with_xi_modifiers
|
|
set.draw do
|
|
get "page/:name" => "pages#show",
|
|
:constraints => { name: / # Desperately overcommented regexp
|
|
( #Either
|
|
david #The Creator
|
|
| #Or
|
|
jamis #The Deployer
|
|
)/xi }
|
|
end
|
|
|
|
assert_equal({ controller: "pages", action: "show", name: "JAMIS" },
|
|
set.recognize_path("/page/JAMIS"))
|
|
|
|
assert_equal "/page/JAMIS",
|
|
url_for(set, controller: "pages", action: "show", name: "JAMIS")
|
|
end
|
|
|
|
def test_routes_with_symbols
|
|
set.draw do
|
|
get "unnamed", controller: :pages, action: :show, name: :as_symbol
|
|
get "named", controller: :pages, action: :show, name: :as_symbol, as: :named
|
|
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
|
|
|
|
def test_regexp_chunk_should_add_question_mark_for_optionals
|
|
set.draw do
|
|
get "/" => "foo#index"
|
|
get "/hello" => "bar#index"
|
|
end
|
|
|
|
assert_equal "/", url_for(set, controller: "foo")
|
|
assert_equal "/hello", url_for(set, controller: "bar")
|
|
|
|
assert_equal({ controller: "foo", action: "index" }, set.recognize_path("/"))
|
|
assert_equal({ controller: "bar", action: "index" }, set.recognize_path("/hello"))
|
|
end
|
|
|
|
def test_assign_route_options_with_anchor_chars
|
|
set.draw do
|
|
ActiveSupport::Deprecation.silence do
|
|
get "/cars/:action/:person/:car/", controller: "cars"
|
|
end
|
|
end
|
|
|
|
assert_equal "/cars/buy/1/2", url_for(set, controller: "cars", action: "buy", person: "1", car: "2")
|
|
|
|
assert_equal({ controller: "cars", action: "buy", person: "1", car: "2" }, set.recognize_path("/cars/buy/1/2"))
|
|
end
|
|
|
|
def test_segmentation_of_dot_path
|
|
set.draw do
|
|
ActiveSupport::Deprecation.silence do
|
|
get "/books/:action.rss", controller: "books"
|
|
end
|
|
end
|
|
|
|
assert_equal "/books/list.rss", url_for(set, controller: "books", action: "list")
|
|
|
|
assert_equal({ controller: "books", action: "list" }, set.recognize_path("/books/list.rss"))
|
|
end
|
|
|
|
def test_segmentation_of_dynamic_dot_path
|
|
set.draw do
|
|
ActiveSupport::Deprecation.silence do
|
|
get "/books(/:action(.:format))", controller: "books"
|
|
end
|
|
end
|
|
|
|
assert_equal "/books/list.rss", url_for(set, controller: "books", action: "list", format: "rss")
|
|
assert_equal "/books/list.xml", url_for(set, controller: "books", action: "list", format: "xml")
|
|
assert_equal "/books/list", url_for(set, controller: "books", action: "list")
|
|
assert_equal "/books", url_for(set, controller: "books", action: "index")
|
|
|
|
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"))
|
|
end
|
|
|
|
def test_slashes_are_implied
|
|
set.draw { ActiveSupport::Deprecation.silence { get("/:controller(/:action(/:id))") } }
|
|
|
|
assert_equal "/content", url_for(set, controller: "content", action: "index")
|
|
assert_equal "/content/list", url_for(set, controller: "content", action: "list")
|
|
assert_equal "/content/show/1", url_for(set, 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"))
|
|
end
|
|
|
|
def test_default_route_recognition
|
|
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/")
|
|
|
|
expected[:id] = "jamis"
|
|
assert_equal expected, default_route_set.recognize_path("/pages/show/jamis/")
|
|
|
|
expected.delete :id
|
|
assert_equal expected, default_route_set.recognize_path("/pages/show")
|
|
assert_equal expected, default_route_set.recognize_path("/pages/show/")
|
|
|
|
expected[:action] = "index"
|
|
assert_equal expected, default_route_set.recognize_path("/pages/")
|
|
assert_equal expected, default_route_set.recognize_path("/pages")
|
|
|
|
assert_raise(ActionController::RoutingError) { default_route_set.recognize_path("/") }
|
|
assert_raise(ActionController::RoutingError) { default_route_set.recognize_path("/pages/how/goood/it/is/to/be/free") }
|
|
end
|
|
|
|
def test_default_route_should_omit_default_action
|
|
assert_equal "/accounts", url_for(default_route_set, controller: "accounts", action: "index")
|
|
end
|
|
|
|
def test_default_route_should_include_default_action_when_id_present
|
|
assert_equal "/accounts/index/20", url_for(default_route_set, controller: "accounts", action: "index", id: "20")
|
|
end
|
|
|
|
def test_default_route_should_work_with_action_but_no_id
|
|
assert_equal "/accounts/list_all", url_for(default_route_set, controller: "accounts", action: "list_all")
|
|
end
|
|
|
|
def test_default_route_should_uri_escape_pluses
|
|
expected = { controller: "pages", action: "show", id: "hello world" }
|
|
assert_equal expected, default_route_set.recognize_path("/pages/show/hello%20world")
|
|
assert_equal "/pages/show/hello%20world", url_for(default_route_set, expected)
|
|
|
|
expected[: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%2Bworld")
|
|
assert_equal "/pages/show/hello+world", url_for(default_route_set, expected)
|
|
end
|
|
|
|
def test_build_empty_query_string
|
|
assert_uri_equal "/foo", url_for(default_route_set, controller: "foo")
|
|
end
|
|
|
|
def test_build_query_string_with_nil_value
|
|
assert_uri_equal "/foo", url_for(default_route_set, controller: "foo", x: nil)
|
|
end
|
|
|
|
def test_simple_build_query_string
|
|
assert_uri_equal "/foo?x=1&y=2", url_for(default_route_set, controller: "foo", x: "1", y: "2")
|
|
end
|
|
|
|
def test_convert_ints_build_query_string
|
|
assert_uri_equal "/foo?x=1&y=2", url_for(default_route_set, controller: "foo", x: 1, y: 2)
|
|
end
|
|
|
|
def test_escape_spaces_build_query_string
|
|
assert_uri_equal "/foo?x=hello+world&y=goodbye+world", url_for(default_route_set, controller: "foo", x: "hello world", y: "goodbye world")
|
|
end
|
|
|
|
def test_expand_array_build_query_string
|
|
assert_uri_equal "/foo?x%5B%5D=1&x%5B%5D=2", url_for(default_route_set, controller: "foo", x: [1, 2])
|
|
end
|
|
|
|
def test_escape_spaces_build_query_string_selected_keys
|
|
assert_uri_equal "/foo?x=hello+world", url_for(default_route_set, controller: "foo", x: "hello world")
|
|
end
|
|
|
|
def test_generate_with_default_params
|
|
set.draw do
|
|
get "dummy/page/:page" => "dummy#show"
|
|
get "dummy/dots/page.:page" => "dummy#dots"
|
|
get "ibocorp(/:page)" => "ibocorp#show",
|
|
:constraints => { page: /\d+/ },
|
|
:defaults => { page: 1 }
|
|
|
|
ActiveSupport::Deprecation.silence do
|
|
get ":controller/:action/:id"
|
|
end
|
|
end
|
|
|
|
assert_equal "/ibocorp", url_for(set, controller: "ibocorp", action: "show", page: 1)
|
|
end
|
|
|
|
include ActionDispatch::RoutingVerbs
|
|
|
|
def test_generate_with_optional_params_recalls_last_request
|
|
@set = make_set false
|
|
|
|
set.draw do
|
|
get "blog/", controller: "blog", action: "index"
|
|
|
|
get "blog(/:year(/:month(/:day)))",
|
|
controller: "blog",
|
|
action: "show_date",
|
|
constraints: { year: /(19|20)\d\d/, month: /[01]?\d/, day: /[0-3]?\d/ },
|
|
day: nil, month: nil
|
|
|
|
get "blog/show/:id", controller: "blog", action: "show", id: /\d+/
|
|
|
|
ActiveSupport::Deprecation.silence do
|
|
get "blog/:controller/:action(/:id)"
|
|
end
|
|
|
|
get "*anything", controller: "blog", action: "unknown_request"
|
|
end
|
|
|
|
recognize_path = ->(path) {
|
|
get(URI("http://example.org" + path))
|
|
controller.request.path_parameters
|
|
}
|
|
|
|
assert_equal({ controller: "blog", action: "index" }, recognize_path.("/blog"))
|
|
assert_equal({ controller: "blog", action: "show", id: "123" }, recognize_path.("/blog/show/123"))
|
|
assert_equal({ controller: "blog", action: "show_date", year: "2004", day: nil, month: nil }, recognize_path.("/blog/2004"))
|
|
assert_equal({ controller: "blog", action: "show_date", year: "2004", month: "12", day: nil }, recognize_path.("/blog/2004/12"))
|
|
assert_equal({ controller: "blog", action: "show_date", year: "2004", month: "12", day: "25" }, recognize_path.("/blog/2004/12/25"))
|
|
assert_equal({ controller: "articles", action: "edit", id: "123" }, recognize_path.("/blog/articles/edit/123"))
|
|
assert_equal({ controller: "articles", action: "show_stats" }, recognize_path.("/blog/articles/show_stats"))
|
|
assert_equal({ controller: "blog", action: "unknown_request", anything: "blog/wibble" }, recognize_path.("/blog/wibble"))
|
|
assert_equal({ controller: "blog", action: "unknown_request", anything: "junk" }, recognize_path.("/junk"))
|
|
|
|
get URI("http://example.org/blog/2006/07/28")
|
|
|
|
assert_equal({ controller: "blog", action: "show_date", year: "2006", month: "07", day: "28" }, controller.request.path_parameters)
|
|
assert_equal("/blog/2006/07/25", controller.url_for(day: 25, only_path: true))
|
|
assert_equal("/blog/2005", controller.url_for(year: 2005, only_path: true))
|
|
assert_equal("/blog/show/123", controller.url_for(action: "show", id: 123, only_path: true))
|
|
assert_equal("/blog/2006", controller.url_for(year: 2006, only_path: true))
|
|
assert_equal("/blog/2006", controller.url_for(year: 2006, month: nil, only_path: true))
|
|
end
|
|
|
|
private
|
|
def assert_uri_equal(expected, actual)
|
|
assert_equal(sort_query_string_params(expected), sort_query_string_params(actual))
|
|
end
|
|
|
|
def sort_query_string_params(uri)
|
|
path, qs = uri.split("?")
|
|
qs = qs.split("&").sort.join("&") if qs
|
|
qs ? "#{path}?#{qs}" : path
|
|
end
|
|
end
|
|
|
|
class RackMountIntegrationTests < ActiveSupport::TestCase
|
|
include RoutingTestHelpers
|
|
|
|
Model = Struct.new(:to_param)
|
|
|
|
Mapping = lambda {
|
|
namespace :admin do
|
|
resources :users, :posts
|
|
end
|
|
|
|
namespace "api" do
|
|
root to: "users#index"
|
|
end
|
|
|
|
get "/blog(/:year(/:month(/:day)))" => "posts#show_date",
|
|
:constraints => {
|
|
year: /(19|20)\d\d/,
|
|
month: /[01]?\d/,
|
|
day: /[0-3]?\d/
|
|
},
|
|
:day => nil,
|
|
:month => nil
|
|
|
|
get "archive/:year", controller: "archive", action: "index",
|
|
defaults: { year: nil },
|
|
constraints: { year: /\d{4}/ },
|
|
as: "blog"
|
|
|
|
resources :people
|
|
get "legacy/people" => "people#index", :legacy => "true"
|
|
|
|
get "symbols", controller: :symbols, action: :show, name: :as_symbol
|
|
get "id_default(/:id)" => "foo#id_default", :id => 1
|
|
match "get_or_post" => "foo#get_or_post", :via => [:get, :post]
|
|
get "optional/:optional" => "posts#index"
|
|
get "projects/:project_id" => "project#index", :as => "project"
|
|
get "clients" => "projects#index"
|
|
|
|
get "ignorecase/geocode/:postalcode" => "geocode#show", :postalcode => /hx\d\d-\d[a-z]{2}/i
|
|
get "extended/geocode/:postalcode" => "geocode#show", :constraints => {
|
|
postalcode: /# Postcode format
|
|
\d{5} #Prefix
|
|
(-\d{4})? #Suffix
|
|
/x
|
|
}, :as => "geocode"
|
|
|
|
get "news(.:format)" => "news#index"
|
|
|
|
ActiveSupport::Deprecation.silence do
|
|
get "comment/:id(/:action)" => "comments#show"
|
|
get "ws/:controller(/:action(/:id))", ws: true
|
|
get "account(/:action)" => "account#subscription"
|
|
get "pages/:page_id/:controller(/:action(/:id))"
|
|
get ":controller/ping", action: "ping"
|
|
end
|
|
|
|
get "こんにちは/世界", controller: "news", action: "index"
|
|
|
|
ActiveSupport::Deprecation.silence do
|
|
match ":controller(/:action(/:id))(.:format)", via: :all
|
|
end
|
|
|
|
root to: "news#index"
|
|
}
|
|
|
|
attr_reader :routes
|
|
attr_reader :controller
|
|
|
|
def setup
|
|
@routes = ActionDispatch::Routing::RouteSet.new
|
|
@routes.draw(&Mapping)
|
|
end
|
|
|
|
def test_recognize_path
|
|
assert_equal({ controller: "admin/users", action: "index" }, @routes.recognize_path("/admin/users", method: :get))
|
|
assert_equal({ controller: "admin/users", action: "create" }, @routes.recognize_path("/admin/users", method: :post))
|
|
assert_equal({ controller: "admin/users", action: "new" }, @routes.recognize_path("/admin/users/new", method: :get))
|
|
assert_equal({ controller: "admin/users", action: "show", id: "1" }, @routes.recognize_path("/admin/users/1", method: :get))
|
|
assert_equal({ controller: "admin/users", action: "update", id: "1" }, @routes.recognize_path("/admin/users/1", method: :put))
|
|
assert_equal({ controller: "admin/users", action: "destroy", id: "1" }, @routes.recognize_path("/admin/users/1", method: :delete))
|
|
assert_equal({ controller: "admin/users", action: "edit", id: "1" }, @routes.recognize_path("/admin/users/1/edit", method: :get))
|
|
|
|
assert_equal({ controller: "admin/posts", action: "index" }, @routes.recognize_path("/admin/posts", method: :get))
|
|
assert_equal({ controller: "admin/posts", action: "new" }, @routes.recognize_path("/admin/posts/new", method: :get))
|
|
|
|
assert_equal({ controller: "api/users", action: "index" }, @routes.recognize_path("/api", method: :get))
|
|
assert_equal({ controller: "api/users", action: "index" }, @routes.recognize_path("/api/", method: :get))
|
|
|
|
assert_equal({ controller: "posts", action: "show_date", year: "2009", month: nil, day: nil }, @routes.recognize_path("/blog/2009", method: :get))
|
|
assert_equal({ controller: "posts", action: "show_date", year: "2009", month: "01", day: nil }, @routes.recognize_path("/blog/2009/01", method: :get))
|
|
assert_equal({ controller: "posts", action: "show_date", year: "2009", month: "01", day: "01" }, @routes.recognize_path("/blog/2009/01/01", method: :get))
|
|
|
|
assert_equal({ controller: "archive", action: "index", year: "2010" }, @routes.recognize_path("/archive/2010"))
|
|
assert_equal({ controller: "archive", action: "index" }, @routes.recognize_path("/archive"))
|
|
|
|
assert_equal({ controller: "people", action: "index" }, @routes.recognize_path("/people", method: :get))
|
|
assert_equal({ controller: "people", action: "index", format: "xml" }, @routes.recognize_path("/people.xml", method: :get))
|
|
assert_equal({ controller: "people", action: "create" }, @routes.recognize_path("/people", method: :post))
|
|
assert_equal({ controller: "people", action: "new" }, @routes.recognize_path("/people/new", method: :get))
|
|
assert_equal({ controller: "people", action: "show", id: "1" }, @routes.recognize_path("/people/1", method: :get))
|
|
assert_equal({ controller: "people", action: "show", id: "1", format: "xml" }, @routes.recognize_path("/people/1.xml", method: :get))
|
|
assert_equal({ controller: "people", action: "update", id: "1" }, @routes.recognize_path("/people/1", method: :put))
|
|
assert_equal({ controller: "people", action: "destroy", id: "1" }, @routes.recognize_path("/people/1", method: :delete))
|
|
assert_equal({ controller: "people", action: "edit", id: "1" }, @routes.recognize_path("/people/1/edit", method: :get))
|
|
assert_equal({ controller: "people", action: "edit", id: "1", format: "xml" }, @routes.recognize_path("/people/1/edit.xml", method: :get))
|
|
|
|
assert_equal({ controller: "symbols", action: "show", name: :as_symbol }, @routes.recognize_path("/symbols"))
|
|
assert_equal({ controller: "foo", action: "id_default", id: "1" }, @routes.recognize_path("/id_default/1"))
|
|
assert_equal({ controller: "foo", action: "id_default", id: "2" }, @routes.recognize_path("/id_default/2"))
|
|
assert_equal({ controller: "foo", action: "id_default", id: 1 }, @routes.recognize_path("/id_default"))
|
|
assert_equal({ controller: "foo", action: "get_or_post" }, @routes.recognize_path("/get_or_post", method: :get))
|
|
assert_equal({ controller: "foo", action: "get_or_post" }, @routes.recognize_path("/get_or_post", method: :post))
|
|
assert_raise(ActionController::RoutingError) { @routes.recognize_path("/get_or_post", method: :put) }
|
|
assert_raise(ActionController::RoutingError) { @routes.recognize_path("/get_or_post", method: :delete) }
|
|
|
|
assert_equal({ controller: "posts", action: "index", optional: "bar" }, @routes.recognize_path("/optional/bar"))
|
|
assert_raise(ActionController::RoutingError) { @routes.recognize_path("/optional") }
|
|
|
|
assert_equal({ controller: "posts", action: "show", id: "1", ws: true }, @routes.recognize_path("/ws/posts/show/1", method: :get))
|
|
assert_equal({ controller: "posts", action: "list", ws: true }, @routes.recognize_path("/ws/posts/list", method: :get))
|
|
assert_equal({ controller: "posts", action: "index", ws: true }, @routes.recognize_path("/ws/posts", method: :get))
|
|
|
|
assert_equal({ controller: "account", action: "subscription" }, @routes.recognize_path("/account", method: :get))
|
|
assert_equal({ controller: "account", action: "subscription" }, @routes.recognize_path("/account/subscription", method: :get))
|
|
assert_equal({ controller: "account", action: "billing" }, @routes.recognize_path("/account/billing", method: :get))
|
|
|
|
assert_equal({ page_id: "1", controller: "notes", action: "index" }, @routes.recognize_path("/pages/1/notes", method: :get))
|
|
assert_equal({ page_id: "1", controller: "notes", action: "list" }, @routes.recognize_path("/pages/1/notes/list", method: :get))
|
|
assert_equal({ page_id: "1", controller: "notes", action: "show", id: "2" }, @routes.recognize_path("/pages/1/notes/show/2", method: :get))
|
|
|
|
assert_equal({ controller: "posts", action: "ping" }, @routes.recognize_path("/posts/ping", method: :get))
|
|
assert_equal({ controller: "posts", action: "index" }, @routes.recognize_path("/posts", method: :get))
|
|
assert_equal({ controller: "posts", action: "index" }, @routes.recognize_path("/posts/index", method: :get))
|
|
assert_equal({ controller: "posts", action: "show" }, @routes.recognize_path("/posts/show", method: :get))
|
|
assert_equal({ controller: "posts", action: "show", id: "1" }, @routes.recognize_path("/posts/show/1", method: :get))
|
|
assert_equal({ controller: "posts", action: "create" }, @routes.recognize_path("/posts/create", method: :post))
|
|
|
|
assert_equal({ controller: "geocode", action: "show", postalcode: "hx12-1az" }, @routes.recognize_path("/ignorecase/geocode/hx12-1az"))
|
|
assert_equal({ controller: "geocode", action: "show", postalcode: "hx12-1AZ" }, @routes.recognize_path("/ignorecase/geocode/hx12-1AZ"))
|
|
assert_equal({ controller: "geocode", action: "show", postalcode: "12345-1234" }, @routes.recognize_path("/extended/geocode/12345-1234"))
|
|
assert_equal({ controller: "geocode", action: "show", postalcode: "12345" }, @routes.recognize_path("/extended/geocode/12345"))
|
|
|
|
assert_equal({ controller: "news", action: "index" }, @routes.recognize_path("/", method: :get))
|
|
assert_equal({ controller: "news", action: "index", format: "rss" }, @routes.recognize_path("/news.rss", method: :get))
|
|
|
|
assert_raise(ActionController::RoutingError) { @routes.recognize_path("/none", method: :get) }
|
|
end
|
|
|
|
def test_generate_extras
|
|
assert_equal ["/people", []], @routes.generate_extras(controller: "people")
|
|
assert_equal ["/people", [:foo]], @routes.generate_extras(controller: "people", foo: "bar")
|
|
assert_equal ["/people", []], @routes.generate_extras(controller: "people", action: "index")
|
|
assert_equal ["/people", [:foo]], @routes.generate_extras(controller: "people", action: "index", foo: "bar")
|
|
assert_equal ["/people/new", []], @routes.generate_extras(controller: "people", action: "new")
|
|
assert_equal ["/people/new", [:foo]], @routes.generate_extras(controller: "people", action: "new", foo: "bar")
|
|
assert_equal ["/people/1", []], @routes.generate_extras(controller: "people", action: "show", id: "1")
|
|
assert_equal ["/people/1", [:bar, :foo]], sort_extras!(@routes.generate_extras(controller: "people", action: "show", id: "1", foo: "2", bar: "3"))
|
|
assert_equal ["/people", [:person]], @routes.generate_extras(controller: "people", action: "create", person: { first_name: "Josh", last_name: "Peek" })
|
|
assert_equal ["/people", [:people]], @routes.generate_extras(controller: "people", action: "create", people: ["Josh", "Dave"])
|
|
|
|
assert_equal ["/posts/show/1", []], @routes.generate_extras(controller: "posts", action: "show", id: "1")
|
|
assert_equal ["/posts/show/1", [:bar, :foo]], sort_extras!(@routes.generate_extras(controller: "posts", action: "show", id: "1", foo: "2", bar: "3"))
|
|
assert_equal ["/posts", []], @routes.generate_extras(controller: "posts", action: "index")
|
|
assert_equal ["/posts", [:foo]], @routes.generate_extras(controller: "posts", action: "index", foo: "bar")
|
|
end
|
|
|
|
def test_extras
|
|
params = { controller: "people" }
|
|
assert_equal [], @routes.extra_keys(params)
|
|
assert_equal({ controller: "people" }, params)
|
|
|
|
params = { controller: "people", foo: "bar" }
|
|
assert_equal [:foo], @routes.extra_keys(params)
|
|
assert_equal({ controller: "people", foo: "bar" }, params)
|
|
|
|
params = { controller: "people", action: "create", person: { name: "Josh" } }
|
|
assert_equal [:person], @routes.extra_keys(params)
|
|
assert_equal({ controller: "people", action: "create", person: { name: "Josh" } }, params)
|
|
|
|
params = { controller: "people", action: "create", domain: { foo: "Josh" } }
|
|
assert_equal [:domain], @routes.extra_keys(params)
|
|
assert_equal({ controller: "people", action: "create", domain: { foo: "Josh" } }, params)
|
|
end
|
|
|
|
def test_unicode_path
|
|
assert_equal({ controller: "news", action: "index" }, @routes.recognize_path(URI::DEFAULT_PARSER.escape("こんにちは/世界"), method: :get))
|
|
end
|
|
|
|
def test_downcased_unicode_path
|
|
assert_equal({ controller: "news", action: "index" }, @routes.recognize_path(URI::DEFAULT_PARSER.escape("こんにちは/世界").downcase, method: :get))
|
|
end
|
|
|
|
private
|
|
def sort_extras!(extras)
|
|
if extras.length == 2
|
|
extras[1].sort! { |a, b| a.to_s <=> b.to_s }
|
|
end
|
|
extras
|
|
end
|
|
end
|