mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
92209356c3
This commit changes the behavior such the path_params now default to UTF8 just like regular parameters. This also changes the behavior such that if a path parameter contains invalid UTF8 it returns a 400 bad request. Previously the behavior was to encode the path params as binary but that's not the same as query params. So this commit makes path params behave the same as query params. It's important to test with a path that's encoded as binary because that's how paths are encoded from the socket. The test that was altered was changed to make the behavior for bad encoding the same as query params. We want to treat path params the same as query params. The params in the test are invalid UTF8 so they should return a bad request. Fixes #29669 *Eileen M. Uchitelle, Aaron Patterson, & Tsukuru Tanimichi*
2108 lines
74 KiB
Ruby
2108 lines
74 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.unpack("H2").first.upcase }
|
|
|
|
@segment = "#{safe.join}#{unsafe.join}".freeze
|
|
@escaped = "#{safe.join}#{hex.join}".freeze
|
|
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.sub(/^\//, ""), 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.sub(/^\//, ""), 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_precidence
|
|
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_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-facebook", controller: "content" }, rs.recognize_path("/content/auth-facebook"))
|
|
|
|
assert_equal "/content/auth_google", url_for(rs, controller: "content", action: "auth_google")
|
|
assert_equal "/content/auth-facebook", url_for(rs, controller: "content", action: "auth-facebook")
|
|
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.send(: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.send(: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.send(: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.send(: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.send(: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.send(: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.send(:root_url))
|
|
assert_equal("/", routes.send(: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.send(:root_url))
|
|
assert_equal("/", routes.send(: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.send(:index_url))
|
|
assert_equal("/", routes.send(: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.send(:root_url))
|
|
assert_equal("http://test.host/?foo=bar", routes.send(: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.send(: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.send(: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_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".dup # '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.send(: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.send(: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.send(: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
|
|
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.send(:show_url, id: 5)
|
|
assert_equal "/people/5", controller.send(:show_path, id: 5)
|
|
|
|
assert_equal "http://test.host/people", controller.send(:index_url)
|
|
assert_equal "/people", controller.send(:index_path)
|
|
|
|
assert_equal "http://test.host/admin/users", controller.send(:users_url)
|
|
assert_equal "/admin/users", controller.send(: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.send(:show_url, id: 5, anchor: "location")
|
|
assert_equal "/people/5#location", controller.send(:show_path, id: 5, anchor: "location")
|
|
|
|
assert_equal "http://test.host/people#location", controller.send(:index_url, anchor: "location")
|
|
assert_equal "/people#location", controller.send(:index_path, anchor: "location")
|
|
|
|
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")
|
|
|
|
assert_equal "http://test.host/people/go/7/hello/joe/5#location",
|
|
controller.send(:multi_url, 7, "hello", 5, anchor: "location")
|
|
|
|
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")
|
|
|
|
assert_equal "http://test.host/people?baz=bar#location",
|
|
controller.send(:index_url, baz: "bar", anchor: "location")
|
|
|
|
assert_equal "http://test.host/people", controller.send(:index_url, anchor: nil)
|
|
assert_equal "http://test.host/people", controller.send(: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.send(: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.send(: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.send(: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.send(: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.send(: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.send(: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.send(: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 !Object.const_defined?("Profiler__"), "Profiler should not be loaded"
|
|
set.draw do
|
|
get "/profile" => "profile#index"
|
|
end
|
|
|
|
request_path_params("/profile") rescue nil
|
|
|
|
assert !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
|
|
|
|
alias :routes :set
|
|
|
|
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", action: "index" }, params)
|
|
|
|
params = { controller: "people", foo: "bar" }
|
|
assert_equal [:foo], @routes.extra_keys(params)
|
|
assert_equal({ controller: "people", action: "index", 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)
|
|
end
|
|
|
|
def test_unicode_path
|
|
assert_equal({ controller: "news", action: "index" }, @routes.recognize_path(URI.parser.escape("こんにちは/世界"), method: :get))
|
|
end
|
|
|
|
def test_downcased_unicode_path
|
|
assert_equal({ controller: "news", action: "index" }, @routes.recognize_path(URI.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
|