mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
462d7cb314
If we set :shallow_path when shallow is called it can result in incorrect paths if the resource is inside a namespace because namespace itself sets the :shallow_path option to the namespace path. We fix this by removing the :shallow_path option from shallow as that should only be turning shallow routes on and not otherwise affecting the scope. To do this we need to treat the :shallow option to resources differently to other scope options and move it to before the nested block is called. This change also has the positive side effect of making the behavior of the :shallow option consistent with the shallow method. Fixes #12498.
3904 lines
111 KiB
Ruby
3904 lines
111 KiB
Ruby
# encoding: UTF-8
|
|
require 'erb'
|
|
require 'abstract_unit'
|
|
require 'controller/fake_controllers'
|
|
|
|
class TestRoutingMapper < ActionDispatch::IntegrationTest
|
|
SprocketsApp = lambda { |env|
|
|
[200, {"Content-Type" => "text/html"}, ["javascripts"]]
|
|
}
|
|
|
|
class IpRestrictor
|
|
def self.matches?(request)
|
|
request.ip =~ /192\.168\.1\.1\d\d/
|
|
end
|
|
end
|
|
|
|
class YoutubeFavoritesRedirector
|
|
def self.call(params, request)
|
|
"http://www.youtube.com/watch?v=#{params[:youtube_id]}"
|
|
end
|
|
end
|
|
|
|
def test_logout
|
|
draw do
|
|
controller :sessions do
|
|
delete 'logout' => :destroy
|
|
end
|
|
end
|
|
|
|
delete '/logout'
|
|
assert_equal 'sessions#destroy', @response.body
|
|
|
|
assert_equal '/logout', logout_path
|
|
assert_equal '/logout', url_for(:controller => 'sessions', :action => 'destroy', :only_path => true)
|
|
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
|
|
|
|
post '/login'
|
|
assert_equal 'sessions#create', @response.body
|
|
|
|
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', 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
|
|
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
|
|
|
|
post '/session'
|
|
assert_equal 'sessions#create', @response.body
|
|
|
|
put '/session'
|
|
assert_equal 'sessions#update', @response.body
|
|
|
|
delete '/session'
|
|
assert_equal 'sessions#destroy', @response.body
|
|
|
|
get '/session/new'
|
|
assert_equal 'sessions#new', @response.body
|
|
assert_equal '/session/new', new_session_path
|
|
|
|
get '/session/edit'
|
|
assert_equal 'sessions#edit', @response.body
|
|
assert_equal '/session/edit', edit_session_path
|
|
|
|
post '/session/reset'
|
|
assert_equal 'sessions#reset', @response.body
|
|
assert_equal '/session/reset', reset_session_path
|
|
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
|
|
|
|
post '/openid/login'
|
|
assert_equal 'openid#login', @response.body
|
|
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
|
|
|
|
post '/bookmark/create'
|
|
assert_equal 'bookmarks#create', @response.body
|
|
assert_equal '/bookmark/create', bookmark_path
|
|
|
|
put '/bookmark/update'
|
|
assert_equal 'bookmarks#update', @response.body
|
|
assert_equal '/bookmark/update', bookmark_update_path
|
|
|
|
get '/bookmark/remove'
|
|
assert_equal 'bookmarks#destroy', @response.body
|
|
assert_equal '/bookmark/remove', bookmark_remove_path
|
|
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
|
|
|
|
post '/pagemark/create'
|
|
assert_equal 'pagemarks#create', @response.body
|
|
assert_equal '/pagemark/create', pagemark_path
|
|
|
|
put '/pagemark/update'
|
|
assert_equal 'pagemarks#update', @response.body
|
|
assert_equal '/pagemark/update', pagemark_update_path
|
|
|
|
get '/pagemark/remove'
|
|
assert_equal 'pagemarks#destroy', @response.body
|
|
assert_equal '/pagemark/remove', pagemark_remove_path
|
|
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
|
|
|
|
get '/admin', {}, {'REMOTE_ADDR' => '10.0.0.100'}
|
|
assert_equal 'pass', @response.headers['X-Cascade']
|
|
|
|
get '/admin/accounts', {}, {'REMOTE_ADDR' => '192.168.1.100'}
|
|
assert_equal 'queenbee#accounts', @response.body
|
|
|
|
get '/admin/accounts', {}, {'REMOTE_ADDR' => '10.0.0.100'}
|
|
assert_equal 'pass', @response.headers['X-Cascade']
|
|
|
|
get '/admin/passwords', {}, {'REMOTE_ADDR' => '192.168.1.100'}
|
|
assert_equal 'queenbee#passwords', @response.body
|
|
|
|
get '/admin/passwords', {}, {'REMOTE_ADDR' => '10.0.0.100'}
|
|
assert_equal 'pass', @response.headers['X-Cascade']
|
|
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
|
|
|
|
get '/global/export'
|
|
assert_equal 'global#export', @response.body
|
|
|
|
get '/global/hide_notice'
|
|
assert_equal 'global#hide_notice', @response.body
|
|
|
|
get '/export/123/foo.txt'
|
|
assert_equal 'global#export', @response.body
|
|
|
|
assert_equal '/global/export', export_request_path
|
|
assert_equal '/global/hide_notice', global_hide_notice_path
|
|
assert_equal '/export/123/foo.txt', export_download_path(:id => 123, :file => 'foo.txt')
|
|
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
|
|
|
|
url_for options
|
|
|
|
# verify that the options passed in have not changed from the original ones
|
|
assert_equal original_options, options
|
|
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)
|
|
|
|
assert_equal '/projects/status', url
|
|
assert_equal '/projects', controller
|
|
end
|
|
|
|
# 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
|
|
|
|
profile_customer_url("customer_model", options)
|
|
|
|
# verify that the options passed in have not changed from the original ones
|
|
assert_equal original_options, options
|
|
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
|
|
|
|
post '/projects'
|
|
assert_equal 'project#create', @response.body
|
|
|
|
get '/projects.xml'
|
|
assert_equal 'project#index', @response.body
|
|
assert_equal '/projects.xml', projects_path(:format => 'xml')
|
|
|
|
get '/projects/new'
|
|
assert_equal 'project#new', @response.body
|
|
assert_equal '/projects/new', new_project_path
|
|
|
|
get '/projects/new.xml'
|
|
assert_equal 'project#new', @response.body
|
|
assert_equal '/projects/new.xml', new_project_path(:format => 'xml')
|
|
|
|
get '/projects/1'
|
|
assert_equal 'project#show', @response.body
|
|
assert_equal '/projects/1', project_path(:id => '1')
|
|
|
|
get '/projects/1.xml'
|
|
assert_equal 'project#show', @response.body
|
|
assert_equal '/projects/1.xml', project_path(:id => '1', :format => 'xml')
|
|
|
|
get '/projects/1/edit'
|
|
assert_equal 'project#edit', @response.body
|
|
assert_equal '/projects/1/edit', edit_project_path(:id => '1')
|
|
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')
|
|
|
|
get '/projects/1/involvements/new'
|
|
assert_equal 'involvements#new', @response.body
|
|
assert_equal '/projects/1/involvements/new', new_project_involvement_path(:project_id => '1')
|
|
|
|
get '/projects/1/involvements/1'
|
|
assert_equal 'involvements#show', @response.body
|
|
assert_equal '/projects/1/involvements/1', project_involvement_path(:project_id => '1', :id => '1')
|
|
|
|
put '/projects/1/involvements/1'
|
|
assert_equal 'involvements#update', @response.body
|
|
|
|
delete '/projects/1/involvements/1'
|
|
assert_equal 'involvements#destroy', @response.body
|
|
|
|
get '/projects/1/involvements/1/edit'
|
|
assert_equal 'involvements#edit', @response.body
|
|
assert_equal '/projects/1/involvements/1/edit', edit_project_involvement_path(:project_id => '1', :id => '1')
|
|
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')
|
|
|
|
put '/projects/1/participants/update_all'
|
|
assert_equal 'participants#update_all', @response.body
|
|
assert_equal '/projects/1/participants/update_all', update_all_project_participants_path(:project_id => '1')
|
|
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')
|
|
|
|
get '/projects/1/companies/1/people'
|
|
assert_equal 'people#index', @response.body
|
|
assert_equal '/projects/1/companies/1/people', project_company_people_path(:project_id => '1', :company_id => '1')
|
|
|
|
get '/projects/1/companies/1/avatar'
|
|
assert_equal 'avatar#show', @response.body
|
|
assert_equal '/projects/1/companies/1/avatar', project_company_avatar_path(:project_id => '1', :company_id => '1')
|
|
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')
|
|
|
|
get '/projects/1/manager/new'
|
|
assert_equal 'managers#new', @response.body
|
|
assert_equal '/projects/1/manager/new', new_project_super_manager_path(:project_id => '1')
|
|
|
|
post '/projects/1/manager/fire'
|
|
assert_equal 'managers#fire', @response.body
|
|
assert_equal '/projects/1/manager/fire', fire_project_super_manager_path(:project_id => '1')
|
|
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')
|
|
|
|
get '/projects/1/images/new'
|
|
assert_equal 'images#new', @response.body
|
|
assert_equal '/projects/1/images/new', new_project_funny_image_path(:project_id => '1')
|
|
|
|
post '/projects/1/images/1/revise'
|
|
assert_equal 'images#revise', @response.body
|
|
assert_equal '/projects/1/images/1/revise', revise_project_funny_image_path(:project_id => '1', :id => '1')
|
|
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')
|
|
|
|
get '/projects/1/people/1'
|
|
assert_equal 'people#show', @response.body
|
|
assert_equal '/projects/1/people/1', project_person_path(:project_id => '1', :id => '1')
|
|
|
|
get '/projects/1/people/1/7a2dec8/avatar'
|
|
assert_equal 'avatars#show', @response.body
|
|
assert_equal '/projects/1/people/1/7a2dec8/avatar', project_person_avatar_path(:project_id => '1', :person_id => '1', :access_token => '7a2dec8')
|
|
|
|
put '/projects/1/people/1/accessible_projects'
|
|
assert_equal 'people#accessible_projects', @response.body
|
|
assert_equal '/projects/1/people/1/accessible_projects', accessible_projects_project_person_path(:project_id => '1', :id => '1')
|
|
|
|
post '/projects/1/people/1/resend'
|
|
assert_equal 'people#resend', @response.body
|
|
assert_equal '/projects/1/people/1/resend', resend_project_person_path(:project_id => '1', :id => '1')
|
|
|
|
post '/projects/1/people/1/generate_new_password'
|
|
assert_equal 'people#generate_new_password', @response.body
|
|
assert_equal '/projects/1/people/1/generate_new_password', generate_new_password_project_person_path(:project_id => '1', :id => '1')
|
|
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 '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')
|
|
|
|
get '/projects/1/posts/archive'
|
|
assert_equal 'posts#archive', @response.body
|
|
assert_equal '/projects/1/posts/archive', archive_project_posts_path(:project_id => '1')
|
|
|
|
get '/projects/1/posts/toggle_view'
|
|
assert_equal 'posts#toggle_view', @response.body
|
|
assert_equal '/projects/1/posts/toggle_view', toggle_view_project_posts_path(:project_id => '1')
|
|
|
|
post '/projects/1/posts/1/preview'
|
|
assert_equal 'posts#preview', @response.body
|
|
assert_equal '/projects/1/posts/1/preview', preview_project_post_path(:project_id => '1', :id => '1')
|
|
|
|
get '/projects/1/posts/1/subscription'
|
|
assert_equal 'subscriptions#show', @response.body
|
|
assert_equal '/projects/1/posts/1/subscription', project_post_subscription_path(:project_id => '1', :post_id => '1')
|
|
|
|
get '/projects/1/posts/1/comments'
|
|
assert_equal 'comments#index', @response.body
|
|
assert_equal '/projects/1/posts/1/comments', project_post_comments_path(:project_id => '1', :post_id => '1')
|
|
|
|
post '/projects/1/posts/1/comments/preview'
|
|
assert_equal 'comments#preview', @response.body
|
|
assert_equal '/projects/1/posts/1/comments/preview', preview_project_post_comments_path(:project_id => '1', :post_id => '1')
|
|
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
|
|
|
|
delete '/replies/1/answer'
|
|
assert_equal 'replies#unmark_as_answer', @response.body
|
|
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
|
|
|
|
get '/posts/1'
|
|
assert_equal 'posts#show', @response.body
|
|
assert_equal '/posts/1', post_path(:id => 1)
|
|
|
|
get '/posts/1/comments'
|
|
assert_equal 'comments#index', @response.body
|
|
assert_equal '/posts/1/comments', post_comments_path(:post_id => 1)
|
|
|
|
post '/posts'
|
|
assert_equal 'pass', @response.headers['X-Cascade']
|
|
put '/posts/1'
|
|
assert_equal 'pass', @response.headers['X-Cascade']
|
|
delete '/posts/1'
|
|
assert_equal 'pass', @response.headers['X-Cascade']
|
|
delete '/posts/1/comments'
|
|
assert_equal 'pass', @response.headers['X-Cascade']
|
|
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
|
|
|
|
patch '/present'
|
|
assert_equal 'presents#update', @response.body
|
|
assert_equal '/present', present_path
|
|
|
|
put '/present'
|
|
assert_equal 'presents#update', @response.body
|
|
assert_equal '/present', present_path
|
|
|
|
post '/future'
|
|
assert_equal 'futures#create', @response.body
|
|
assert_equal '/future', future_path
|
|
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
|
|
|
|
delete '/relationships/1'
|
|
assert_equal 'relationships#destroy', @response.body
|
|
assert_equal '/relationships/1', relationship_path(1)
|
|
|
|
patch '/friendships/1'
|
|
assert_equal 'friendships#update', @response.body
|
|
assert_equal '/friendships/1', friendship_path(1)
|
|
|
|
put '/friendships/1'
|
|
assert_equal 'friendships#update', @response.body
|
|
assert_equal '/friendships/1', friendship_path(1)
|
|
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
|
|
assert_equal '/sheep/1/edit', edit_sheep_path(1)
|
|
assert_equal '/sheep/1/_it', _it_sheep_path(1)
|
|
end
|
|
|
|
def test_resource_does_not_modify_passed_options
|
|
options = {:id => /.+?/, :format => /json|xml/}
|
|
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/}
|
|
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
|
|
|
|
get '/pt/projetos/1/editar'
|
|
assert_equal 'projects#edit', @response.body
|
|
assert_equal '/pt/projetos/1/editar', edit_pt_project_path(1)
|
|
|
|
get '/pt/administrador'
|
|
assert_equal 'admins#show', @response.body
|
|
assert_equal '/pt/administrador', pt_admin_path
|
|
|
|
get '/pt/administrador/novo'
|
|
assert_equal 'admins#new', @response.body
|
|
assert_equal '/pt/administrador/novo', new_pt_admin_path
|
|
|
|
put '/pt/administrador/ativar'
|
|
assert_equal 'admins#activate', @response.body
|
|
assert_equal '/pt/administrador/ativar', activate_pt_admin_path
|
|
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
|
|
|
|
put '/pt/projetos/1/fechar'
|
|
assert_equal 'projects#close', @response.body
|
|
assert_equal '/pt/projetos/1/fechar', close_pt_project_path(1)
|
|
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
|
|
|
|
assert_equal '/people/1/update', update_person_path(:id => 1)
|
|
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
|
|
|
|
assert_equal '/projects/1/people/2/update', update_project_person_path(:project_id => 1, :id => 2)
|
|
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
|
|
|
|
get '/forum/basecamp'
|
|
assert_equal 'forum/products#show', @response.body
|
|
assert_equal '/forum/basecamp', forum_product_path(:id => 'basecamp')
|
|
|
|
get '/forum/basecamp/questions'
|
|
assert_equal 'forum/questions#index', @response.body
|
|
assert_equal '/forum/basecamp/questions', forum_product_questions_path(:product_id => 'basecamp')
|
|
|
|
get '/forum/basecamp/questions/1'
|
|
assert_equal 'forum/questions#show', @response.body
|
|
assert_equal '/forum/basecamp/questions/1', forum_product_question_path(:product_id => 'basecamp', :id => 1)
|
|
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
|
|
|
|
assert_equal '/articles/2009/8/18/rails-3', article_path(:year => 2009, :month => 8, :day => 18, :title => 'rails-3')
|
|
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
|
|
|
|
get '/account/credit'
|
|
assert_equal 'account/credits#show', @response.body
|
|
assert_equal '/account/credit', account_credit_path
|
|
|
|
get '/account/credit_card'
|
|
assert_equal 'account/credit_cards#show', @response.body
|
|
assert_equal '/account/credit_card', account_credit_card_path
|
|
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
|
|
|
|
get '/clients/1/google/account/secret/info'
|
|
assert_equal '/clients/1/google/account/secret/info', client_google_account_secret_info_path(1)
|
|
assert_equal 'google/secret/infos#show', @response.body
|
|
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_namespace_containing_numbers
|
|
draw do
|
|
namespace :v2 do
|
|
resources :subscriptions
|
|
end
|
|
end
|
|
|
|
get '/v2/subscriptions'
|
|
assert_equal 'v2/subscriptions#index', @response.body
|
|
assert_equal '/v2/subscriptions', v2_subscriptions_path
|
|
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
|
|
|
|
get '/articles/123/1'
|
|
assert_equal 'pass', @response.headers['X-Cascade']
|
|
|
|
assert_equal '/articles/rails/1', article_with_title_path(:title => 'rails', :id => 1)
|
|
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
|
|
|
|
get '/12345/rooms/1'
|
|
assert_equal 'rooms#show', @response.body
|
|
|
|
get '/12345/rooms/1/edit'
|
|
assert_equal 'rooms#edit', @response.body
|
|
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_scoped_root_as_name
|
|
draw do
|
|
scope '(:locale)', :locale => /en|pl/ do
|
|
root :to => 'projects#index', :as => 'projects'
|
|
end
|
|
end
|
|
|
|
assert_equal '/en', projects_path(:locale => 'en')
|
|
assert_equal '/', projects_path
|
|
get '/en'
|
|
assert_equal 'projects#index', @response.body
|
|
end
|
|
|
|
def test_scope_with_format_option
|
|
draw do
|
|
get "direct/index", as: :no_format_direct, format: false
|
|
|
|
scope format: false do
|
|
get "scoped/index", as: :no_format_scoped
|
|
end
|
|
end
|
|
|
|
assert_equal "/direct/index", no_format_direct_path
|
|
assert_equal "/direct/index?format=html", no_format_direct_path(format: "html")
|
|
|
|
assert_equal "/scoped/index", no_format_scoped_path
|
|
assert_equal "/scoped/index?format=html", no_format_scoped_path(format: "html")
|
|
|
|
get '/scoped/index'
|
|
assert_equal "scoped#index", @response.body
|
|
|
|
get '/scoped/index.html'
|
|
assert_equal "Not Found", @response.body
|
|
end
|
|
|
|
def test_resources_with_format_false_from_scope
|
|
draw do
|
|
scope format: false do
|
|
resources :posts
|
|
resource :user
|
|
end
|
|
end
|
|
|
|
get "/posts"
|
|
assert_response :success
|
|
assert_equal "posts#index", @response.body
|
|
assert_equal "/posts", posts_path
|
|
|
|
get "/posts.html"
|
|
assert_response :not_found
|
|
assert_equal "Not Found", @response.body
|
|
assert_equal "/posts?format=html", posts_path(format: "html")
|
|
|
|
get "/user"
|
|
assert_response :success
|
|
assert_equal "users#show", @response.body
|
|
assert_equal "/user", user_path
|
|
|
|
get "/user.html"
|
|
assert_response :not_found
|
|
assert_equal "Not Found", @response.body
|
|
assert_equal "/user?format=html", user_path(format: "html")
|
|
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_with_many_paths_containing_a_slash
|
|
draw do
|
|
get 'get/first', 'get/second', 'get/third', :to => 'get#show'
|
|
end
|
|
|
|
get '/get/first'
|
|
assert_equal 'get#show', @response.body
|
|
|
|
get '/get/second'
|
|
assert_equal 'get#show', @response.body
|
|
|
|
get '/get/third'
|
|
assert_equal 'get#show', @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_with_multiple_paths_inside_namespace
|
|
draw do
|
|
namespace :proposals do
|
|
put 'activate', 'inactivate'
|
|
end
|
|
end
|
|
|
|
put '/proposals/activate'
|
|
assert_equal 'proposals#activate', @response.body
|
|
|
|
put '/proposals/inactivate'
|
|
assert_equal 'proposals#inactivate', @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_match_shorthand_inside_scope_with_variables_with_controller
|
|
draw do
|
|
scope ':locale' do
|
|
match 'questions/new', via: [:get]
|
|
end
|
|
end
|
|
|
|
get '/de/questions/new'
|
|
assert_equal 'questions#new', @response.body
|
|
assert_equal 'de', @request.params[:locale]
|
|
end
|
|
|
|
def test_match_shorthand_inside_nested_namespaces_and_scopes_with_controller
|
|
draw do
|
|
namespace :api do
|
|
namespace :v3 do
|
|
scope ':locale' do
|
|
get "products/list"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
get '/api/v3/en/products/list'
|
|
assert_equal 'api/v3/products#list', @response.body
|
|
end
|
|
|
|
def test_controller_option_with_nesting_and_leading_slash
|
|
draw do
|
|
scope '/job', controller: 'job' do
|
|
scope ':id', action: 'manage_applicant' do
|
|
get "/active"
|
|
end
|
|
end
|
|
end
|
|
|
|
get '/job/5/active'
|
|
assert_equal 'job#manage_applicant', @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
|
|
|
|
get '/account/whatever/callback'
|
|
assert_equal 'Not Found', @response.body
|
|
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'
|
|
verify_redirect 'http://www.example.com:3000/login'
|
|
ensure
|
|
self.host = previous_host
|
|
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'
|
|
assert_equal 'account#description', @response.body
|
|
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)
|
|
assert_equal '/descriptions/1', description_path(nil, 1)
|
|
|
|
get '/en/descriptions'
|
|
assert_equal 'descriptions#index', @response.body
|
|
|
|
get '/descriptions'
|
|
assert_equal 'descriptions#index', @response.body
|
|
|
|
get '/en/descriptions/1'
|
|
assert_equal 'descriptions#show', @response.body
|
|
|
|
get '/descriptions/1'
|
|
assert_equal 'descriptions#show', @response.body
|
|
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)
|
|
assert_equal '/admin/descriptions/1', admin_description_path(nil, 1)
|
|
|
|
get '/admin/en/descriptions'
|
|
assert_equal 'admin/descriptions#index', @response.body
|
|
|
|
get '/admin/descriptions'
|
|
assert_equal 'admin/descriptions#index', @response.body
|
|
|
|
get '/admin/en/descriptions/1'
|
|
assert_equal 'admin/descriptions#show', @response.body
|
|
|
|
get '/admin/descriptions/1'
|
|
assert_equal 'admin/descriptions#show', @response.body
|
|
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]
|
|
|
|
get '/en/registrations/new'
|
|
assert_equal 'en', @request.params[:locale]
|
|
end
|
|
|
|
def test_default_string_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]
|
|
|
|
get '/default_pages'
|
|
assert_equal 'home', @request.params[:id]
|
|
|
|
get '/scoped_pages'
|
|
assert_equal 'home', @request.params[:id]
|
|
end
|
|
|
|
def test_default_integer_params
|
|
draw do
|
|
get 'inline_pages/(:page)', to: 'pages#show', page: 1
|
|
get 'default_pages/(:page)', to: 'pages#show', defaults: { page: 1 }
|
|
|
|
defaults page: 1 do
|
|
get 'scoped_pages/(:page)', to: 'pages#show'
|
|
end
|
|
end
|
|
|
|
get '/inline_pages'
|
|
assert_equal 1, @request.params[:page]
|
|
|
|
get '/default_pages'
|
|
assert_equal 1, @request.params[:page]
|
|
|
|
get '/scoped_pages'
|
|
assert_equal 1, @request.params[:page]
|
|
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'
|
|
assert_equal 'products#root', @response.body
|
|
get '/products/favorite'
|
|
assert_equal 'products#favorite', @response.body
|
|
get '/products/0001'
|
|
assert_equal 'products#show', @response.body
|
|
|
|
get '/products/1/images'
|
|
assert_equal 'pass', @response.headers['X-Cascade']
|
|
get '/products/0001/images'
|
|
assert_equal 'images#index', @response.body
|
|
get '/products/0001/images/0001'
|
|
assert_equal 'images#show', @response.body
|
|
|
|
get '/dashboard', {}, {'REMOTE_ADDR' => '10.0.0.100'}
|
|
assert_equal 'pass', @response.headers['X-Cascade']
|
|
get '/dashboard', {}, {'REMOTE_ADDR' => '192.168.1.100'}
|
|
assert_equal 'dashboards#show', @response.body
|
|
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
|
|
|
|
get '/api'
|
|
assert_equal 'mes#index', @response.body
|
|
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
|
|
|
|
get '/api/v2'
|
|
assert_equal 'mes#index', @response.body
|
|
|
|
get '/api/v3/admin/me'
|
|
assert_equal 'mes#show', @response.body
|
|
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
|
|
|
|
assert_equal 'http://www.example.com/whatever/foo/bar/1',
|
|
url_for(:controller => "foo", :action => "bar", :id => 1)
|
|
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
|
|
|
|
get 'whatever/foo/bar/show/1'
|
|
assert_equal 'foo/bar#show', @response.body
|
|
|
|
assert_equal 'http://www.example.com/whatever/foo/bar/show',
|
|
url_for(:controller => "foo/bar", :action => "show")
|
|
|
|
assert_equal 'http://www.example.com/whatever/foo/bar/show/1',
|
|
url_for(:controller => "foo/bar", :action => "show", :id => '1')
|
|
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
|
|
assert_equal '/pt/products/novo/preview', preview_new_pt_product_path
|
|
assert_equal '/profile/new/preview', preview_new_profile_path
|
|
|
|
post '/replies/new/preview'
|
|
assert_equal 'replies#preview', @response.body
|
|
|
|
post '/pt/projetos/novo/preview'
|
|
assert_equal 'projects#preview', @response.body
|
|
|
|
post '/pt/administrador/novo/preview'
|
|
assert_equal 'admins#preview', @response.body
|
|
|
|
post '/pt/products/novo/preview'
|
|
assert_equal 'products#preview', @response.body
|
|
|
|
post '/profile/new/preview'
|
|
assert_equal 'profiles#preview', @response.body
|
|
end
|
|
|
|
def test_resource_merges_options_from_scope
|
|
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'
|
|
assert_equal 404, status
|
|
|
|
assert_raise(NoMethodError) { edit_product_image_path('1', '2') }
|
|
|
|
post '/products/1/images/2/edit'
|
|
assert_equal 404, status
|
|
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
|
|
|
|
get '/api/teams/new'
|
|
assert_equal 'api/teams#new', @response.body
|
|
assert_equal '/api/teams/new', new_api_team_path
|
|
|
|
get '/api/teams/1'
|
|
assert_equal 'api/teams#show', @response.body
|
|
assert_equal '/api/teams/1', api_team_path(:id => '1')
|
|
|
|
get '/api/teams/1/edit'
|
|
assert_equal 'api/teams#edit', @response.body
|
|
assert_equal '/api/teams/1/edit', edit_api_team_path(:id => '1')
|
|
|
|
get '/api/teams/1/players'
|
|
assert_equal 'api/players#index', @response.body
|
|
assert_equal '/api/teams/1/players', api_team_players_path(:team_id => '1')
|
|
|
|
get '/api/teams/1/players/new'
|
|
assert_equal 'api/players#new', @response.body
|
|
assert_equal '/api/teams/1/players/new', new_api_team_player_path(:team_id => '1')
|
|
|
|
get '/api/players/2'
|
|
assert_equal 'api/players#show', @response.body
|
|
assert_equal '/api/players/2', api_player_path(:id => '2')
|
|
|
|
get '/api/players/2/edit'
|
|
assert_equal 'api/players#edit', @response.body
|
|
assert_equal '/api/players/2/edit', edit_api_player_path(:id => '2')
|
|
|
|
get '/api/teams/1/captain'
|
|
assert_equal 'api/captains#show', @response.body
|
|
assert_equal '/api/teams/1/captain', api_team_captain_path(:team_id => '1')
|
|
|
|
get '/api/teams/1/captain/new'
|
|
assert_equal 'api/captains#new', @response.body
|
|
assert_equal '/api/teams/1/captain/new', new_api_team_captain_path(:team_id => '1')
|
|
|
|
get '/api/teams/1/captain/edit'
|
|
assert_equal 'api/captains#edit', @response.body
|
|
assert_equal '/api/teams/1/captain/edit', edit_api_team_captain_path(:team_id => '1')
|
|
|
|
get '/threads'
|
|
assert_equal 'threads#index', @response.body
|
|
assert_equal '/threads', threads_path
|
|
|
|
get '/threads/new'
|
|
assert_equal 'threads#new', @response.body
|
|
assert_equal '/threads/new', new_thread_path
|
|
|
|
get '/threads/1'
|
|
assert_equal 'threads#show', @response.body
|
|
assert_equal '/threads/1', thread_path(:id => '1')
|
|
|
|
get '/threads/1/edit'
|
|
assert_equal 'threads#edit', @response.body
|
|
assert_equal '/threads/1/edit', edit_thread_path(:id => '1')
|
|
|
|
get '/threads/1/owner'
|
|
assert_equal 'owners#show', @response.body
|
|
assert_equal '/threads/1/owner', thread_owner_path(:thread_id => '1')
|
|
|
|
get '/threads/1/messages'
|
|
assert_equal 'messages#index', @response.body
|
|
assert_equal '/threads/1/messages', thread_messages_path(:thread_id => '1')
|
|
|
|
get '/threads/1/messages/new'
|
|
assert_equal 'messages#new', @response.body
|
|
assert_equal '/threads/1/messages/new', new_thread_message_path(:thread_id => '1')
|
|
|
|
get '/messages/2'
|
|
assert_equal 'messages#show', @response.body
|
|
assert_equal '/messages/2', message_path(:id => '2')
|
|
|
|
get '/messages/2/edit'
|
|
assert_equal 'messages#edit', @response.body
|
|
assert_equal '/messages/2/edit', edit_message_path(:id => '2')
|
|
|
|
get '/messages/2/comments'
|
|
assert_equal 'comments#index', @response.body
|
|
assert_equal '/messages/2/comments', message_comments_path(:message_id => '2')
|
|
|
|
get '/messages/2/comments/new'
|
|
assert_equal 'comments#new', @response.body
|
|
assert_equal '/messages/2/comments/new', new_message_comment_path(:message_id => '2')
|
|
|
|
get '/comments/3'
|
|
assert_equal 'comments#show', @response.body
|
|
assert_equal '/comments/3', comment_path(:id => '3')
|
|
|
|
get '/comments/3/edit'
|
|
assert_equal 'comments#edit', @response.body
|
|
assert_equal '/comments/3/edit', edit_comment_path(:id => '3')
|
|
|
|
post '/comments/3/preview'
|
|
assert_equal 'comments#preview', @response.body
|
|
assert_equal '/comments/3/preview', preview_comment_path(:id => '3')
|
|
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)
|
|
|
|
get '/hello/notes/1/edit'
|
|
assert_equal 'notes#edit', @response.body
|
|
assert_equal '/hello/notes/1/edit', edit_note_path(:id => '1')
|
|
|
|
get '/hello/notes/1/trackbacks/new'
|
|
assert_equal 'trackbacks#new', @response.body
|
|
assert_equal '/hello/notes/1/trackbacks/new', new_note_trackback_path(:note_id => 1)
|
|
|
|
get '/hello/trackbacks/1'
|
|
assert_equal 'trackbacks#show', @response.body
|
|
assert_equal '/hello/trackbacks/1', trackback_path(:id => '1')
|
|
|
|
get '/hello/trackbacks/1/edit'
|
|
assert_equal 'trackbacks#edit', @response.body
|
|
assert_equal '/hello/trackbacks/1/edit', edit_trackback_path(:id => '1')
|
|
|
|
put '/hello/trackbacks/1'
|
|
assert_equal 'trackbacks#update', @response.body
|
|
|
|
post '/hello/notes/1/trackbacks'
|
|
assert_equal 'trackbacks#create', @response.body
|
|
|
|
delete '/hello/trackbacks/1'
|
|
assert_equal 'trackbacks#destroy', @response.body
|
|
|
|
get '/hello/notes'
|
|
assert_equal 'notes#index', @response.body
|
|
|
|
post '/hello/notes'
|
|
assert_equal 'notes#create', @response.body
|
|
|
|
get '/hello/notes/new'
|
|
assert_equal 'notes#new', @response.body
|
|
assert_equal '/hello/notes/new', new_note_path
|
|
|
|
get '/hello/notes/1'
|
|
assert_equal 'notes#show', @response.body
|
|
assert_equal '/hello/notes/1', note_path(:id => 1)
|
|
|
|
put '/hello/notes/1'
|
|
assert_equal 'notes#update', @response.body
|
|
|
|
delete '/hello/notes/1'
|
|
assert_equal 'notes#destroy', @response.body
|
|
end
|
|
|
|
def test_shallow_option_nested_resources_within_scope
|
|
draw do
|
|
scope '/hello' do
|
|
resources :notes, :shallow => true do
|
|
resources :trackbacks
|
|
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)
|
|
|
|
get '/hello/notes/1/edit'
|
|
assert_equal 'notes#edit', @response.body
|
|
assert_equal '/hello/notes/1/edit', edit_note_path(:id => '1')
|
|
|
|
get '/hello/notes/1/trackbacks/new'
|
|
assert_equal 'trackbacks#new', @response.body
|
|
assert_equal '/hello/notes/1/trackbacks/new', new_note_trackback_path(:note_id => 1)
|
|
|
|
get '/hello/trackbacks/1'
|
|
assert_equal 'trackbacks#show', @response.body
|
|
assert_equal '/hello/trackbacks/1', trackback_path(:id => '1')
|
|
|
|
get '/hello/trackbacks/1/edit'
|
|
assert_equal 'trackbacks#edit', @response.body
|
|
assert_equal '/hello/trackbacks/1/edit', edit_trackback_path(:id => '1')
|
|
|
|
put '/hello/trackbacks/1'
|
|
assert_equal 'trackbacks#update', @response.body
|
|
|
|
post '/hello/notes/1/trackbacks'
|
|
assert_equal 'trackbacks#create', @response.body
|
|
|
|
delete '/hello/trackbacks/1'
|
|
assert_equal 'trackbacks#destroy', @response.body
|
|
|
|
get '/hello/notes'
|
|
assert_equal 'notes#index', @response.body
|
|
|
|
post '/hello/notes'
|
|
assert_equal 'notes#create', @response.body
|
|
|
|
get '/hello/notes/new'
|
|
assert_equal 'notes#new', @response.body
|
|
assert_equal '/hello/notes/new', new_note_path
|
|
|
|
get '/hello/notes/1'
|
|
assert_equal 'notes#show', @response.body
|
|
assert_equal '/hello/notes/1', note_path(:id => 1)
|
|
|
|
put '/hello/notes/1'
|
|
assert_equal 'notes#update', @response.body
|
|
|
|
delete '/hello/notes/1'
|
|
assert_equal 'notes#destroy', @response.body
|
|
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')
|
|
assert_equal '/customers/new/preview', another_preview_new_customer_path
|
|
assert_equal '/customers/1/avatar/thumbnail.jpg', thumbnail_customer_avatar_path(:customer_id => '1', :format => :jpg)
|
|
assert_equal '/customers/1/invoices/outstanding', outstanding_customer_invoices_path(:customer_id => '1')
|
|
assert_equal '/customers/1/invoices/2/print', print_customer_invoice_path(:customer_id => '1', :id => '2')
|
|
assert_equal '/customers/1/invoices/new/preview', preview_new_customer_invoice_path(:customer_id => '1')
|
|
assert_equal '/customers/1/notes/new/preview', preview_new_customer_note_path(:customer_id => '1')
|
|
assert_equal '/notes/1/print', print_note_path(:id => '1')
|
|
assert_equal '/api/customers/recent', recent_api_customers_path
|
|
assert_equal '/api/customers/1/profile', profile_api_customer_path(:id => '1')
|
|
assert_equal '/api/customers/new/preview', preview_new_api_customer_path
|
|
|
|
get '/customers/1/invoices/overdue'
|
|
assert_equal 'invoices#overdue', @response.body
|
|
|
|
get '/customers/1/secret/profile'
|
|
assert_equal 'customers#secret', @response.body
|
|
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')
|
|
|
|
get '/notices/1'
|
|
assert_equal 'api/notices#show', @response.body
|
|
assert_equal '/notices/1', notice_path(:id => '1')
|
|
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')
|
|
|
|
get '/api/1.0/users.json'
|
|
assert_equal 'api/users#index', @response.body
|
|
assert_equal true, @request.format.json?
|
|
assert_equal '/api/1.0/users.json', api_users_path(:version => '1.0', :format => :json)
|
|
|
|
get '/api/1.0/users/first.last'
|
|
assert_equal 'api/users#show', @response.body
|
|
assert_equal 'first.last', @request.params[:id]
|
|
assert_equal '/api/1.0/users/first.last', api_user_path(:version => '1.0', :id => 'first.last')
|
|
|
|
get '/api/1.0/users/first.last.xml'
|
|
assert_equal 'api/users#show', @response.body
|
|
assert_equal 'first.last', @request.params[:id]
|
|
assert_equal true, @request.format.xml?
|
|
assert_equal '/api/1.0/users/first.last.xml', api_user_path(:version => '1.0', :id => 'first.last', :format => :xml)
|
|
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',
|
|
url_for(:controller => "followers", :action => "index", :username => "bob")
|
|
|
|
get '/followers'
|
|
assert_equal 'followers#index', @response.body
|
|
assert_equal 'http://www.example.com/followers',
|
|
url_for(:controller => "followers", :action => "index", :username => nil)
|
|
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',
|
|
url_for(:controller => "groups", :action => "index", :username => "bob")
|
|
|
|
get '/groups'
|
|
assert_equal 'groups#index', @response.body
|
|
assert_equal 'http://www.example.com/groups',
|
|
url_for(:controller => "groups", :action => "index", :username => nil)
|
|
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',
|
|
url_for(:controller => "photos", :action => "index", :username => "bob")
|
|
|
|
get 'photos'
|
|
assert_equal 'photos#index', @response.body
|
|
assert_equal 'http://www.example.com/photos',
|
|
url_for(:controller => "photos", :action => "index", :username => nil)
|
|
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
|
|
|
|
get '/groups/discussions/messages/1'
|
|
assert_equal 'messages#show', @response.body
|
|
|
|
get '/groups/messages'
|
|
assert_equal 'messages#index', @response.body
|
|
|
|
get '/groups/messages/1'
|
|
assert_equal 'messages#show', @response.body
|
|
|
|
get '/discussions/messages'
|
|
assert_equal 'messages#index', @response.body
|
|
|
|
get '/discussions/messages/1'
|
|
assert_equal 'messages#show', @response.body
|
|
|
|
get '/messages'
|
|
assert_equal 'messages#index', @response.body
|
|
|
|
get '/messages/1'
|
|
assert_equal 'messages#show', @response.body
|
|
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')
|
|
|
|
get '/movies/00001'
|
|
assert_equal 'Not Found', @response.body
|
|
assert_raises(ActionController::UrlGenerationError){ movie_path(:id => '00001') }
|
|
|
|
get '/movies/0001/reviews'
|
|
assert_equal 'reviews#index', @response.body
|
|
assert_equal '/movies/0001/reviews', movie_reviews_path(:movie_id => '0001')
|
|
|
|
get '/movies/00001/reviews'
|
|
assert_equal 'Not Found', @response.body
|
|
assert_raises(ActionController::UrlGenerationError){ movie_reviews_path(:movie_id => '00001') }
|
|
|
|
get '/movies/0001/reviews/0001'
|
|
assert_equal 'reviews#show', @response.body
|
|
assert_equal '/movies/0001/reviews/0001', movie_review_path(:movie_id => '0001', :id => '0001')
|
|
|
|
get '/movies/00001/reviews/0001'
|
|
assert_equal 'Not Found', @response.body
|
|
assert_raises(ActionController::UrlGenerationError){ movie_path(:movie_id => '00001', :id => '00001') }
|
|
|
|
get '/movies/0001/trailer'
|
|
assert_equal 'trailers#show', @response.body
|
|
assert_equal '/movies/0001/trailer', movie_trailer_path(:movie_id => '0001')
|
|
|
|
get '/movies/00001/trailer'
|
|
assert_equal 'Not Found', @response.body
|
|
assert_raises(ActionController::UrlGenerationError){ movie_trailer_path(:movie_id => '00001') }
|
|
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
|
|
|
|
get '/only/clubs/1/edit'
|
|
assert_equal 'Not Found', @response.body
|
|
assert_raise(NoMethodError) { edit_only_club_path(:id => '1') }
|
|
|
|
get '/only/clubs/1/players'
|
|
assert_equal 'only/players#index', @response.body
|
|
assert_equal '/only/clubs/1/players', only_club_players_path(:club_id => '1')
|
|
|
|
get '/only/clubs/1/players/2/edit'
|
|
assert_equal 'Not Found', @response.body
|
|
assert_raise(NoMethodError) { edit_only_club_player_path(:club_id => '1', :id => '2') }
|
|
|
|
get '/only/clubs/1/chairman'
|
|
assert_equal 'only/chairmen#show', @response.body
|
|
assert_equal '/only/clubs/1/chairman', only_club_chairman_path(:club_id => '1')
|
|
|
|
get '/only/clubs/1/chairman/edit'
|
|
assert_equal 'Not Found', @response.body
|
|
assert_raise(NoMethodError) { edit_only_club_chairman_path(:club_id => '1') }
|
|
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
|
|
|
|
get '/except/clubs/1/edit'
|
|
assert_equal 'Not Found', @response.body
|
|
assert_raise(NoMethodError) { edit_except_club_path(:id => '1') }
|
|
|
|
get '/except/clubs/1/players'
|
|
assert_equal 'except/players#index', @response.body
|
|
assert_equal '/except/clubs/1/players', except_club_players_path(:club_id => '1')
|
|
|
|
get '/except/clubs/1/players/2/edit'
|
|
assert_equal 'Not Found', @response.body
|
|
assert_raise(NoMethodError) { edit_except_club_player_path(:club_id => '1', :id => '2') }
|
|
|
|
get '/except/clubs/1/chairman'
|
|
assert_equal 'except/chairmen#show', @response.body
|
|
assert_equal '/except/clubs/1/chairman', except_club_chairman_path(:club_id => '1')
|
|
|
|
get '/except/clubs/1/chairman/edit'
|
|
assert_equal 'Not Found', @response.body
|
|
assert_raise(NoMethodError) { edit_except_club_chairman_path(:club_id => '1') }
|
|
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
|
|
|
|
get '/only/sectors/1'
|
|
assert_equal 'Not Found', @response.body
|
|
assert_raise(NoMethodError) { only_sector_path(:id => '1') }
|
|
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')
|
|
|
|
get '/only/sectors/1/leader'
|
|
assert_equal 'only/leaders#show', @response.body
|
|
assert_equal '/only/sectors/1/leader', only_sector_leader_path(:sector_id => '1')
|
|
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
|
|
|
|
get '/except/sectors/1'
|
|
assert_equal 'Not Found', @response.body
|
|
assert_raise(NoMethodError) { except_sector_path(:id => '1') }
|
|
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')
|
|
|
|
get '/except/sectors/1/leader'
|
|
assert_equal 'except/leaders#show', @response.body
|
|
assert_equal '/except/sectors/1/leader', except_sector_leader_path(:sector_id => '1')
|
|
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')
|
|
|
|
get '/only/sectors/1/managers/2'
|
|
assert_equal 'Not Found', @response.body
|
|
assert_raise(NoMethodError) { only_sector_manager_path(:sector_id => '1', :id => '2') }
|
|
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')
|
|
|
|
get '/except/sectors/1/managers/2'
|
|
assert_equal 'Not Found', @response.body
|
|
assert_raise(NoMethodError) { except_sector_manager_path(:sector_id => '1', :id => '2') }
|
|
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')
|
|
|
|
get '/only/sectors/1/companies/2/divisions/3'
|
|
assert_equal 'Not Found', @response.body
|
|
assert_raise(NoMethodError) { only_sector_company_division_path(:sector_id => '1', :company_id => '2', :id => '3') }
|
|
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')
|
|
|
|
get '/except/sectors/1/companies/2/divisions/3'
|
|
assert_equal 'Not Found', @response.body
|
|
assert_raise(NoMethodError) { except_sector_company_division_path(:sector_id => '1', :company_id => '2', :id => '3') }
|
|
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')
|
|
|
|
get '/only/sectors/1/companies/2/departments/3'
|
|
assert_equal 'Not Found', @response.body
|
|
assert_raise(NoMethodError) { only_sector_company_department_path(:sector_id => '1', :company_id => '2', :id => '3') }
|
|
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')
|
|
|
|
get '/except/sectors/1/companies/2/departments/3'
|
|
assert_equal 'Not Found', @response.body
|
|
assert_raise(NoMethodError) { except_sector_company_department_path(:sector_id => '1', :company_id => '2', :id => '3') }
|
|
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
|
|
|
|
get '/transport/taxis/new'
|
|
assert_equal 'transport/taxis#new', @response.body
|
|
assert_equal '/transport/taxis/new', new_transport_taxi_path
|
|
|
|
post '/transport/taxis'
|
|
assert_equal 'transport/taxis#create', @response.body
|
|
|
|
get '/transport/taxis/1'
|
|
assert_equal 'transport/taxis#show', @response.body
|
|
assert_equal '/transport/taxis/1', transport_taxi_path(:id => '1')
|
|
|
|
get '/transport/taxis/1/edit'
|
|
assert_equal 'transport/taxis#edit', @response.body
|
|
assert_equal '/transport/taxis/1/edit', edit_transport_taxi_path(:id => '1')
|
|
|
|
put '/transport/taxis/1'
|
|
assert_equal 'transport/taxis#update', @response.body
|
|
|
|
delete '/transport/taxis/1'
|
|
assert_equal 'transport/taxis#destroy', @response.body
|
|
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
|
|
|
|
post '/medical/taxis'
|
|
assert_equal 'medical/taxis#create', @response.body
|
|
|
|
get '/medical/taxis'
|
|
assert_equal 'medical/taxis#show', @response.body
|
|
assert_equal '/medical/taxis', medical_taxis_path
|
|
|
|
get '/medical/taxis/edit'
|
|
assert_equal 'medical/taxis#edit', @response.body
|
|
assert_equal '/medical/taxis/edit', edit_medical_taxis_path
|
|
|
|
put '/medical/taxis'
|
|
assert_equal 'medical/taxis#update', @response.body
|
|
|
|
delete '/medical/taxis'
|
|
assert_equal 'medical/taxis#destroy', @response.body
|
|
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')
|
|
|
|
get '/sections/1/preview'
|
|
assert_equal 'sections#preview', @response.body
|
|
assert_equal '/sections/1/preview', preview_section_path(:id => '1')
|
|
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')
|
|
|
|
get '/wiki/articles/Ruby_on_Rails_3.0/comments/new'
|
|
assert_equal 'wiki/comments#new', @response.body
|
|
assert_equal '/wiki/articles/Ruby_on_Rails_3.0/comments/new', new_wiki_article_comment_path(:article_id => 'Ruby_on_Rails_3.0')
|
|
|
|
post '/wiki/articles/Ruby_on_Rails_3.0/comments'
|
|
assert_equal 'wiki/comments#create', @response.body
|
|
assert_equal '/wiki/articles/Ruby_on_Rails_3.0/comments', wiki_article_comments_path(:article_id => 'Ruby_on_Rails_3.0')
|
|
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
|
|
|
|
get '/pages/Ruby_on_Rails'
|
|
assert_equal 'wiki_pages#show', @response.body
|
|
assert_equal '/pages/Ruby_on_Rails', wiki_page_path(:id => 'Ruby_on_Rails')
|
|
|
|
get '/my_account'
|
|
assert_equal 'wiki_accounts#show', @response.body
|
|
assert_equal '/my_account', wiki_account_path
|
|
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'
|
|
end
|
|
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
|
|
|
|
get '/countries/France/cities'
|
|
assert_equal 'countries#cities', @response.body
|
|
|
|
get '/countries/UK'
|
|
verify_redirect 'http://www.example.com/countries/all'
|
|
|
|
get '/countries/UK/cities'
|
|
verify_redirect 'http://www.example.com/countries/all/cities'
|
|
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
|
|
|
|
get '/italians/sculptors'
|
|
assert_equal 'italians#sculptors', @response.body
|
|
|
|
get '/italians/painters/botticelli'
|
|
assert_equal 'Not Found', @response.body
|
|
|
|
get '/italians/painters/michelangelo'
|
|
assert_equal 'italians#painters', @response.body
|
|
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
|
|
|
|
post '/customers/1/deactivate'
|
|
assert_equal 'customers#deactivate', @response.body
|
|
assert_equal '/customers/1/deactivate', deactivate_customer_path(:id => '1')
|
|
|
|
get '/customers/old'
|
|
assert_equal 'customers#old', @response.body
|
|
assert_equal '/customers/old', stale_customers_path
|
|
|
|
get '/customers/1/invoices/aged/3'
|
|
assert_equal 'invoices#aged', @response.body
|
|
assert_equal '/customers/1/invoices/aged/3', aged_customer_invoices_path(:customer_id => '1', :months => '3')
|
|
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')
|
|
|
|
get '/lists/01234012340123401234fffff/todos/1'
|
|
assert_equal 'todos#show', @response.body
|
|
assert_equal '/lists/01234012340123401234fffff/todos/1', list_todo_path(:list_id => '01234012340123401234fffff', :id => '1')
|
|
|
|
get '/lists/2/todos/1'
|
|
assert_equal 'Not Found', @response.body
|
|
assert_raises(ActionController::UrlGenerationError){ list_todo_path(:list_id => '2', :id => '1') }
|
|
end
|
|
|
|
def test_redirect_argument_error
|
|
routes = Class.new { include ActionDispatch::Routing::Redirection }.new
|
|
assert_raises(ArgumentError) { routes.redirect Object.new }
|
|
end
|
|
|
|
def test_named_route_check
|
|
before, after = nil
|
|
|
|
draw do
|
|
before = has_named_route?(:hello)
|
|
get "/hello", as: :hello, to: "hello#world"
|
|
after = has_named_route?(:hello)
|
|
end
|
|
|
|
assert !before, "expected to not have named route :hello before route definition"
|
|
assert after, "expected to have named route :hello after route definition"
|
|
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
|
|
end
|
|
end
|
|
|
|
assert !respond_to?(:routes_no_collision_path)
|
|
end
|
|
|
|
def test_controller_name_with_leading_slash_raise_error
|
|
assert_raise(ArgumentError) do
|
|
draw { get '/feeds/:service', :to => '/feeds#show' }
|
|
end
|
|
|
|
assert_raise(ArgumentError) do
|
|
draw { get '/feeds/:service', :controller => '/feeds', :action => 'show' }
|
|
end
|
|
|
|
assert_raise(ArgumentError) do
|
|
draw { get '/api/feeds/:service', :to => '/api/feeds#show' }
|
|
end
|
|
|
|
assert_raise(ArgumentError) do
|
|
draw { controller("/feeds") { get '/feeds/:service', :to => :show } }
|
|
end
|
|
|
|
assert_raise(ArgumentError) do
|
|
draw { resources :feeds, :controller => '/feeds' }
|
|
end
|
|
end
|
|
|
|
def test_invalid_route_name_raises_error
|
|
assert_raise(ArgumentError) do
|
|
draw { get '/products', :to => 'products#index', :as => 'products ' }
|
|
end
|
|
|
|
assert_raise(ArgumentError) do
|
|
draw { get '/products', :to => 'products#index', :as => ' products' }
|
|
end
|
|
|
|
assert_raise(ArgumentError) do
|
|
draw { get '/products', :to => 'products#index', :as => 'products!' }
|
|
end
|
|
|
|
assert_raise(ArgumentError) do
|
|
draw { get '/products', :to => 'products#index', :as => 'products index' }
|
|
end
|
|
|
|
assert_raise(ArgumentError) do
|
|
draw { get '/products', :to => 'products#index', :as => '1products' }
|
|
end
|
|
end
|
|
|
|
def test_duplicate_route_name_raises_error
|
|
assert_raise(ArgumentError) do
|
|
draw do
|
|
get '/collision', :to => 'collision#show', :as => 'collision'
|
|
get '/duplicate', :to => 'duplicate#show', :as => 'collision'
|
|
end
|
|
end
|
|
end
|
|
|
|
def test_duplicate_route_name_via_resources_raises_error
|
|
assert_raise(ArgumentError) do
|
|
draw do
|
|
resources :collisions
|
|
get '/collision', :to => 'collision#show', :as => 'collision'
|
|
end
|
|
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]
|
|
|
|
get '/profiles/bob/details'
|
|
assert_equal 'bob', @request.params[:username]
|
|
|
|
get '/profiles/bob/messages/34'
|
|
assert_equal 'bob', @request.params[:profile_username]
|
|
assert_equal '34', @request.params[:id]
|
|
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
|
|
|
|
get '/profiles/bob1/details'
|
|
assert_equal 404, @response.status
|
|
|
|
get '/profiles/bob1/messages/34'
|
|
assert_equal 404, @response.status
|
|
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
|
|
|
|
def test_action_from_path_is_not_frozen
|
|
draw do
|
|
get 'search' => 'search'
|
|
end
|
|
|
|
get '/search'
|
|
assert !@request.params[:action].frozen?
|
|
end
|
|
|
|
def test_multiple_positional_args_with_the_same_name
|
|
draw do
|
|
get '/downloads/:id/:id.tar' => 'downloads#show', as: :download, format: false
|
|
end
|
|
|
|
expected_params = {
|
|
controller: 'downloads',
|
|
action: 'show',
|
|
id: '1'
|
|
}
|
|
|
|
get '/downloads/1/1.tar'
|
|
assert_equal 'downloads#show', @response.body
|
|
assert_equal expected_params, @request.symbolized_path_parameters
|
|
assert_equal '/downloads/1/1.tar', download_path('1')
|
|
assert_equal '/downloads/1/1.tar', download_path('1', '1')
|
|
end
|
|
|
|
def test_absolute_controller_namespace
|
|
draw do
|
|
namespace :foo do
|
|
get '/', to: '/bar#index', as: 'root'
|
|
end
|
|
end
|
|
|
|
get '/foo'
|
|
assert_equal 'bar#index', @response.body
|
|
assert_equal '/foo', foo_root_path
|
|
end
|
|
|
|
def test_trailing_slash
|
|
draw do
|
|
resources :streams
|
|
end
|
|
|
|
get '/streams'
|
|
assert @response.ok?, 'route without trailing slash should work'
|
|
|
|
get '/streams/'
|
|
assert @response.ok?, 'route with trailing slash should work'
|
|
|
|
get '/streams?foobar'
|
|
assert @response.ok?, 'route without trailing slash and with QUERY_STRING should work'
|
|
|
|
get '/streams/?foobar'
|
|
assert @response.ok?, 'route with trailing slash and with QUERY_STRING should work'
|
|
end
|
|
|
|
def test_route_with_dashes_in_path
|
|
draw do
|
|
get '/contact-us', to: 'pages#contact_us'
|
|
end
|
|
|
|
get '/contact-us'
|
|
assert_equal 'pages#contact_us', @response.body
|
|
assert_equal '/contact-us', contact_us_path
|
|
end
|
|
|
|
def test_shorthand_route_with_dashes_in_path
|
|
draw do
|
|
get '/about-us/index'
|
|
end
|
|
|
|
get '/about-us/index'
|
|
assert_equal 'about_us#index', @response.body
|
|
assert_equal '/about-us/index', about_us_index_path
|
|
end
|
|
|
|
def test_resource_routes_with_dashes_in_path
|
|
draw do
|
|
resources :photos, only: [:show] do
|
|
get 'user-favorites', on: :collection
|
|
get 'preview-photo', on: :member
|
|
get 'summary-text'
|
|
end
|
|
end
|
|
|
|
get '/photos/user-favorites'
|
|
assert_equal 'photos#user_favorites', @response.body
|
|
assert_equal '/photos/user-favorites', user_favorites_photos_path
|
|
|
|
get '/photos/1/preview-photo'
|
|
assert_equal 'photos#preview_photo', @response.body
|
|
assert_equal '/photos/1/preview-photo', preview_photo_photo_path('1')
|
|
|
|
get '/photos/1/summary-text'
|
|
assert_equal 'photos#summary_text', @response.body
|
|
assert_equal '/photos/1/summary-text', photo_summary_text_path('1')
|
|
|
|
get '/photos/1'
|
|
assert_equal 'photos#show', @response.body
|
|
assert_equal '/photos/1', photo_path('1')
|
|
end
|
|
|
|
def test_shallow_path_inside_namespace_is_not_added_twice
|
|
draw do
|
|
namespace :admin do
|
|
shallow do
|
|
resources :posts do
|
|
resources :comments
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
get '/admin/posts/1/comments'
|
|
assert_equal 'admin/comments#index', @response.body
|
|
assert_equal '/admin/posts/1/comments', admin_post_comments_path('1')
|
|
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!
|
|
yield
|
|
ensure
|
|
https!(old_https)
|
|
end
|
|
|
|
def verify_redirect(url, status=301)
|
|
assert_equal status, @response.status
|
|
assert_equal url, @response.headers['Location']
|
|
assert_equal expected_redirect_body(url), @response.body
|
|
end
|
|
|
|
def expected_redirect_body(url)
|
|
%(<html><body>You are being <a href="#{ERB::Util.h(url)}">redirected</a>.</body></html>)
|
|
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] ] }
|
|
end
|
|
|
|
def setup
|
|
super
|
|
s = self
|
|
@app = ActionDispatch::Routing::RouteSet.new
|
|
@app.append do
|
|
get '/hello' => s.simple_app('fail')
|
|
get '/goodbye' => s.simple_app('goodbye')
|
|
end
|
|
|
|
@app.draw do
|
|
get '/hello' => s.simple_app('hello')
|
|
end
|
|
end
|
|
|
|
def test_goodbye_should_be_available
|
|
get '/goodbye'
|
|
assert_equal 'goodbye', @response.body
|
|
end
|
|
|
|
def test_hello_should_not_be_overwritten
|
|
get '/hello'
|
|
assert_equal 'hello', @response.body
|
|
end
|
|
|
|
def test_missing_routes_are_still_missing
|
|
get '/random'
|
|
assert_equal 404, @response.status
|
|
end
|
|
end
|
|
|
|
class TestNamespaceWithControllerOption < ActionDispatch::IntegrationTest
|
|
module ::Admin
|
|
class StorageFilesController < ActionController::Base
|
|
def index
|
|
render :text => "admin/storage_files#index"
|
|
end
|
|
end
|
|
end
|
|
|
|
def draw(&block)
|
|
@app = ActionDispatch::Routing::RouteSet.new
|
|
@app.draw(&block)
|
|
end
|
|
|
|
def test_valid_controller_options_inside_namespace
|
|
draw do
|
|
namespace :admin do
|
|
resources :storage_files, :controller => "storage_files"
|
|
end
|
|
end
|
|
|
|
get '/admin/storage_files'
|
|
assert_equal "admin/storage_files#index", @response.body
|
|
end
|
|
|
|
def test_resources_with_valid_namespaced_controller_option
|
|
draw do
|
|
resources :storage_files, :controller => 'admin/storage_files'
|
|
end
|
|
|
|
get 'storage_files'
|
|
assert_equal "admin/storage_files#index", @response.body
|
|
end
|
|
|
|
def test_warn_with_ruby_constant_syntax_controller_option
|
|
e = assert_raise(ArgumentError) do
|
|
draw do
|
|
namespace :admin do
|
|
resources :storage_files, :controller => "StorageFiles"
|
|
end
|
|
end
|
|
end
|
|
|
|
assert_match "'admin/StorageFiles' is not a supported controller name", e.message
|
|
end
|
|
|
|
def test_warn_with_ruby_constant_syntax_namespaced_controller_option
|
|
e = assert_raise(ArgumentError) do
|
|
draw do
|
|
resources :storage_files, :controller => 'Admin::StorageFiles'
|
|
end
|
|
end
|
|
|
|
assert_match "'Admin::StorageFiles' is not a supported controller name", e.message
|
|
end
|
|
end
|
|
|
|
class TestDefaultScope < ActionDispatch::IntegrationTest
|
|
module ::Blog
|
|
class PostsController < ActionController::Base
|
|
def index
|
|
render :text => "blog/posts#index"
|
|
end
|
|
end
|
|
end
|
|
|
|
DefaultScopeRoutes = ActionDispatch::Routing::RouteSet.new
|
|
DefaultScopeRoutes.default_scope = {:module => :blog}
|
|
DefaultScopeRoutes.draw do
|
|
resources :posts
|
|
end
|
|
|
|
def app
|
|
DefaultScopeRoutes
|
|
end
|
|
|
|
include DefaultScopeRoutes.url_helpers
|
|
|
|
def test_default_scope
|
|
get '/posts'
|
|
assert_equal "blog/posts#index", @response.body
|
|
end
|
|
end
|
|
|
|
class TestHttpMethods < ActionDispatch::IntegrationTest
|
|
RFC2616 = %w(OPTIONS GET HEAD POST PUT DELETE TRACE CONNECT)
|
|
RFC2518 = %w(PROPFIND PROPPATCH MKCOL COPY MOVE LOCK UNLOCK)
|
|
RFC3253 = %w(VERSION-CONTROL REPORT CHECKOUT CHECKIN UNCHECKOUT MKWORKSPACE UPDATE LABEL MERGE BASELINE-CONTROL MKACTIVITY)
|
|
RFC3648 = %w(ORDERPATCH)
|
|
RFC3744 = %w(ACL)
|
|
RFC5323 = %w(SEARCH)
|
|
RFC5789 = %w(PATCH)
|
|
|
|
def simple_app(response)
|
|
lambda { |env| [ 200, { 'Content-Type' => 'text/plain' }, [response] ] }
|
|
end
|
|
|
|
setup do
|
|
s = self
|
|
@app = ActionDispatch::Routing::RouteSet.new
|
|
|
|
@app.draw do
|
|
(RFC2616 + RFC2518 + RFC3253 + RFC3648 + RFC3744 + RFC5323 + RFC5789).each do |method|
|
|
match '/' => s.simple_app(method), :via => method.underscore.to_sym
|
|
end
|
|
end
|
|
end
|
|
|
|
(RFC2616 + RFC2518 + RFC3253 + RFC3648 + RFC3744 + RFC5323 + RFC5789).each do |method|
|
|
test "request method #{method.underscore} can be matched" do
|
|
get '/', nil, 'REQUEST_METHOD' => method
|
|
assert_equal method, @response.body
|
|
end
|
|
end
|
|
end
|
|
|
|
class TestUriPathEscaping < ActionDispatch::IntegrationTest
|
|
Routes = ActionDispatch::Routing::RouteSet.new.tap do |app|
|
|
app.draw do
|
|
get '/:segment' => lambda { |env|
|
|
path_params = env['action_dispatch.request.path_parameters']
|
|
[200, { 'Content-Type' => 'text/plain' }, [path_params[:segment]]]
|
|
}, :as => :segment
|
|
|
|
get '/*splat' => lambda { |env|
|
|
path_params = env['action_dispatch.request.path_parameters']
|
|
[200, { 'Content-Type' => 'text/plain' }, [path_params[:splat]]]
|
|
}, :as => :splat
|
|
end
|
|
end
|
|
|
|
include Routes.url_helpers
|
|
def app; Routes end
|
|
|
|
test 'escapes generated path segment' do
|
|
assert_equal '/a%20b/c+d', segment_path(:segment => 'a b/c+d')
|
|
end
|
|
|
|
test 'unescapes recognized path segment' do
|
|
get '/a%20b%2Fc+d'
|
|
assert_equal 'a b/c+d', @response.body
|
|
end
|
|
|
|
test 'escapes generated path splat' do
|
|
assert_equal '/a%20b/c+d', splat_path(:splat => 'a b/c+d')
|
|
end
|
|
|
|
test 'unescapes recognized path splat' do
|
|
get '/a%20b/c+d'
|
|
assert_equal 'a b/c+d', @response.body
|
|
end
|
|
end
|
|
|
|
class TestUnicodePaths < ActionDispatch::IntegrationTest
|
|
Routes = ActionDispatch::Routing::RouteSet.new.tap do |app|
|
|
app.draw do
|
|
get "/ほげ" => lambda { |env|
|
|
[200, { 'Content-Type' => 'text/plain' }, []]
|
|
}, :as => :unicode_path
|
|
end
|
|
end
|
|
|
|
include Routes.url_helpers
|
|
def app; Routes end
|
|
|
|
test 'recognizes unicode path' do
|
|
get "/#{Rack::Utils.escape("ほげ")}"
|
|
assert_equal "200", @response.code
|
|
end
|
|
end
|
|
|
|
class TestMultipleNestedController < ActionDispatch::IntegrationTest
|
|
module ::Foo
|
|
module Bar
|
|
class BazController < ActionController::Base
|
|
def index
|
|
render :inline => "<%= url_for :controller => '/pooh', :action => 'index' %>"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
Routes = ActionDispatch::Routing::RouteSet.new.tap do |app|
|
|
app.draw do
|
|
namespace :foo do
|
|
namespace :bar do
|
|
get "baz" => "baz#index"
|
|
end
|
|
end
|
|
get "pooh" => "pooh#index"
|
|
end
|
|
end
|
|
|
|
include Routes.url_helpers
|
|
def app; Routes end
|
|
|
|
test "controller option which starts with '/' from multiple nested controller" do
|
|
get "/foo/bar/baz"
|
|
assert_equal "/pooh", @response.body
|
|
end
|
|
end
|
|
|
|
class TestTildeAndMinusPaths < ActionDispatch::IntegrationTest
|
|
Routes = ActionDispatch::Routing::RouteSet.new.tap do |app|
|
|
app.draw do
|
|
ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] }
|
|
|
|
get "/~user" => ok
|
|
get "/young-and-fine" => ok
|
|
end
|
|
end
|
|
|
|
include Routes.url_helpers
|
|
def app; Routes end
|
|
|
|
test 'recognizes tilde path' do
|
|
get "/~user"
|
|
assert_equal "200", @response.code
|
|
end
|
|
|
|
test 'recognizes minus path' do
|
|
get "/young-and-fine"
|
|
assert_equal "200", @response.code
|
|
end
|
|
|
|
end
|
|
|
|
class TestRedirectInterpolation < ActionDispatch::IntegrationTest
|
|
Routes = ActionDispatch::Routing::RouteSet.new.tap do |app|
|
|
app.draw do
|
|
ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] }
|
|
|
|
get "/foo/:id" => redirect("/foo/bar/%{id}")
|
|
get "/bar/:id" => redirect(:path => "/foo/bar/%{id}")
|
|
get "/baz/:id" => redirect("/baz?id=%{id}&foo=?&bar=1#id-%{id}")
|
|
get "/foo/bar/:id" => ok
|
|
get "/baz" => ok
|
|
end
|
|
end
|
|
|
|
def app; Routes end
|
|
|
|
test "redirect escapes interpolated parameters with redirect proc" do
|
|
get "/foo/1%3E"
|
|
verify_redirect "http://www.example.com/foo/bar/1%3E"
|
|
end
|
|
|
|
test "redirect escapes interpolated parameters with option proc" do
|
|
get "/bar/1%3E"
|
|
verify_redirect "http://www.example.com/foo/bar/1%3E"
|
|
end
|
|
|
|
test "path redirect escapes interpolated parameters correctly" do
|
|
get "/foo/1%201"
|
|
verify_redirect "http://www.example.com/foo/bar/1%201"
|
|
|
|
get "/baz/1%201"
|
|
verify_redirect "http://www.example.com/baz?id=1+1&foo=?&bar=1#id-1%201"
|
|
end
|
|
|
|
private
|
|
def verify_redirect(url, status=301)
|
|
assert_equal status, @response.status
|
|
assert_equal url, @response.headers['Location']
|
|
assert_equal expected_redirect_body(url), @response.body
|
|
end
|
|
|
|
def expected_redirect_body(url)
|
|
%(<html><body>You are being <a href="#{ERB::Util.h(url)}">redirected</a>.</body></html>)
|
|
end
|
|
end
|
|
|
|
class TestConstraintsAccessingParameters < ActionDispatch::IntegrationTest
|
|
Routes = ActionDispatch::Routing::RouteSet.new.tap do |app|
|
|
app.draw do
|
|
ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] }
|
|
|
|
get "/:foo" => ok, :constraints => lambda { |r| r.params[:foo] == 'foo' }
|
|
get "/:bar" => ok
|
|
end
|
|
end
|
|
|
|
def app; Routes end
|
|
|
|
test "parameters are reset between constraint checks" do
|
|
get "/bar"
|
|
assert_equal nil, @request.params[:foo]
|
|
assert_equal "bar", @request.params[:bar]
|
|
end
|
|
end
|
|
|
|
class TestGlobRoutingMapper < ActionDispatch::IntegrationTest
|
|
Routes = ActionDispatch::Routing::RouteSet.new.tap do |app|
|
|
app.draw do
|
|
ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] }
|
|
|
|
get "/*id" => redirect("/not_cars"), :constraints => {id: /dummy/}
|
|
get "/cars" => ok
|
|
end
|
|
end
|
|
|
|
#include Routes.url_helpers
|
|
def app; Routes end
|
|
|
|
def test_glob_constraint
|
|
get "/dummy"
|
|
assert_equal "301", @response.code
|
|
assert_equal "/not_cars", @response.header['Location'].match('/[^/]+$')[0]
|
|
end
|
|
|
|
def test_glob_constraint_skip_route
|
|
get "/cars"
|
|
assert_equal "200", @response.code
|
|
end
|
|
def test_glob_constraint_skip_all
|
|
get "/missing"
|
|
assert_equal "404", @response.code
|
|
end
|
|
end
|
|
|
|
class TestOptimizedNamedRoutes < ActionDispatch::IntegrationTest
|
|
Routes = ActionDispatch::Routing::RouteSet.new.tap do |app|
|
|
app.draw do
|
|
ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] }
|
|
get '/foo' => ok, as: :foo
|
|
get '/post(/:action(/:id))' => ok, as: :posts
|
|
get '/:foo/:foo_type/bars/:id' => ok, as: :bar
|
|
get '/projects/:id.:format' => ok, as: :project
|
|
end
|
|
end
|
|
|
|
include Routes.url_helpers
|
|
def app; Routes end
|
|
|
|
test 'enabled when not mounted and default_url_options is empty' do
|
|
assert Routes.url_helpers.optimize_routes_generation?
|
|
end
|
|
|
|
test 'named route called as singleton method' do
|
|
assert_equal '/foo', Routes.url_helpers.foo_path
|
|
end
|
|
|
|
test 'named route called on included module' do
|
|
assert_equal '/foo', foo_path
|
|
end
|
|
|
|
test 'nested optional segments are removed' do
|
|
assert_equal '/post', Routes.url_helpers.posts_path
|
|
assert_equal '/post', posts_path
|
|
end
|
|
|
|
test 'segments with same prefix are replaced correctly' do
|
|
assert_equal '/foo/baz/bars/1', Routes.url_helpers.bar_path('foo', 'baz', '1')
|
|
assert_equal '/foo/baz/bars/1', bar_path('foo', 'baz', '1')
|
|
end
|
|
|
|
test 'segments separated with a period are replaced correctly' do
|
|
assert_equal '/projects/1.json', Routes.url_helpers.project_path(1, :json)
|
|
assert_equal '/projects/1.json', project_path(1, :json)
|
|
end
|
|
end
|
|
|
|
class TestNamedRouteUrlHelpers < ActionDispatch::IntegrationTest
|
|
class CategoriesController < ActionController::Base
|
|
def show
|
|
render :text => "categories#show"
|
|
end
|
|
end
|
|
|
|
class ProductsController < ActionController::Base
|
|
def show
|
|
render :text => "products#show"
|
|
end
|
|
end
|
|
|
|
Routes = ActionDispatch::Routing::RouteSet.new.tap do |app|
|
|
app.draw do
|
|
scope :module => "test_named_route_url_helpers" do
|
|
get "/categories/:id" => 'categories#show', :as => :category
|
|
get "/products/:id" => 'products#show', :as => :product
|
|
end
|
|
end
|
|
end
|
|
|
|
def app; Routes end
|
|
|
|
include Routes.url_helpers
|
|
|
|
test "url helpers do not ignore nil parameters when using non-optimized routes" do
|
|
Routes.stubs(:optimize_routes_generation?).returns(false)
|
|
|
|
get "/categories/1"
|
|
assert_response :success
|
|
assert_raises(ActionController::UrlGenerationError) { product_path(nil) }
|
|
end
|
|
end
|
|
|
|
class TestUrlConstraints < ActionDispatch::IntegrationTest
|
|
Routes = ActionDispatch::Routing::RouteSet.new.tap do |app|
|
|
app.draw do
|
|
ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] }
|
|
|
|
constraints :subdomain => 'admin' do
|
|
get '/' => ok, :as => :admin_root
|
|
end
|
|
|
|
scope :constraints => { :protocol => 'https://' } do
|
|
get '/' => ok, :as => :secure_root
|
|
end
|
|
|
|
get '/' => ok, :as => :alternate_root, :constraints => { :port => 8080 }
|
|
|
|
get '/search' => ok, :constraints => { :subdomain => false }
|
|
|
|
get '/logs' => ok, :constraints => { :subdomain => true }
|
|
end
|
|
end
|
|
|
|
include Routes.url_helpers
|
|
def app; Routes end
|
|
|
|
test "constraints are copied to defaults when using constraints method" do
|
|
assert_equal 'http://admin.example.com/', admin_root_url
|
|
|
|
get 'http://admin.example.com/'
|
|
assert_response :success
|
|
end
|
|
|
|
test "constraints are copied to defaults when using scope constraints hash" do
|
|
assert_equal 'https://www.example.com/', secure_root_url
|
|
|
|
get 'https://www.example.com/'
|
|
assert_response :success
|
|
end
|
|
|
|
test "constraints are copied to defaults when using route constraints hash" do
|
|
assert_equal 'http://www.example.com:8080/', alternate_root_url
|
|
|
|
get 'http://www.example.com:8080/'
|
|
assert_response :success
|
|
end
|
|
|
|
test "false constraint expressions check for absence of values" do
|
|
get 'http://example.com/search'
|
|
assert_response :success
|
|
assert_equal 'http://example.com/search', search_url
|
|
|
|
get 'http://api.example.com/search'
|
|
assert_response :not_found
|
|
end
|
|
|
|
test "true constraint expressions check for presence of values" do
|
|
get 'http://api.example.com/logs'
|
|
assert_response :success
|
|
assert_equal 'http://api.example.com/logs', logs_url
|
|
|
|
get 'http://example.com/logs'
|
|
assert_response :not_found
|
|
end
|
|
end
|
|
|
|
class TestInvalidUrls < ActionDispatch::IntegrationTest
|
|
class FooController < ActionController::Base
|
|
def show
|
|
render :text => "foo#show"
|
|
end
|
|
end
|
|
|
|
test "invalid UTF-8 encoding returns a 400 Bad Request" do
|
|
with_routing do |set|
|
|
set.draw do
|
|
get "/bar/:id", :to => redirect("/foo/show/%{id}")
|
|
get "/foo/show(/:id)", :to => "test_invalid_urls/foo#show"
|
|
get "/foo(/:action(/:id))", :to => "test_invalid_urls/foo"
|
|
get "/:controller(/:action(/:id))"
|
|
end
|
|
|
|
get "/%E2%EF%BF%BD%A6"
|
|
assert_response :bad_request
|
|
|
|
get "/foo/%E2%EF%BF%BD%A6"
|
|
assert_response :bad_request
|
|
|
|
get "/foo/show/%E2%EF%BF%BD%A6"
|
|
assert_response :bad_request
|
|
|
|
get "/bar/%E2%EF%BF%BD%A6"
|
|
assert_response :bad_request
|
|
end
|
|
end
|
|
end
|
|
|
|
class TestOptionalRootSegments < ActionDispatch::IntegrationTest
|
|
stub_controllers do |routes|
|
|
Routes = routes
|
|
Routes.draw do
|
|
get '/(page/:page)', :to => 'pages#index', :as => :root
|
|
end
|
|
end
|
|
|
|
def app
|
|
Routes
|
|
end
|
|
|
|
include Routes.url_helpers
|
|
|
|
def test_optional_root_segments
|
|
get '/'
|
|
assert_equal 'pages#index', @response.body
|
|
assert_equal '/', root_path
|
|
|
|
get '/page/1'
|
|
assert_equal 'pages#index', @response.body
|
|
assert_equal '1', @request.params[:page]
|
|
assert_equal '/page/1', root_path('1')
|
|
assert_equal '/page/1', root_path(:page => '1')
|
|
end
|
|
end
|
|
|
|
class TestPortConstraints < ActionDispatch::IntegrationTest
|
|
Routes = ActionDispatch::Routing::RouteSet.new.tap do |app|
|
|
app.draw do
|
|
ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] }
|
|
|
|
get '/integer', to: ok, constraints: { :port => 8080 }
|
|
get '/string', to: ok, constraints: { :port => '8080' }
|
|
get '/array', to: ok, constraints: { :port => [8080] }
|
|
get '/regexp', to: ok, constraints: { :port => /8080/ }
|
|
end
|
|
end
|
|
|
|
include Routes.url_helpers
|
|
def app; Routes end
|
|
|
|
def test_integer_port_constraints
|
|
get 'http://www.example.com/integer'
|
|
assert_response :not_found
|
|
|
|
get 'http://www.example.com:8080/integer'
|
|
assert_response :success
|
|
end
|
|
|
|
def test_string_port_constraints
|
|
get 'http://www.example.com/string'
|
|
assert_response :not_found
|
|
|
|
get 'http://www.example.com:8080/string'
|
|
assert_response :success
|
|
end
|
|
|
|
def test_array_port_constraints
|
|
get 'http://www.example.com/array'
|
|
assert_response :not_found
|
|
|
|
get 'http://www.example.com:8080/array'
|
|
assert_response :success
|
|
end
|
|
|
|
def test_regexp_port_constraints
|
|
get 'http://www.example.com/regexp'
|
|
assert_response :not_found
|
|
|
|
get 'http://www.example.com:8080/regexp'
|
|
assert_response :success
|
|
end
|
|
end
|
|
|
|
class TestFormatConstraints < ActionDispatch::IntegrationTest
|
|
Routes = ActionDispatch::Routing::RouteSet.new.tap do |app|
|
|
app.draw do
|
|
ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] }
|
|
|
|
get '/string', to: ok, constraints: { format: 'json' }
|
|
get '/regexp', to: ok, constraints: { format: /json/ }
|
|
get '/json_only', to: ok, format: true, constraints: { format: /json/ }
|
|
get '/xml_only', to: ok, format: 'xml'
|
|
end
|
|
end
|
|
|
|
include Routes.url_helpers
|
|
def app; Routes end
|
|
|
|
def test_string_format_constraints
|
|
get 'http://www.example.com/string'
|
|
assert_response :success
|
|
|
|
get 'http://www.example.com/string.json'
|
|
assert_response :success
|
|
|
|
get 'http://www.example.com/string.html'
|
|
assert_response :not_found
|
|
end
|
|
|
|
def test_regexp_format_constraints
|
|
get 'http://www.example.com/regexp'
|
|
assert_response :success
|
|
|
|
get 'http://www.example.com/regexp.json'
|
|
assert_response :success
|
|
|
|
get 'http://www.example.com/regexp.html'
|
|
assert_response :not_found
|
|
end
|
|
|
|
def test_enforce_with_format_true_with_constraint
|
|
get 'http://www.example.com/json_only.json'
|
|
assert_response :success
|
|
|
|
get 'http://www.example.com/json_only.html'
|
|
assert_response :not_found
|
|
|
|
get 'http://www.example.com/json_only'
|
|
assert_response :not_found
|
|
end
|
|
|
|
def test_enforce_with_string
|
|
get 'http://www.example.com/xml_only.xml'
|
|
assert_response :success
|
|
|
|
get 'http://www.example.com/xml_only'
|
|
assert_response :success
|
|
|
|
get 'http://www.example.com/xml_only.json'
|
|
assert_response :not_found
|
|
end
|
|
end
|
|
|
|
class TestRouteDefaults < ActionDispatch::IntegrationTest
|
|
stub_controllers do |routes|
|
|
Routes = routes
|
|
Routes.draw do
|
|
resources :posts, bucket_type: 'post'
|
|
resources :projects, defaults: { bucket_type: 'project' }
|
|
end
|
|
end
|
|
|
|
def app
|
|
Routes
|
|
end
|
|
|
|
include Routes.url_helpers
|
|
|
|
def test_route_options_are_required_for_url_for
|
|
assert_raises(ActionController::UrlGenerationError) do
|
|
assert_equal '/posts/1', url_for(controller: 'posts', action: 'show', id: 1, only_path: true)
|
|
end
|
|
|
|
assert_equal '/posts/1', url_for(controller: 'posts', action: 'show', id: 1, bucket_type: 'post', only_path: true)
|
|
end
|
|
|
|
def test_route_defaults_are_not_required_for_url_for
|
|
assert_equal '/projects/1', url_for(controller: 'projects', action: 'show', id: 1, only_path: true)
|
|
end
|
|
end
|
|
|
|
class TestRackAppRouteGeneration < ActionDispatch::IntegrationTest
|
|
stub_controllers do |routes|
|
|
Routes = routes
|
|
Routes.draw do
|
|
rack_app = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] }
|
|
mount rack_app, at: '/account', as: 'account'
|
|
mount rack_app, at: '/:locale/account', as: 'localized_account'
|
|
end
|
|
end
|
|
|
|
def app
|
|
Routes
|
|
end
|
|
|
|
include Routes.url_helpers
|
|
|
|
def test_mounted_application_doesnt_match_unnamed_route
|
|
assert_raise(ActionController::UrlGenerationError) do
|
|
assert_equal '/account?controller=products', url_for(controller: 'products', action: 'index', only_path: true)
|
|
end
|
|
|
|
assert_raise(ActionController::UrlGenerationError) do
|
|
assert_equal '/de/account?controller=products', url_for(controller: 'products', action: 'index', :locale => 'de', only_path: true)
|
|
end
|
|
end
|
|
end
|
|
|
|
class TestRedirectRouteGeneration < ActionDispatch::IntegrationTest
|
|
stub_controllers do |routes|
|
|
Routes = routes
|
|
Routes.draw do
|
|
get '/account', to: redirect('/myaccount'), as: 'account'
|
|
get '/:locale/account', to: redirect('/%{locale}/myaccount'), as: 'localized_account'
|
|
end
|
|
end
|
|
|
|
def app
|
|
Routes
|
|
end
|
|
|
|
include Routes.url_helpers
|
|
|
|
def test_redirect_doesnt_match_unnamed_route
|
|
assert_raise(ActionController::UrlGenerationError) do
|
|
assert_equal '/account?controller=products', url_for(controller: 'products', action: 'index', only_path: true)
|
|
end
|
|
|
|
assert_raise(ActionController::UrlGenerationError) do
|
|
assert_equal '/de/account?controller=products', url_for(controller: 'products', action: 'index', :locale => 'de', only_path: true)
|
|
end
|
|
end
|
|
end
|
|
|
|
class TestUrlGenerationErrors < ActionDispatch::IntegrationTest
|
|
Routes = ActionDispatch::Routing::RouteSet.new.tap do |app|
|
|
app.draw do
|
|
get "/products/:id" => 'products#show', :as => :product
|
|
end
|
|
end
|
|
|
|
def app; Routes end
|
|
|
|
include Routes.url_helpers
|
|
|
|
test "url helpers raise a helpful error message whem generation fails" do
|
|
url, missing = { action: 'show', controller: 'products', id: nil }, [:id]
|
|
message = "No route matches #{url.inspect} missing required keys: #{missing.inspect}"
|
|
|
|
# Optimized url helper
|
|
error = assert_raises(ActionController::UrlGenerationError){ product_path(nil) }
|
|
assert_equal message, error.message
|
|
|
|
# Non-optimized url helper
|
|
error = assert_raises(ActionController::UrlGenerationError, message){ product_path(id: nil) }
|
|
assert_equal message, error.message
|
|
end
|
|
end
|