aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/test/dispatch/routing_test.rb
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/test/dispatch/routing_test.rb')
-rw-r--r--actionpack/test/dispatch/routing_test.rb1715
1 files changed, 1081 insertions, 634 deletions
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index 0a59d3cf9e..4f5d8fdb7c 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -20,592 +20,13 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
end
- stub_controllers do |routes|
- Routes = routes
- Routes.draw do
- default_url_options :host => "rubyonrails.org"
- resources_path_names :correlation_indexes => "info_about_correlation_indexes"
-
+ def test_logout
+ draw do
controller :sessions do
- get 'login' => :new
- post 'login' => :create
delete 'logout' => :destroy
end
-
- resource :session do
- get :create
- post :reset
-
- resource :info
-
- member do
- get :crush
- end
- end
-
- scope "bookmark", :controller => "bookmarks", :as => :bookmark do
- get :new, :path => "build"
- post :create, :path => "create", :as => ""
- put :update
- get :remove, :action => :destroy, :as => :remove
- end
-
- scope "pagemark", :controller => "pagemarks", :as => :pagemark do
- get "new", :path => "build"
- post "create", :as => ""
- put "update"
- get "remove", :action => :destroy, :as => :remove
- end
-
- get 'account/logout' => redirect("/logout"), :as => :logout_redirect
- get 'account/login', :to => redirect("/login")
- get 'secure', :to => redirect("/secure/login")
-
- get 'mobile', :to => redirect(:subdomain => 'mobile')
- get 'documentation', :to => redirect(:domain => 'example-documentation.com', :path => '')
- get 'new_documentation', :to => redirect(:path => '/documentation/new')
- get 'super_new_documentation', :to => redirect(:host => 'super-docs.com')
-
- get 'stores/:name', :to => redirect(:subdomain => 'stores', :path => '/%{name}')
- get 'stores/:name(*rest)', :to => redirect(:subdomain => 'stores', :path => '/%{name}%{rest}')
-
- get 'youtube_favorites/:youtube_id/:name', :to => redirect(YoutubeFavoritesRedirector)
-
- constraints(lambda { |req| true }) do
- get 'account/overview'
- end
-
- get '/account/nested/overview'
- get 'sign_in' => "sessions#new"
-
- get 'account/modulo/:name', :to => redirect("/%{name}s")
- get 'account/proc/:name', :to => redirect {|params, req| "/#{params[:name].pluralize}" }
- get 'account/proc_req' => redirect {|params, req| "/#{req.method}" }
-
- get 'account/google' => redirect('http://www.google.com/', :status => 302)
-
- match 'openid/login', :via => [:get, :post], :to => "openid#login"
-
- controller(:global) do
- get 'global/hide_notice'
- get 'global/export', :to => :export, :as => :export_request
- get '/export/:id/:file', :to => :export, :as => :export_download, :constraints => { :file => /.*/ }
- get 'global/:action'
- end
-
- get "/local/:action", :controller => "local"
-
- get "/projects/status(.:format)"
- get "/404", :to => lambda { |env| [404, {"Content-Type" => "text/plain"}, ["NOT FOUND"]] }
-
- constraints(:ip => /192\.168\.1\.\d\d\d/) do
- get 'admin' => "queenbee#index"
- end
-
- constraints ::TestRoutingMapper::IpRestrictor do
- get 'admin/accounts' => "queenbee#accounts"
- end
-
- get 'admin/passwords' => "queenbee#passwords", :constraints => ::TestRoutingMapper::IpRestrictor
-
- scope 'pt', :as => 'pt' do
- resources :projects, :path_names => { :edit => 'editar', :new => 'novo' }, :path => 'projetos' do
- post :preview, :on => :new
- put :close, :on => :member, :path => 'fechar'
- get :open, :on => :new, :path => 'abrir'
- end
- resource :admin, :path_names => { :new => 'novo', :activate => 'ativar' }, :path => 'administrador' do
- post :preview, :on => :new
- put :activate, :on => :member
- end
- resources :products, :path_names => { :new => 'novo' } do
- new do
- post :preview
- end
- end
- end
-
- resources :projects, :controller => :project do
- resources :involvements, :attachments
- get :correlation_indexes, :on => :collection
-
- resources :participants do
- put :update_all, :on => :collection
- end
-
- resources :companies do
- resources :people
- resource :avatar, :controller => :avatar
- end
-
- resources :images, :as => :funny_images do
- post :revise, :on => :member
- end
-
- resource :manager, :as => :super_manager do
- post :fire
- end
-
- resources :people do
- nested do
- scope "/:access_token" do
- resource :avatar
- end
- end
-
- member do
- get 'some_path_with_name'
- put :accessible_projects
- post :resend, :generate_new_password
- end
- end
-
- resources :posts do
- get :archive, :toggle_view, :on => :collection
- post :preview, :on => :member
-
- resource :subscription
-
- resources :comments do
- post :preview, :on => :collection
- end
- end
-
- post 'new', :action => 'new', :on => :collection, :as => :new
- end
-
- resources :replies do
- collection do
- get 'page/:page' => 'replies#index', :page => %r{\d+}
- get ':page' => 'replies#index', :page => %r{\d+}
- end
-
- new do
- post :preview
- end
-
- member do
- put :answer, :to => :mark_as_answer
- delete :answer, :to => :unmark_as_answer
- end
- end
-
- resources :posts, :only => [:index, :show] do
- namespace :admin do
- root :to => "index#index"
- end
- resources :comments, :except => :destroy do
- get "views" => "comments#views", :as => :views
- end
- end
-
- resource :past, :only => :destroy
- resource :present, :only => :update
- resource :future, :only => :create
- resources :relationships, :only => [:create, :destroy]
- resources :friendships, :only => [:update]
-
- shallow do
- namespace :api do
- resources :teams do
- resources :players
- resource :captain
- end
- end
- end
-
- scope '/hello' do
- shallow do
- resources :notes do
- resources :trackbacks
- end
- end
- end
-
- resources :threads, :shallow => true do
- resource :owner
- resources :messages do
- resources :comments do
- member do
- post :preview
- end
- end
- end
- end
-
- resources :sheep do
- get "_it", :on => :member
- end
-
- resources :clients do
- namespace :google do
- resource :account do
- namespace :secret do
- resource :info
- end
- end
- end
- end
-
- resources :customers do
- get :recent, :on => :collection
- get "profile", :on => :member
- get "secret/profile" => "customers#secret", :on => :member
- post "preview" => "customers#preview", :as => :another_preview, :on => :new
- resource :avatar do
- get "thumbnail" => "avatars#thumbnail", :as => :thumbnail, :on => :member
- end
- resources :invoices do
- get "outstanding" => "invoices#outstanding", :on => :collection
- get "overdue", :to => :overdue, :on => :collection
- get "print" => "invoices#print", :as => :print, :on => :member
- post "preview" => "invoices#preview", :as => :preview, :on => :new
- get "aged/:months", :on => :collection, :action => :aged, :as => :aged
- end
- resources :notes, :shallow => true do
- get "preview" => "notes#preview", :as => :preview, :on => :new
- get "print" => "notes#print", :as => :print, :on => :member
- end
- get "inactive", :on => :collection
- post "deactivate", :on => :member
- get "old", :on => :collection, :as => :stale
- get "export"
- end
-
- namespace :api do
- resources :customers do
- get "recent" => "customers#recent", :as => :recent, :on => :collection
- get "profile" => "customers#profile", :as => :profile, :on => :member
- post "preview" => "customers#preview", :as => :preview, :on => :new
- end
- scope(':version', :version => /.+/) do
- resources :users, :id => /.+?/, :format => /json|xml/
- end
-
- get "products/list"
- end
-
- get 'sprockets.js' => ::TestRoutingMapper::SprocketsApp
-
- get 'people/:id/update', :to => 'people#update', :as => :update_person
- get '/projects/:project_id/people/:id/update', :to => 'people#update', :as => :update_project_person
-
- # misc
- get 'articles/:year/:month/:day/:title', :to => "articles#show", :as => :article
-
- # default params
- get 'inline_pages/(:id)', :to => 'pages#show', :id => 'home'
- get 'default_pages/(:id)', :to => 'pages#show', :defaults => { :id => 'home' }
- defaults :id => 'home' do
- get 'scoped_pages/(:id)', :to => 'pages#show'
- end
-
- namespace :account do
- get 'shorthand'
- get 'description', :to => :description, :as => "description"
- get ':action/callback', :action => /twitter|github/, :to => "callbacks", :as => :callback
- resource :subscription, :credit, :credit_card
-
- root :to => "account#index"
-
- namespace :admin do
- resource :subscription
- end
- end
-
- namespace :forum do
- resources :products, :path => '' do
- resources :questions
- end
- end
-
- namespace :users, :path => 'usuarios' do
- root :to => 'home#index'
- end
-
- controller :articles do
- scope '/articles', :as => 'article' do
- scope :path => '/:title', :title => /[a-z]+/, :as => :with_title do
- get '/:id', :to => :with_id, :as => ""
- end
- end
- end
-
- scope ':access_token', :constraints => { :access_token => /\w{5,5}/ } do
- resources :rooms
- end
-
- get '/info' => 'projects#info', :as => 'info'
-
- namespace :admin do
- scope '(:locale)', :locale => /en|pl/ do
- resources :descriptions
- end
- end
-
- scope '(:locale)', :locale => /en|pl/ do
- get "registrations/new"
- resources :descriptions
- root :to => 'projects#index'
- end
-
- scope :only => [:index, :show] do
- resources :products, :constraints => { :id => /\d{4}/ } do
- root :to => "products#root"
- get :favorite, :on => :collection
- resources :images
- end
- resource :account
- end
-
- resource :dashboard, :constraints => { :ip => /192\.168\.1\.\d{1,3}/ }
-
- resource :token, :module => :api
- scope :module => :api do
- resources :errors, :shallow => true do
- resources :notices
- end
- end
-
- scope :path => 'api' do
- resource :me
- get '/' => 'mes#index'
- scope :v2 do
- resource :me, as: 'v2_me'
- get '/' => 'mes#index'
- end
-
- scope :v3, :admin do
- resource :me, as: 'v3_me'
- end
- end
-
- get "(/:username)/followers" => "followers#index"
- get "/groups(/user/:username)" => "groups#index"
- get "(/user/:username)/photos" => "photos#index"
-
- scope '(groups)' do
- scope '(discussions)' do
- resources :messages
- end
- end
-
- get "whatever/:controller(/:action(/:id))", :id => /\d+/
-
- resource :profile do
- get :settings
-
- new do
- post :preview
- end
- end
-
- resources :content
-
- namespace :transport do
- resources :taxis
- end
-
- namespace :medical do
- resource :taxis
- end
-
- scope :constraints => { :id => /\d+/ } do
- get '/tickets', :to => 'tickets#index', :as => :tickets
- end
-
- scope :constraints => { :id => /\d{4}/ } do
- resources :movies do
- resources :reviews
- resource :trailer
- end
- end
-
- namespace :private do
- root :to => redirect('/private/index')
- get "index", :to => 'private#index'
- end
-
- scope :only => [:index, :show] do
- namespace :only do
- resources :clubs do
- resources :players
- resource :chairman
- end
- end
- end
-
- scope :except => [:new, :create, :edit, :update, :destroy] do
- namespace :except do
- resources :clubs do
- resources :players
- resource :chairman
- end
- end
- end
-
- namespace :wiki do
- resources :articles, :id => /[^\/]+/ do
- resources :comments, :only => [:create, :new]
- end
- end
-
- resources :wiki_pages, :path => :pages
- resource :wiki_account, :path => :my_account
-
- scope :only => :show do
- namespace :only do
- resources :sectors, :only => :index do
- resources :companies do
- scope :only => :index do
- resources :divisions
- end
- scope :except => [:show, :update, :destroy] do
- resources :departments
- end
- end
- resource :leader
- resources :managers, :except => [:show, :update, :destroy]
- end
- end
- end
-
- scope :except => :index do
- namespace :except do
- resources :sectors, :except => [:show, :update, :destroy] do
- resources :companies do
- scope :except => [:show, :update, :destroy] do
- resources :divisions
- end
- scope :only => :index do
- resources :departments
- end
- end
- resource :leader
- resources :managers, :only => :index
- end
- end
- end
-
- resources :sections, :id => /.+/ do
- get :preview, :on => :member
- end
-
- resources :profiles, :param => :username, :username => /[a-z]+/ do
- get :details, :on => :member
- resources :messages
- end
-
- resources :orders do
- constraints :download => /[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}/ do
- resources :downloads, :param => :download, :shallow => true
- end
- end
-
- scope :as => "routes" do
- get "/c/:id", :as => :collision, :to => "collision#show"
- get "/collision", :to => "collision#show"
- get "/no_collision", :to => "collision#show", :as => nil
-
- get "/fc/:id", :as => :forced_collision, :to => "forced_collision#show"
- get "/forced_collision", :as => :forced_collision, :to => "forced_collision#show"
- end
-
- get '/purchases/:token/:filename',
- :to => 'purchases#fetch',
- :token => /[[:alnum:]]{10}/,
- :filename => /(.+)/,
- :as => :purchase
-
- resources :lists, :id => /([A-Za-z0-9]{25})|default/ do
- resources :todos, :id => /\d+/
- end
-
- scope '/countries/:country', :constraints => lambda { |params, req| %w(all France).include?(params[:country]) } do
- get '/', :to => 'countries#index'
- get '/cities', :to => 'countries#cities'
- end
-
- get '/countries/:country/(*other)', :to => redirect{ |params, req| params[:other] ? "/countries/all/#{params[:other]}" : '/countries/all' }
-
- get '/:locale/*file.:format', :to => 'files#show', :file => /path\/to\/existing\/file/
-
- scope '/italians' do
- get '/writers', :to => 'italians#writers', :constraints => ::TestRoutingMapper::IpRestrictor
- get '/sculptors', :to => 'italians#sculptors'
- get '/painters/:painter', :to => 'italians#painters', :constraints => {:painter => /michelangelo/}
- end
- end
- end
-
- class TestAltApp < ActionDispatch::IntegrationTest
- class AltRequest
- def initialize(env)
- @env = env
- end
-
- def path_info
- "/"
- end
-
- def request_method
- "GET"
- end
-
- def ip
- "127.0.0.1"
- end
-
- def x_header
- @env["HTTP_X_HEADER"] || ""
- end
- end
-
- class XHeader
- def call(env)
- [200, {"Content-Type" => "text/html"}, ["XHeader"]]
- end
- end
-
- class AltApp
- def call(env)
- [200, {"Content-Type" => "text/html"}, ["Alternative App"]]
- end
- end
-
- AltRoutes = ActionDispatch::Routing::RouteSet.new(AltRequest)
- AltRoutes.draw do
- get "/" => TestRoutingMapper::TestAltApp::XHeader.new, :constraints => {:x_header => /HEADER/}
- get "/" => TestRoutingMapper::TestAltApp::AltApp.new
- end
-
- def app
- AltRoutes
end
- def test_alt_request_without_header
- get "/"
- assert_equal "Alternative App", @response.body
- end
-
- def test_alt_request_with_matched_header
- get "/", {}, "HTTP_X_HEADER" => "HEADER"
- assert_equal "XHeader", @response.body
- end
-
- def test_alt_request_with_unmatched_header
- get "/", {}, "HTTP_X_HEADER" => "NON_MATCH"
- assert_equal "Alternative App", @response.body
- end
- end
-
- def app
- Routes
- end
-
- include Routes.url_helpers
-
- def test_logout
delete '/logout'
assert_equal 'sessions#destroy', @response.body
@@ -614,6 +35,15 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_login
+ draw do
+ default_url_options :host => "rubyonrails.org"
+
+ controller :sessions do
+ get 'login' => :new
+ post 'login' => :create
+ end
+ end
+
get '/login'
assert_equal 'sessions#new', @response.body
assert_equal '/login', login_path
@@ -624,39 +54,59 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
assert_equal '/login', url_for(:controller => 'sessions', :action => 'create', :only_path => true)
assert_equal '/login', url_for(:controller => 'sessions', :action => 'new', :only_path => true)
- assert_equal 'http://rubyonrails.org/login', Routes.url_for(:controller => 'sessions', :action => 'create')
- assert_equal 'http://rubyonrails.org/login', Routes.url_helpers.login_url
+ assert_equal 'http://rubyonrails.org/login', url_for(:controller => 'sessions', :action => 'create')
+ assert_equal 'http://rubyonrails.org/login', login_url
end
def test_login_redirect
+ draw do
+ get 'account/login', :to => redirect("/login")
+ end
+
get '/account/login'
verify_redirect 'http://www.example.com/login'
end
def test_logout_redirect_without_to
+ draw do
+ get 'account/logout' => redirect("/logout"), :as => :logout_redirect
+ end
+
assert_equal '/account/logout', logout_redirect_path
get '/account/logout'
verify_redirect 'http://www.example.com/logout'
end
def test_namespace_redirect
+ draw do
+ namespace :private do
+ root :to => redirect('/private/index')
+ get "index", :to => 'private#index'
+ end
+ end
+
get '/private'
verify_redirect 'http://www.example.com/private/index'
end
def test_namespace_with_controller_segment
assert_raise(ArgumentError) do
- self.class.stub_controllers do |routes|
- routes.draw do
- namespace :admin do
- get '/:controller(/:action(/:id(.:format)))'
- end
+ draw do
+ namespace :admin do
+ get '/:controller(/:action(/:id(.:format)))'
end
end
end
end
def test_session_singleton_resource
+ draw do
+ resource :session do
+ get :create
+ post :reset
+ end
+ end
+
get '/session'
assert_equal 'sessions#create', @response.body
assert_equal '/session', session_path
@@ -684,68 +134,126 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_session_info_nested_singleton_resource
+ draw do
+ resource :session do
+ resource :info
+ end
+ end
+
get '/session/info'
assert_equal 'infos#show', @response.body
assert_equal '/session/info', session_info_path
end
def test_member_on_resource
+ draw do
+ resource :session do
+ member do
+ get :crush
+ end
+ end
+ end
+
get '/session/crush'
assert_equal 'sessions#crush', @response.body
assert_equal '/session/crush', crush_session_path
end
def test_redirect_modulo
+ draw do
+ get 'account/modulo/:name', :to => redirect("/%{name}s")
+ end
+
get '/account/modulo/name'
verify_redirect 'http://www.example.com/names'
end
def test_redirect_proc
+ draw do
+ get 'account/proc/:name', :to => redirect {|params, req| "/#{params[:name].pluralize}" }
+ end
+
get '/account/proc/person'
verify_redirect 'http://www.example.com/people'
end
def test_redirect_proc_with_request
+ draw do
+ get 'account/proc_req' => redirect {|params, req| "/#{req.method}" }
+ end
+
get '/account/proc_req'
verify_redirect 'http://www.example.com/GET'
end
def test_redirect_hash_with_subdomain
+ draw do
+ get 'mobile', :to => redirect(:subdomain => 'mobile')
+ end
+
get '/mobile'
verify_redirect 'http://mobile.example.com/mobile'
end
def test_redirect_hash_with_domain_and_path
+ draw do
+ get 'documentation', :to => redirect(:domain => 'example-documentation.com', :path => '')
+ end
+
get '/documentation'
verify_redirect 'http://www.example-documentation.com'
end
def test_redirect_hash_with_path
+ draw do
+ get 'new_documentation', :to => redirect(:path => '/documentation/new')
+ end
+
get '/new_documentation'
verify_redirect 'http://www.example.com/documentation/new'
end
def test_redirect_hash_with_host
+ draw do
+ get 'super_new_documentation', :to => redirect(:host => 'super-docs.com')
+ end
+
get '/super_new_documentation?section=top'
verify_redirect 'http://super-docs.com/super_new_documentation?section=top'
end
def test_redirect_hash_path_substitution
+ draw do
+ get 'stores/:name', :to => redirect(:subdomain => 'stores', :path => '/%{name}')
+ end
+
get '/stores/iernest'
verify_redirect 'http://stores.example.com/iernest'
end
def test_redirect_hash_path_substitution_with_catch_all
+ draw do
+ get 'stores/:name(*rest)', :to => redirect(:subdomain => 'stores', :path => '/%{name}%{rest}')
+ end
+
get '/stores/iernest/products'
verify_redirect 'http://stores.example.com/iernest/products'
end
def test_redirect_class
+ draw do
+ get 'youtube_favorites/:youtube_id/:name', :to => redirect(YoutubeFavoritesRedirector)
+ end
+
get '/youtube_favorites/oHg5SJYRHA0/rick-rolld'
verify_redirect 'http://www.youtube.com/watch?v=oHg5SJYRHA0'
end
def test_openid
+ draw do
+ match 'openid/login', :via => [:get, :post], :to => "openid#login"
+ end
+
get '/openid/login'
assert_equal 'openid#login', @response.body
@@ -754,6 +262,15 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_bookmarks
+ draw do
+ scope "bookmark", :controller => "bookmarks", :as => :bookmark do
+ get :new, :path => "build"
+ post :create, :path => "create", :as => ""
+ put :update
+ get :remove, :action => :destroy, :as => :remove
+ end
+ end
+
get '/bookmark/build'
assert_equal 'bookmarks#new', @response.body
assert_equal '/bookmark/build', bookmark_new_path
@@ -772,6 +289,15 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_pagemarks
+ draw do
+ scope "pagemark", :controller => "pagemarks", :as => :pagemark do
+ get "new", :path => "build"
+ post "create", :as => ""
+ put "update"
+ get "remove", :action => :destroy, :as => :remove
+ end
+ end
+
get '/pagemark/build'
assert_equal 'pagemarks#new', @response.body
assert_equal '/pagemark/build', pagemark_new_path
@@ -790,6 +316,18 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_admin
+ draw do
+ constraints(:ip => /192\.168\.1\.\d\d\d/) do
+ get 'admin' => "queenbee#index"
+ end
+
+ constraints ::TestRoutingMapper::IpRestrictor do
+ get 'admin/accounts' => "queenbee#accounts"
+ end
+
+ get 'admin/passwords' => "queenbee#passwords", :constraints => ::TestRoutingMapper::IpRestrictor
+ end
+
get '/admin', {}, {'REMOTE_ADDR' => '192.168.1.100'}
assert_equal 'queenbee#index', @response.body
@@ -810,6 +348,15 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_global
+ draw do
+ controller(:global) do
+ get 'global/hide_notice'
+ get 'global/export', :to => :export, :as => :export_request
+ get '/export/:id/:file', :to => :export, :as => :export_download, :constraints => { :file => /.*/ }
+ get 'global/:action'
+ end
+ end
+
get '/global/dashboard'
assert_equal 'global#dashboard', @response.body
@@ -828,12 +375,20 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_local
+ draw do
+ get "/local/:action", :controller => "local"
+ end
+
get '/local/dashboard'
assert_equal 'local#dashboard', @response.body
end
# tests the use of dup in url_for
def test_url_for_with_no_side_effects
+ draw do
+ get "/projects/status(.:format)"
+ end
+
# without dup, additional (and possibly unwanted) values will be present in the options (eg. :host)
original_options = {:controller => 'projects', :action => 'status'}
options = original_options.dup
@@ -845,6 +400,10 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_url_for_does_not_modify_controller
+ draw do
+ get "/projects/status(.:format)"
+ end
+
controller = '/projects'
options = {:controller => controller, :action => 'status', :only_path => true}
url = url_for(options)
@@ -855,6 +414,12 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
# tests the arguments modification free version of define_hash_access
def test_named_route_with_no_side_effects
+ draw do
+ resources :customers do
+ get "profile", :on => :member
+ end
+ end
+
original_options = { :host => 'test.host' }
options = original_options.dup
@@ -865,11 +430,19 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_projects_status
+ draw do
+ get "/projects/status(.:format)"
+ end
+
assert_equal '/projects/status', url_for(:controller => 'projects', :action => 'status', :only_path => true)
assert_equal '/projects/status.json', url_for(:controller => 'projects', :action => 'status', :format => 'json', :only_path => true)
end
def test_projects
+ draw do
+ resources :projects, :controller => :project
+ end
+
get '/projects'
assert_equal 'project#index', @response.body
assert_equal '/projects', projects_path
@@ -903,12 +476,24 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_projects_with_post_action_and_new_path_on_collection
+ draw do
+ resources :projects, :controller => :project do
+ post 'new', :action => 'new', :on => :collection, :as => :new
+ end
+ end
+
post '/projects/new'
assert_equal "project#new", @response.body
assert_equal "/projects/new", new_projects_path
end
def test_projects_involvements
+ draw do
+ resources :projects, :controller => :project do
+ resources :involvements, :attachments
+ end
+ end
+
get '/projects/1/involvements'
assert_equal 'involvements#index', @response.body
assert_equal '/projects/1/involvements', project_involvements_path(:project_id => '1')
@@ -933,12 +518,26 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_projects_attachments
+ draw do
+ resources :projects, :controller => :project do
+ resources :involvements, :attachments
+ end
+ end
+
get '/projects/1/attachments'
assert_equal 'attachments#index', @response.body
assert_equal '/projects/1/attachments', project_attachments_path(:project_id => '1')
end
def test_projects_participants
+ draw do
+ resources :projects, :controller => :project do
+ resources :participants do
+ put :update_all, :on => :collection
+ end
+ end
+ end
+
get '/projects/1/participants'
assert_equal 'participants#index', @response.body
assert_equal '/projects/1/participants', project_participants_path(:project_id => '1')
@@ -949,6 +548,15 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_projects_companies
+ draw do
+ resources :projects, :controller => :project do
+ resources :companies do
+ resources :people
+ resource :avatar, :controller => :avatar
+ end
+ end
+ end
+
get '/projects/1/companies'
assert_equal 'companies#index', @response.body
assert_equal '/projects/1/companies', project_companies_path(:project_id => '1')
@@ -963,6 +571,14 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_project_manager
+ draw do
+ resources :projects do
+ resource :manager, :as => :super_manager do
+ post :fire
+ end
+ end
+ end
+
get '/projects/1/manager'
assert_equal 'managers#show', @response.body
assert_equal '/projects/1/manager', project_super_manager_path(:project_id => '1')
@@ -977,6 +593,14 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_project_images
+ draw do
+ resources :projects do
+ resources :images, :as => :funny_images do
+ post :revise, :on => :member
+ end
+ end
+ end
+
get '/projects/1/images'
assert_equal 'images#index', @response.body
assert_equal '/projects/1/images', project_funny_images_path(:project_id => '1')
@@ -991,6 +615,23 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_projects_people
+ draw do
+ resources :projects do
+ resources :people do
+ nested do
+ scope "/:access_token" do
+ resource :avatar
+ end
+ end
+
+ member do
+ put :accessible_projects
+ post :resend, :generate_new_password
+ end
+ end
+ end
+ end
+
get '/projects/1/people'
assert_equal 'people#index', @response.body
assert_equal '/projects/1/people', project_people_path(:project_id => '1')
@@ -1017,12 +658,35 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_projects_with_resources_path_names
+ draw do
+ resources_path_names :correlation_indexes => "info_about_correlation_indexes"
+
+ resources :projects do
+ get :correlation_indexes, :on => :collection
+ end
+ end
+
get '/projects/info_about_correlation_indexes'
- assert_equal 'project#correlation_indexes', @response.body
+ assert_equal 'projects#correlation_indexes', @response.body
assert_equal '/projects/info_about_correlation_indexes', correlation_indexes_projects_path
end
def test_projects_posts
+ draw do
+ resources :projects do
+ resources :posts do
+ get :archive, :toggle_view, :on => :collection
+ post :preview, :on => :member
+
+ resource :subscription
+
+ resources :comments do
+ post :preview, :on => :collection
+ end
+ end
+ end
+ end
+
get '/projects/1/posts'
assert_equal 'posts#index', @response.body
assert_equal '/projects/1/posts', project_posts_path(:project_id => '1')
@@ -1053,6 +717,15 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_replies
+ draw do
+ resources :replies do
+ member do
+ put :answer, :to => :mark_as_answer
+ delete :answer, :to => :unmark_as_answer
+ end
+ end
+ end
+
put '/replies/1/answer'
assert_equal 'replies#mark_as_answer', @response.body
@@ -1061,6 +734,12 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_resource_routes_with_only_and_except
+ draw do
+ resources :posts, :only => [:index, :show] do
+ resources :comments, :except => :destroy
+ end
+ end
+
get '/posts'
assert_equal 'posts#index', @response.body
assert_equal '/posts', posts_path
@@ -1084,6 +763,12 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_resource_routes_only_create_update_destroy
+ draw do
+ resource :past, :only => :destroy
+ resource :present, :only => :update
+ resource :future, :only => :create
+ end
+
delete '/past'
assert_equal 'pasts#destroy', @response.body
assert_equal '/past', past_path
@@ -1102,6 +787,11 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_resources_routes_only_create_update_destroy
+ draw do
+ resources :relationships, :only => [:create, :destroy]
+ resources :friendships, :only => [:update]
+ end
+
post '/relationships'
assert_equal 'relationships#create', @response.body
assert_equal '/relationships', relationships_path
@@ -1120,12 +810,22 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_resource_with_slugs_in_ids
+ draw do
+ resources :posts
+ end
+
get '/posts/rails-rocks'
assert_equal 'posts#show', @response.body
assert_equal '/posts/rails-rocks', post_path(:id => 'rails-rocks')
end
def test_resources_for_uncountable_names
+ draw do
+ resources :sheep do
+ get "_it", :on => :member
+ end
+ end
+
assert_equal '/sheep', sheep_index_path
assert_equal '/sheep/1', sheep_path(1)
assert_equal '/sheep/new', new_sheep_path
@@ -1135,25 +835,26 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
def test_resource_does_not_modify_passed_options
options = {:id => /.+?/, :format => /json|xml/}
- self.class.stub_controllers do |routes|
- routes.draw do
- resource :user, options
- end
- end
+ draw { resource :user, options }
assert_equal({:id => /.+?/, :format => /json|xml/}, options)
end
def test_resources_does_not_modify_passed_options
options = {:id => /.+?/, :format => /json|xml/}
- self.class.stub_controllers do |routes|
- routes.draw do
- resources :users, options
- end
- end
+ draw { resources :users, options }
assert_equal({:id => /.+?/, :format => /json|xml/}, options)
end
def test_path_names
+ draw do
+ scope 'pt', :as => 'pt' do
+ resources :projects, :path_names => { :edit => 'editar', :new => 'novo' }, :path => 'projetos'
+ resource :admin, :path_names => { :new => 'novo', :activate => 'ativar' }, :path => 'administrador' do
+ put :activate, :on => :member
+ end
+ end
+ end
+
get '/pt/projetos'
assert_equal 'projects#index', @response.body
assert_equal '/pt/projetos', pt_projects_path
@@ -1176,6 +877,15 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_path_option_override
+ draw do
+ scope 'pt', :as => 'pt' do
+ resources :projects, :path_names => { :new => 'novo' }, :path => 'projetos' do
+ put :close, :on => :member, :path => 'fechar'
+ get :open, :on => :new, :path => 'abrir'
+ end
+ end
+ end
+
get '/pt/projetos/novo/abrir'
assert_equal 'projects#open', @response.body
assert_equal '/pt/projetos/novo/abrir', open_new_pt_project_path
@@ -1186,11 +896,19 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_sprockets
+ draw do
+ get 'sprockets.js' => ::TestRoutingMapper::SprocketsApp
+ end
+
get '/sprockets.js'
assert_equal 'javascripts', @response.body
end
def test_update_person_route
+ draw do
+ get 'people/:id/update', :to => 'people#update', :as => :update_person
+ end
+
get '/people/1/update'
assert_equal 'people#update', @response.body
@@ -1198,6 +916,10 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_update_project_person
+ draw do
+ get '/projects/:project_id/people/:id/update', :to => 'people#update', :as => :update_project_person
+ end
+
get '/projects/1/people/2/update'
assert_equal 'people#update', @response.body
@@ -1205,6 +927,14 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_forum_products
+ draw do
+ namespace :forum do
+ resources :products, :path => '' do
+ resources :questions
+ end
+ end
+ end
+
get '/forum'
assert_equal 'forum/products#index', @response.body
assert_equal '/forum', forum_products_path
@@ -1223,6 +953,10 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_articles_perma
+ draw do
+ get 'articles/:year/:month/:day/:title', :to => "articles#show", :as => :article
+ end
+
get '/articles/2009/08/18/rails-3'
assert_equal 'articles#show', @response.body
@@ -1230,6 +964,12 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_account_namespace
+ draw do
+ namespace :account do
+ resource :subscription, :credit, :credit_card
+ end
+ end
+
get '/account/subscription'
assert_equal 'account/subscriptions#show', @response.body
assert_equal '/account/subscription', account_subscription_path
@@ -1244,12 +984,32 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_nested_namespace
+ draw do
+ namespace :account do
+ namespace :admin do
+ resource :subscription
+ end
+ end
+ end
+
get '/account/admin/subscription'
assert_equal 'account/admin/subscriptions#show', @response.body
assert_equal '/account/admin/subscription', account_admin_subscription_path
end
def test_namespace_nested_in_resources
+ draw do
+ resources :clients do
+ namespace :google do
+ resource :account do
+ namespace :secret do
+ resource :info
+ end
+ end
+ end
+ end
+ end
+
get '/clients/1/google/account'
assert_equal '/clients/1/google/account', client_google_account_path(1)
assert_equal 'google/accounts#show', @response.body
@@ -1260,12 +1020,28 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_namespace_with_options
+ draw do
+ namespace :users, :path => 'usuarios' do
+ root :to => 'home#index'
+ end
+ end
+
get '/usuarios'
assert_equal '/usuarios', users_root_path
assert_equal 'users/home#index', @response.body
end
def test_articles_with_id
+ draw do
+ controller :articles do
+ scope '/articles', :as => 'article' do
+ scope :path => '/:title', :title => /[a-z]+/, :as => :with_title do
+ get '/:id', :to => :with_id, :as => ""
+ end
+ end
+ end
+ end
+
get '/articles/rails/1'
assert_equal 'articles#with_id', @response.body
@@ -1276,6 +1052,12 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_access_token_rooms
+ draw do
+ scope ':access_token', :constraints => { :access_token => /\w{5,5}/ } do
+ resources :rooms
+ end
+ end
+
get '/12345/rooms'
assert_equal 'rooms#index', @response.body
@@ -1287,40 +1069,91 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_root
+ draw do
+ root :to => 'projects#index'
+ end
+
assert_equal '/', root_path
get '/'
assert_equal 'projects#index', @response.body
end
+ def test_scoped_root
+ draw do
+ scope '(:locale)', :locale => /en|pl/ do
+ root :to => 'projects#index'
+ end
+ end
+
+ assert_equal '/en', root_path(:locale => 'en')
+ get '/en'
+ assert_equal 'projects#index', @response.body
+ end
+
def test_index
+ draw do
+ get '/info' => 'projects#info', :as => 'info'
+ end
+
assert_equal '/info', info_path
get '/info'
assert_equal 'projects#info', @response.body
end
def test_match_shorthand_with_no_scope
+ draw do
+ get 'account/overview'
+ end
+
assert_equal '/account/overview', account_overview_path
get '/account/overview'
assert_equal 'account#overview', @response.body
end
def test_match_shorthand_inside_namespace
+ draw do
+ namespace :account do
+ get 'shorthand'
+ end
+ end
+
assert_equal '/account/shorthand', account_shorthand_path
get '/account/shorthand'
assert_equal 'account#shorthand', @response.body
end
def test_match_shorthand_inside_namespace_with_controller
+ draw do
+ namespace :api do
+ get "products/list"
+ end
+ end
+
assert_equal '/api/products/list', api_products_list_path
get '/api/products/list'
assert_equal 'api/products#list', @response.body
end
def test_dynamically_generated_helpers_on_collection_do_not_clobber_resources_url_helper
+ draw do
+ resources :replies do
+ collection do
+ get 'page/:page' => 'replies#index', :page => %r{\d+}
+ get ':page' => 'replies#index', :page => %r{\d+}
+ end
+ end
+ end
+
assert_equal '/replies', replies_path
end
def test_scoped_controller_with_namespace_and_action
+ draw do
+ namespace :account do
+ get ':action/callback', :action => /twitter|github/, :to => "callbacks", :as => :callback
+ end
+ end
+
assert_equal '/account/twitter/callback', account_callback_path("twitter")
get '/account/twitter/callback'
assert_equal 'account/callbacks#twitter', @response.body
@@ -1330,23 +1163,39 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_convention_match_nested_and_with_leading_slash
+ draw do
+ get '/account/nested/overview'
+ end
+
assert_equal '/account/nested/overview', account_nested_overview_path
get '/account/nested/overview'
assert_equal 'account/nested#overview', @response.body
end
def test_convention_with_explicit_end
+ draw do
+ get 'sign_in' => "sessions#new"
+ end
+
get '/sign_in'
assert_equal 'sessions#new', @response.body
assert_equal '/sign_in', sign_in_path
end
def test_redirect_with_complete_url_and_status
+ draw do
+ get 'account/google' => redirect('http://www.google.com/', :status => 302)
+ end
+
get '/account/google'
verify_redirect 'http://www.google.com/', 302
end
def test_redirect_with_port
+ draw do
+ get 'account/login', :to => redirect("/login")
+ end
+
previous_host, self.host = self.host, 'www.example.com:3000'
get '/account/login'
@@ -1356,6 +1205,12 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_normalize_namespaced_matches
+ draw do
+ namespace :account do
+ get 'description', :to => :description, :as => "description"
+ end
+ end
+
assert_equal '/account/description', account_description_path
get '/account/description'
@@ -1363,18 +1218,36 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_namespaced_roots
+ draw do
+ namespace :account do
+ root :to => "account#index"
+ end
+ end
+
assert_equal '/account', account_root_path
get '/account'
assert_equal 'account/account#index', @response.body
end
def test_optional_scoped_root
+ draw do
+ scope '(:locale)', :locale => /en|pl/ do
+ root :to => 'projects#index'
+ end
+ end
+
assert_equal '/en', root_path("en")
get '/en'
assert_equal 'projects#index', @response.body
end
def test_optional_scoped_path
+ draw do
+ scope '(:locale)', :locale => /en|pl/ do
+ resources :descriptions
+ end
+ end
+
assert_equal '/en/descriptions', descriptions_path("en")
assert_equal '/descriptions', descriptions_path(nil)
assert_equal '/en/descriptions/1', description_path("en", 1)
@@ -1394,6 +1267,14 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_nested_optional_scoped_path
+ draw do
+ namespace :admin do
+ scope '(:locale)', :locale => /en|pl/ do
+ resources :descriptions
+ end
+ end
+ end
+
assert_equal '/admin/en/descriptions', admin_descriptions_path("en")
assert_equal '/admin/descriptions', admin_descriptions_path(nil)
assert_equal '/admin/en/descriptions/1', admin_description_path("en", 1)
@@ -1413,6 +1294,12 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_nested_optional_path_shorthand
+ draw do
+ scope '(:locale)', :locale => /en|pl/ do
+ get "registrations/new"
+ end
+ end
+
get '/registrations/new'
assert_nil @request.params[:locale]
@@ -1421,6 +1308,15 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_default_params
+ draw do
+ get 'inline_pages/(:id)', :to => 'pages#show', :id => 'home'
+ get 'default_pages/(:id)', :to => 'pages#show', :defaults => { :id => 'home' }
+
+ defaults :id => 'home' do
+ get 'scoped_pages/(:id)', :to => 'pages#show'
+ end
+ end
+
get '/inline_pages'
assert_equal 'home', @request.params[:id]
@@ -1432,6 +1328,16 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_resource_constraints
+ draw do
+ resources :products, :constraints => { :id => /\d{4}/ } do
+ root :to => "products#root"
+ get :favorite, :on => :collection
+ resources :images
+ end
+
+ resource :dashboard, :constraints => { :ip => /192\.168\.1\.\d{1,3}/ }
+ end
+
get '/products/1'
assert_equal 'pass', @response.headers['X-Cascade']
get '/products'
@@ -1455,18 +1361,35 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_root_works_in_the_resources_scope
+ draw do
+ resources :products do
+ root :to => "products#root"
+ end
+ end
+
get '/products'
assert_equal 'products#root', @response.body
assert_equal '/products', products_root_path
end
def test_module_scope
+ draw do
+ resource :token, :module => :api
+ end
+
get '/token'
assert_equal 'api/tokens#show', @response.body
assert_equal '/token', token_path
end
def test_path_scope
+ draw do
+ scope :path => 'api' do
+ resource :me
+ get '/' => 'mes#index'
+ end
+ end
+
get '/api/me'
assert_equal 'mes#show', @response.body
assert_equal '/api/me', me_path
@@ -1476,6 +1399,19 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_symbol_scope
+ draw do
+ scope :path => 'api' do
+ scope :v2 do
+ resource :me, as: 'v2_me'
+ get '/' => 'mes#index'
+ end
+
+ scope :v3, :admin do
+ resource :me, as: 'v3_me'
+ end
+ end
+ end
+
get '/api/v2/me'
assert_equal 'mes#show', @response.body
assert_equal '/api/v2/me', v2_me_path
@@ -1488,6 +1424,10 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_url_generator_for_generic_route
+ draw do
+ get "whatever/:controller(/:action(/:id))"
+ end
+
get 'whatever/foo/bar'
assert_equal 'foo#bar', @response.body
@@ -1496,6 +1436,10 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_url_generator_for_namespaced_generic_route
+ draw do
+ get "whatever/:controller(/:action(/:id))", :id => /\d+/
+ end
+
get 'whatever/foo/bar/show'
assert_equal 'foo/bar#show', @response.body
@@ -1509,11 +1453,37 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
url_for(:controller => "foo/bar", :action => "show", :id => '1')
end
- def test_assert_recognizes_account_overview
- assert_recognizes({:controller => "account", :action => "overview"}, "/account/overview")
- end
-
def test_resource_new_actions
+ draw do
+ resources :replies do
+ new do
+ post :preview
+ end
+ end
+
+ scope 'pt', :as => 'pt' do
+ resources :projects, :path_names => { :new => 'novo' }, :path => 'projetos' do
+ post :preview, :on => :new
+ end
+
+ resource :admin, :path_names => { :new => 'novo' }, :path => 'administrador' do
+ post :preview, :on => :new
+ end
+
+ resources :products, :path_names => { :new => 'novo' } do
+ new do
+ post :preview
+ end
+ end
+ end
+
+ resource :profile do
+ new do
+ post :preview
+ end
+ end
+ end
+
assert_equal '/replies/new/preview', preview_new_reply_path
assert_equal '/pt/projetos/novo/preview', preview_new_pt_project_path
assert_equal '/pt/administrador/novo/preview', preview_new_pt_admin_path
@@ -1537,13 +1507,27 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_resource_merges_options_from_scope
- assert_raise(NameError) { new_account_path }
+ draw do
+ scope :only => :show do
+ resource :account
+ end
+ end
+
+ assert_raise(NoMethodError) { new_account_path }
get '/account/new'
assert_equal 404, status
end
def test_resources_merges_options_from_scope
+ draw do
+ scope :only => [:index, :show] do
+ resources :products do
+ resources :images
+ end
+ end
+ end
+
assert_raise(NoMethodError) { edit_product_path('1') }
get '/products/1/edit'
@@ -1556,6 +1540,28 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_shallow_nested_resources
+ draw do
+ shallow do
+ namespace :api do
+ resources :teams do
+ resources :players
+ resource :captain
+ end
+ end
+ end
+
+ resources :threads, :shallow => true do
+ resource :owner
+ resources :messages do
+ resources :comments do
+ member do
+ post :preview
+ end
+ end
+ end
+ end
+ end
+
get '/api/teams'
assert_equal 'api/teams#index', @response.body
assert_equal '/api/teams', api_teams_path
@@ -1658,6 +1664,16 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_shallow_nested_resources_within_scope
+ draw do
+ scope '/hello' do
+ shallow do
+ resources :notes do
+ resources :trackbacks
+ end
+ end
+ end
+ end
+
get '/hello/notes/1/trackbacks'
assert_equal 'trackbacks#index', @response.body
assert_equal '/hello/notes/1/trackbacks', note_trackbacks_path(:note_id => 1)
@@ -1709,6 +1725,36 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_custom_resource_routes_are_scoped
+ draw do
+ resources :customers do
+ get :recent, :on => :collection
+ get "profile", :on => :member
+ get "secret/profile" => "customers#secret", :on => :member
+ post "preview" => "customers#preview", :as => :another_preview, :on => :new
+ resource :avatar do
+ get "thumbnail" => "avatars#thumbnail", :as => :thumbnail, :on => :member
+ end
+ resources :invoices do
+ get "outstanding" => "invoices#outstanding", :on => :collection
+ get "overdue", :to => :overdue, :on => :collection
+ get "print" => "invoices#print", :as => :print, :on => :member
+ post "preview" => "invoices#preview", :as => :preview, :on => :new
+ end
+ resources :notes, :shallow => true do
+ get "preview" => "notes#preview", :as => :preview, :on => :new
+ get "print" => "notes#print", :as => :print, :on => :member
+ end
+ end
+
+ namespace :api do
+ resources :customers do
+ get "recent" => "customers#recent", :as => :recent, :on => :collection
+ get "profile" => "customers#profile", :as => :profile, :on => :member
+ post "preview" => "customers#preview", :as => :preview, :on => :new
+ end
+ end
+ end
+
assert_equal '/customers/recent', recent_customers_path
assert_equal '/customers/1/profile', profile_customer_path(:id => '1')
assert_equal '/customers/1/secret/profile', secret_profile_customer_path(:id => '1')
@@ -1731,6 +1777,14 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_shallow_nested_routes_ignore_module
+ draw do
+ scope :module => :api do
+ resources :errors, :shallow => true do
+ resources :notices
+ end
+ end
+ end
+
get '/errors/1/notices'
assert_equal 'api/notices#index', @response.body
assert_equal '/errors/1/notices', error_notices_path(:error_id => '1')
@@ -1741,6 +1795,14 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_non_greedy_regexp
+ draw do
+ namespace :api do
+ scope(':version', :version => /.+/) do
+ resources :users, :id => /.+?/, :format => /json|xml/
+ end
+ end
+ end
+
get '/api/1.0/users'
assert_equal 'api/users#index', @response.body
assert_equal '/api/1.0/users', api_users_path(:version => '1.0')
@@ -1763,16 +1825,28 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_glob_parameter_accepts_regexp
+ draw do
+ get '/:locale/*file.:format', :to => 'files#show', :file => /path\/to\/existing\/file/
+ end
+
get '/en/path/to/existing/file.html'
assert_equal 200, @response.status
end
def test_resources_controller_name_is_not_pluralized
+ draw do
+ resources :content
+ end
+
get '/content'
assert_equal 'content#index', @response.body
end
def test_url_generator_for_optional_prefix_dynamic_segment
+ draw do
+ get "(/:username)/followers" => "followers#index"
+ end
+
get '/bob/followers'
assert_equal 'followers#index', @response.body
assert_equal 'http://www.example.com/bob/followers',
@@ -1785,6 +1859,10 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_url_generator_for_optional_suffix_static_and_dynamic_segment
+ draw do
+ get "/groups(/user/:username)" => "groups#index"
+ end
+
get '/groups/user/bob'
assert_equal 'groups#index', @response.body
assert_equal 'http://www.example.com/groups/user/bob',
@@ -1797,6 +1875,10 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_url_generator_for_optional_prefix_static_and_dynamic_segment
+ draw do
+ get "(/user/:username)/photos" => "photos#index"
+ end
+
get 'user/bob/photos'
assert_equal 'photos#index', @response.body
assert_equal 'http://www.example.com/user/bob/photos',
@@ -1809,6 +1891,14 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_url_recognition_for_optional_static_segments
+ draw do
+ scope '(groups)' do
+ scope '(discussions)' do
+ resources :messages
+ end
+ end
+ end
+
get '/groups/discussions/messages'
assert_equal 'messages#index', @response.body
@@ -1835,12 +1925,27 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_router_removes_invalid_conditions
+ draw do
+ scope :constraints => { :id => /\d+/ } do
+ get '/tickets', :to => 'tickets#index', :as => :tickets
+ end
+ end
+
get '/tickets'
assert_equal 'tickets#index', @response.body
assert_equal '/tickets', tickets_path
end
def test_constraints_are_merged_from_scope
+ draw do
+ scope :constraints => { :id => /\d{4}/ } do
+ resources :movies do
+ resources :reviews
+ resource :trailer
+ end
+ end
+ end
+
get '/movies/0001'
assert_equal 'movies#show', @response.body
assert_equal '/movies/0001', movie_path(:id => '0001')
@@ -1875,6 +1980,17 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_only_should_be_read_from_scope
+ draw do
+ scope :only => [:index, :show] do
+ namespace :only do
+ resources :clubs do
+ resources :players
+ resource :chairman
+ end
+ end
+ end
+ end
+
get '/only/clubs'
assert_equal 'only/clubs#index', @response.body
assert_equal '/only/clubs', only_clubs_path
@@ -1901,6 +2017,17 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_except_should_be_read_from_scope
+ draw do
+ scope :except => [:new, :create, :edit, :update, :destroy] do
+ namespace :except do
+ resources :clubs do
+ resources :players
+ resource :chairman
+ end
+ end
+ end
+ end
+
get '/except/clubs'
assert_equal 'except/clubs#index', @response.body
assert_equal '/except/clubs', except_clubs_path
@@ -1927,6 +2054,14 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_only_option_should_override_scope
+ draw do
+ scope :only => :show do
+ namespace :only do
+ resources :sectors, :only => :index
+ end
+ end
+ end
+
get '/only/sectors'
assert_equal 'only/sectors#index', @response.body
assert_equal '/only/sectors', only_sectors_path
@@ -1937,6 +2072,17 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_only_option_should_not_inherit
+ draw do
+ scope :only => :show do
+ namespace :only do
+ resources :sectors, :only => :index do
+ resources :companies
+ resource :leader
+ end
+ end
+ end
+ end
+
get '/only/sectors/1/companies/2'
assert_equal 'only/companies#show', @response.body
assert_equal '/only/sectors/1/companies/2', only_sector_company_path(:sector_id => '1', :id => '2')
@@ -1947,6 +2093,14 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_except_option_should_override_scope
+ draw do
+ scope :except => :index do
+ namespace :except do
+ resources :sectors, :except => [:show, :update, :destroy]
+ end
+ end
+ end
+
get '/except/sectors'
assert_equal 'except/sectors#index', @response.body
assert_equal '/except/sectors', except_sectors_path
@@ -1957,6 +2111,17 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_except_option_should_not_inherit
+ draw do
+ scope :except => :index do
+ namespace :except do
+ resources :sectors, :except => [:show, :update, :destroy] do
+ resources :companies
+ resource :leader
+ end
+ end
+ end
+ end
+
get '/except/sectors/1/companies/2'
assert_equal 'except/companies#show', @response.body
assert_equal '/except/sectors/1/companies/2', except_sector_company_path(:sector_id => '1', :id => '2')
@@ -1967,6 +2132,16 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_except_option_should_override_scoped_only
+ draw do
+ scope :only => :show do
+ namespace :only do
+ resources :sectors, :only => :index do
+ resources :managers, :except => [:show, :update, :destroy]
+ end
+ end
+ end
+ end
+
get '/only/sectors/1/managers'
assert_equal 'only/managers#index', @response.body
assert_equal '/only/sectors/1/managers', only_sector_managers_path(:sector_id => '1')
@@ -1977,6 +2152,16 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_only_option_should_override_scoped_except
+ draw do
+ scope :except => :index do
+ namespace :except do
+ resources :sectors, :except => [:show, :update, :destroy] do
+ resources :managers, :only => :index
+ end
+ end
+ end
+ end
+
get '/except/sectors/1/managers'
assert_equal 'except/managers#index', @response.body
assert_equal '/except/sectors/1/managers', except_sector_managers_path(:sector_id => '1')
@@ -1987,6 +2172,20 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_only_scope_should_override_parent_scope
+ draw do
+ scope :only => :show do
+ namespace :only do
+ resources :sectors, :only => :index do
+ resources :companies do
+ scope :only => :index do
+ resources :divisions
+ end
+ end
+ end
+ end
+ end
+ end
+
get '/only/sectors/1/companies/2/divisions'
assert_equal 'only/divisions#index', @response.body
assert_equal '/only/sectors/1/companies/2/divisions', only_sector_company_divisions_path(:sector_id => '1', :company_id => '2')
@@ -1997,6 +2196,20 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_except_scope_should_override_parent_scope
+ draw do
+ scope :except => :index do
+ namespace :except do
+ resources :sectors, :except => [:show, :update, :destroy] do
+ resources :companies do
+ scope :except => [:show, :update, :destroy] do
+ resources :divisions
+ end
+ end
+ end
+ end
+ end
+ end
+
get '/except/sectors/1/companies/2/divisions'
assert_equal 'except/divisions#index', @response.body
assert_equal '/except/sectors/1/companies/2/divisions', except_sector_company_divisions_path(:sector_id => '1', :company_id => '2')
@@ -2007,6 +2220,20 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_except_scope_should_override_parent_only_scope
+ draw do
+ scope :only => :show do
+ namespace :only do
+ resources :sectors, :only => :index do
+ resources :companies do
+ scope :except => [:show, :update, :destroy] do
+ resources :departments
+ end
+ end
+ end
+ end
+ end
+ end
+
get '/only/sectors/1/companies/2/departments'
assert_equal 'only/departments#index', @response.body
assert_equal '/only/sectors/1/companies/2/departments', only_sector_company_departments_path(:sector_id => '1', :company_id => '2')
@@ -2017,6 +2244,20 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_only_scope_should_override_parent_except_scope
+ draw do
+ scope :except => :index do
+ namespace :except do
+ resources :sectors, :except => [:show, :update, :destroy] do
+ resources :companies do
+ scope :only => :index do
+ resources :departments
+ end
+ end
+ end
+ end
+ end
+ end
+
get '/except/sectors/1/companies/2/departments'
assert_equal 'except/departments#index', @response.body
assert_equal '/except/sectors/1/companies/2/departments', except_sector_company_departments_path(:sector_id => '1', :company_id => '2')
@@ -2027,6 +2268,12 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_resources_are_not_pluralized
+ draw do
+ namespace :transport do
+ resources :taxis
+ end
+ end
+
get '/transport/taxis'
assert_equal 'transport/taxis#index', @response.body
assert_equal '/transport/taxis', transport_taxis_path
@@ -2054,6 +2301,12 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_singleton_resources_are_not_singularized
+ draw do
+ namespace :medical do
+ resource :taxis
+ end
+ end
+
get '/medical/taxis/new'
assert_equal 'medical/taxis#new', @response.body
assert_equal '/medical/taxis/new', new_medical_taxis_path
@@ -2077,6 +2330,12 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_greedy_resource_id_regexp_doesnt_match_edit_and_custom_action
+ draw do
+ resources :sections, :id => /.+/ do
+ get :preview, :on => :member
+ end
+ end
+
get '/sections/1/edit'
assert_equal 'sections#edit', @response.body
assert_equal '/sections/1/edit', edit_section_path(:id => '1')
@@ -2087,6 +2346,14 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_resource_constraints_are_pushed_to_scope
+ draw do
+ namespace :wiki do
+ resources :articles, :id => /[^\/]+/ do
+ resources :comments, :only => [:create, :new]
+ end
+ end
+ end
+
get '/wiki/articles/Ruby_on_Rails_3.0'
assert_equal 'wiki/articles#show', @response.body
assert_equal '/wiki/articles/Ruby_on_Rails_3.0', wiki_article_path(:id => 'Ruby_on_Rails_3.0')
@@ -2101,6 +2368,11 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_resources_path_can_be_a_symbol
+ draw do
+ resources :wiki_pages, :path => :pages
+ resource :wiki_account, :path => :my_account
+ end
+
get '/pages'
assert_equal 'wiki_pages#index', @response.body
assert_equal '/pages', wiki_pages_path
@@ -2115,6 +2387,10 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_redirect_https
+ draw do
+ get 'secure', :to => redirect("/secure/login")
+ end
+
with_https do
get '/secure'
verify_redirect 'https://www.example.com/secure/login'
@@ -2122,6 +2398,15 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_symbolized_path_parameters_is_not_stale
+ draw do
+ scope '/countries/:country', :constraints => lambda { |params, req| %w(all France).include?(params[:country]) } do
+ get '/', :to => 'countries#index'
+ get '/cities', :to => 'countries#cities'
+ end
+
+ get '/countries/:country/(*other)', :to => redirect{ |params, req| params[:other] ? "/countries/all/#{params[:other]}" : '/countries/all' }
+ end
+
get '/countries/France'
assert_equal 'countries#index', @response.body
@@ -2136,6 +2421,14 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_constraints_block_not_carried_to_following_routes
+ draw do
+ scope '/italians' do
+ get '/writers', :to => 'italians#writers', :constraints => ::TestRoutingMapper::IpRestrictor
+ get '/sculptors', :to => 'italians#sculptors'
+ get '/painters/:painter', :to => 'italians#painters', :constraints => {:painter => /michelangelo/}
+ end
+ end
+
get '/italians/writers'
assert_equal 'Not Found', @response.body
@@ -2150,6 +2443,18 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_custom_resource_actions_defined_using_string
+ draw do
+ resources :customers do
+ resources :invoices do
+ get "aged/:months", :on => :collection, :action => :aged, :as => :aged
+ end
+
+ get "inactive", :on => :collection
+ post "deactivate", :on => :member
+ get "old", :on => :collection, :as => :stale
+ end
+ end
+
get '/customers/inactive'
assert_equal 'customers#inactive', @response.body
assert_equal '/customers/inactive', inactive_customers_path
@@ -2168,18 +2473,38 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_route_defined_in_resources_scope_level
+ draw do
+ resources :customers do
+ get "export"
+ end
+ end
+
get '/customers/1/export'
assert_equal 'customers#export', @response.body
assert_equal '/customers/1/export', customer_export_path(:customer_id => '1')
end
def test_named_character_classes_in_regexp_constraints
+ draw do
+ get '/purchases/:token/:filename',
+ :to => 'purchases#fetch',
+ :token => /[[:alnum:]]{10}/,
+ :filename => /(.+)/,
+ :as => :purchase
+ end
+
get '/purchases/315004be7e/Ruby_on_Rails_3.pdf'
assert_equal 'purchases#fetch', @response.body
assert_equal '/purchases/315004be7e/Ruby_on_Rails_3.pdf', purchase_path(:token => '315004be7e', :filename => 'Ruby_on_Rails_3.pdf')
end
def test_nested_resource_constraints
+ draw do
+ resources :lists, :id => /([A-Za-z0-9]{25})|default/ do
+ resources :todos, :id => /\d+/
+ end
+ end
+
get '/lists/01234012340123401234fffff'
assert_equal 'lists#show', @response.body
assert_equal '/lists/01234012340123401234fffff', list_path(:id => '01234012340123401234fffff')
@@ -2194,6 +2519,17 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_named_routes_collision_is_avoided_unless_explicitly_given_as
+ draw do
+ scope :as => "routes" do
+ get "/c/:id", :as => :collision, :to => "collision#show"
+ get "/collision", :to => "collision#show"
+ get "/no_collision", :to => "collision#show", :as => nil
+
+ get "/fc/:id", :as => :forced_collision, :to => "forced_collision#show"
+ get "/forced_collision", :as => :forced_collision, :to => "forced_collision#show"
+ end
+ end
+
assert_equal "/c/1", routes_collision_path(1)
assert_equal "/fc/1", routes_forced_collision_path(1)
end
@@ -2204,86 +2540,100 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_explicitly_avoiding_the_named_route
+ draw do
+ scope :as => "routes" do
+ get "/c/:id", :as => :collision, :to => "collision#show"
+ get "/collision", :to => "collision#show"
+ get "/no_collision", :to => "collision#show", :as => nil
+
+ get "/fc/:id", :as => :forced_collision, :to => "forced_collision#show"
+ get "/forced_collision", :as => :forced_collision, :to => "forced_collision#show"
+ end
+ end
+
assert !respond_to?(:routes_no_collision_path)
end
def test_controller_name_with_leading_slash_raise_error
assert_raise(ArgumentError) do
- self.class.stub_controllers do |routes|
- routes.draw { get '/feeds/:service', :to => '/feeds#show' }
- end
+ draw { get '/feeds/:service', :to => '/feeds#show' }
end
assert_raise(ArgumentError) do
- self.class.stub_controllers do |routes|
- routes.draw { get '/feeds/:service', :controller => '/feeds', :action => 'show' }
- end
+ draw { get '/feeds/:service', :controller => '/feeds', :action => 'show' }
end
assert_raise(ArgumentError) do
- self.class.stub_controllers do |routes|
- routes.draw { get '/api/feeds/:service', :to => '/api/feeds#show' }
- end
+ draw { get '/api/feeds/:service', :to => '/api/feeds#show' }
end
assert_raise(ArgumentError) do
- self.class.stub_controllers do |routes|
- routes.draw { controller("/feeds") { get '/feeds/:service', :to => :show } }
- end
+ draw { controller("/feeds") { get '/feeds/:service', :to => :show } }
end
assert_raise(ArgumentError) do
- self.class.stub_controllers do |routes|
- routes.draw { resources :feeds, :controller => '/feeds' }
- end
+ draw { resources :feeds, :controller => '/feeds' }
end
end
def test_invalid_route_name_raises_error
assert_raise(ArgumentError) do
- self.class.stub_controllers do |routes|
- routes.draw { get '/products', :to => 'products#index', :as => 'products ' }
- end
+ draw { get '/products', :to => 'products#index', :as => 'products ' }
end
assert_raise(ArgumentError) do
- self.class.stub_controllers do |routes|
- routes.draw { get '/products', :to => 'products#index', :as => ' products' }
- end
+ draw { get '/products', :to => 'products#index', :as => ' products' }
end
assert_raise(ArgumentError) do
- self.class.stub_controllers do |routes|
- routes.draw { get '/products', :to => 'products#index', :as => 'products!' }
- end
+ draw { get '/products', :to => 'products#index', :as => 'products!' }
end
assert_raise(ArgumentError) do
- self.class.stub_controllers do |routes|
- routes.draw { get '/products', :to => 'products#index', :as => 'products index' }
- end
+ draw { get '/products', :to => 'products#index', :as => 'products index' }
end
assert_raise(ArgumentError) do
- self.class.stub_controllers do |routes|
- routes.draw { get '/products', :to => 'products#index', :as => '1products' }
- end
+ draw { get '/products', :to => 'products#index', :as => '1products' }
end
end
def test_nested_route_in_nested_resource
+ draw do
+ resources :posts, :only => [:index, :show] do
+ resources :comments, :except => :destroy do
+ get "views" => "comments#views", :as => :views
+ end
+ end
+ end
+
get "/posts/1/comments/2/views"
assert_equal "comments#views", @response.body
assert_equal "/posts/1/comments/2/views", post_comment_views_path(:post_id => '1', :comment_id => '2')
end
def test_root_in_deeply_nested_scope
+ draw do
+ resources :posts, :only => [:index, :show] do
+ namespace :admin do
+ root :to => "index#index"
+ end
+ end
+ end
+
get "/posts/1/admin"
assert_equal "admin/index#index", @response.body
assert_equal "/posts/1/admin", post_admin_root_path(:post_id => '1')
end
def test_custom_param
+ draw do
+ resources :profiles, :param => :username do
+ get :details, :on => :member
+ resources :messages
+ end
+ end
+
get '/profiles/bob'
assert_equal 'profiles#show', @response.body
assert_equal 'bob', @request.params[:username]
@@ -2297,6 +2647,13 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_custom_param_constraint
+ draw do
+ resources :profiles, :param => :username, :username => /[a-z]+/ do
+ get :details, :on => :member
+ resources :messages
+ end
+ end
+
get '/profiles/bob1'
assert_equal 404, @response.status
@@ -2308,12 +2665,41 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
def test_shallow_custom_param
+ draw do
+ resources :orders do
+ constraints :download => /[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}/ do
+ resources :downloads, :param => :download, :shallow => true
+ end
+ end
+ end
+
get '/downloads/0c0c0b68-d24b-11e1-a861-001ff3fffe6f.zip'
assert_equal 'downloads#show', @response.body
assert_equal '0c0c0b68-d24b-11e1-a861-001ff3fffe6f', @request.params[:download]
end
private
+
+ def draw(&block)
+ self.class.stub_controllers do |routes|
+ @app = routes
+ @app.default_url_options = { host: 'www.example.com' }
+ @app.draw(&block)
+ end
+ end
+
+ def url_for(options = {})
+ @app.url_helpers.url_for(options)
+ end
+
+ def method_missing(method, *args, &block)
+ if method.to_s =~ /_(path|url)$/
+ @app.url_helpers.send(method, *args, &block)
+ else
+ super
+ end
+ end
+
def with_https
old_https = https?
https!
@@ -2333,6 +2719,67 @@ private
end
end
+class TestAltApp < ActionDispatch::IntegrationTest
+ class AltRequest
+ def initialize(env)
+ @env = env
+ end
+
+ def path_info
+ "/"
+ end
+
+ def request_method
+ "GET"
+ end
+
+ def ip
+ "127.0.0.1"
+ end
+
+ def x_header
+ @env["HTTP_X_HEADER"] || ""
+ end
+ end
+
+ class XHeader
+ def call(env)
+ [200, {"Content-Type" => "text/html"}, ["XHeader"]]
+ end
+ end
+
+ class AltApp
+ def call(env)
+ [200, {"Content-Type" => "text/html"}, ["Alternative App"]]
+ end
+ end
+
+ AltRoutes = ActionDispatch::Routing::RouteSet.new(AltRequest)
+ AltRoutes.draw do
+ get "/" => TestAltApp::XHeader.new, :constraints => {:x_header => /HEADER/}
+ get "/" => TestAltApp::AltApp.new
+ end
+
+ def app
+ AltRoutes
+ end
+
+ def test_alt_request_without_header
+ get "/"
+ assert_equal "Alternative App", @response.body
+ end
+
+ def test_alt_request_with_matched_header
+ get "/", {}, "HTTP_X_HEADER" => "HEADER"
+ assert_equal "XHeader", @response.body
+ end
+
+ def test_alt_request_with_unmatched_header
+ get "/", {}, "HTTP_X_HEADER" => "NON_MATCH"
+ assert_equal "Alternative App", @response.body
+ end
+end
+
class TestAppendingRoutes < ActionDispatch::IntegrationTest
def simple_app(resp)
lambda { |e| [ 200, { 'Content-Type' => 'text/plain' }, [resp] ] }