diff options
Diffstat (limited to 'actionpack/test/dispatch/routing/inspector_test.rb')
-rw-r--r-- | actionpack/test/dispatch/routing/inspector_test.rb | 495 |
1 files changed, 495 insertions, 0 deletions
diff --git a/actionpack/test/dispatch/routing/inspector_test.rb b/actionpack/test/dispatch/routing/inspector_test.rb new file mode 100644 index 0000000000..fe1f1995d8 --- /dev/null +++ b/actionpack/test/dispatch/routing/inspector_test.rb @@ -0,0 +1,495 @@ +# frozen_string_literal: true + +require "abstract_unit" +require "rails/engine" +require "action_dispatch/routing/inspector" +require "io/console/size" + +class MountedRackApp + def self.call(env) + end +end + +class Rails::DummyController +end + +module ActionDispatch + module Routing + class RoutesInspectorTest < ActiveSupport::TestCase + setup do + @set = ActionDispatch::Routing::RouteSet.new + end + + def test_displaying_routes_for_engines + engine = Class.new(Rails::Engine) do + def self.inspect + "Blog::Engine" + end + end + engine.routes.draw do + get "/cart", to: "cart#show" + end + + output = draw do + get "/custom/assets", to: "custom_assets#show" + mount engine => "/blog", :as => "blog" + end + + assert_equal [ + " Prefix Verb URI Pattern Controller#Action", + "custom_assets GET /custom/assets(.:format) custom_assets#show", + " blog /blog Blog::Engine", + "", + "Routes for Blog::Engine:", + " cart GET /cart(.:format) cart#show" + ], output + end + + def test_displaying_routes_for_engines_without_routes + engine = Class.new(Rails::Engine) do + def self.inspect + "Blog::Engine" + end + end + engine.routes.draw do + end + + output = draw do + mount engine => "/blog", as: "blog" + end + + assert_equal [ + "Prefix Verb URI Pattern Controller#Action", + " blog /blog Blog::Engine", + "", + "Routes for Blog::Engine:" + ], output + end + + def test_cart_inspect + output = draw do + get "/cart", to: "cart#show" + end + + assert_equal [ + "Prefix Verb URI Pattern Controller#Action", + " cart GET /cart(.:format) cart#show" + ], output + end + + def test_articles_inspect_with_multiple_verbs + output = draw do + match "articles/:id", to: "articles#update", via: [:put, :patch] + end + + assert_equal [ + "Prefix Verb URI Pattern Controller#Action", + " PUT|PATCH /articles/:id(.:format) articles#update" + ], output + end + + def test_inspect_shows_custom_assets + output = draw do + get "/custom/assets", to: "custom_assets#show" + end + + assert_equal [ + " Prefix Verb URI Pattern Controller#Action", + "custom_assets GET /custom/assets(.:format) custom_assets#show" + ], output + end + + def test_inspect_routes_shows_resources_route + output = draw do + resources :articles + end + + assert_equal [ + " Prefix Verb URI Pattern Controller#Action", + " articles GET /articles(.:format) articles#index", + " POST /articles(.:format) articles#create", + " new_article GET /articles/new(.:format) articles#new", + "edit_article GET /articles/:id/edit(.:format) articles#edit", + " article GET /articles/:id(.:format) articles#show", + " PATCH /articles/:id(.:format) articles#update", + " PUT /articles/:id(.:format) articles#update", + " DELETE /articles/:id(.:format) articles#destroy" + ], output + end + + def test_inspect_routes_shows_root_route + output = draw do + root to: "pages#main" + end + + assert_equal [ + "Prefix Verb URI Pattern Controller#Action", + " root GET / pages#main" + ], output + end + + def test_inspect_routes_shows_dynamic_action_route + output = draw do + ActiveSupport::Deprecation.silence do + get "api/:action" => "api" + end + end + + assert_equal [ + "Prefix Verb URI Pattern Controller#Action", + " GET /api/:action(.:format) api#:action" + ], output + end + + def test_inspect_routes_shows_controller_and_action_only_route + output = draw do + ActiveSupport::Deprecation.silence do + get ":controller/:action" + end + end + + assert_equal [ + "Prefix Verb URI Pattern Controller#Action", + " GET /:controller/:action(.:format) :controller#:action" + ], output + end + + def test_inspect_routes_shows_controller_and_action_route_with_constraints + output = draw do + ActiveSupport::Deprecation.silence do + get ":controller(/:action(/:id))", id: /\d+/ + end + end + + assert_equal [ + "Prefix Verb URI Pattern Controller#Action", + " GET /:controller(/:action(/:id))(.:format) :controller#:action {:id=>/\\d+/}" + ], output + end + + def test_rails_routes_shows_route_with_defaults + output = draw do + get "photos/:id" => "photos#show", :defaults => { format: "jpg" } + end + + assert_equal [ + "Prefix Verb URI Pattern Controller#Action", + ' GET /photos/:id(.:format) photos#show {:format=>"jpg"}' + ], output + end + + def test_rails_routes_shows_route_with_constraints + output = draw do + get "photos/:id" => "photos#show", :id => /[A-Z]\d{5}/ + end + + assert_equal [ + "Prefix Verb URI Pattern Controller#Action", + " GET /photos/:id(.:format) photos#show {:id=>/[A-Z]\\d{5}/}" + ], output + end + + def test_rails_routes_shows_routes_with_dashes + output = draw do + get "about-us" => "pages#about_us" + get "our-work/latest" + + resources :photos, only: [:show] do + get "user-favorites", on: :collection + get "preview-photo", on: :member + get "summary-text" + end + end + + assert_equal [ + " Prefix Verb URI Pattern Controller#Action", + " about_us GET /about-us(.:format) pages#about_us", + " our_work_latest GET /our-work/latest(.:format) our_work#latest", + "user_favorites_photos GET /photos/user-favorites(.:format) photos#user_favorites", + " preview_photo_photo GET /photos/:id/preview-photo(.:format) photos#preview_photo", + " photo_summary_text GET /photos/:photo_id/summary-text(.:format) photos#summary_text", + " photo GET /photos/:id(.:format) photos#show" + ], output + end + + def test_rails_routes_shows_route_with_rack_app + output = draw do + get "foo/:id" => MountedRackApp, :id => /[A-Z]\d{5}/ + end + + assert_equal [ + "Prefix Verb URI Pattern Controller#Action", + " GET /foo/:id(.:format) MountedRackApp {:id=>/[A-Z]\\d{5}/}" + ], output + end + + def test_rails_routes_shows_named_route_with_mounted_rack_app + output = draw do + mount MountedRackApp => "/foo" + end + + assert_equal [ + " Prefix Verb URI Pattern Controller#Action", + "mounted_rack_app /foo MountedRackApp" + ], output + end + + def test_rails_routes_shows_overridden_named_route_with_mounted_rack_app_with_name + output = draw do + mount MountedRackApp => "/foo", as: "blog" + end + + assert_equal [ + "Prefix Verb URI Pattern Controller#Action", + " blog /foo MountedRackApp" + ], output + end + + def test_rails_routes_shows_route_with_rack_app_nested_with_dynamic_constraints + constraint = Class.new do + def inspect + "( my custom constraint )" + end + end + + output = draw do + scope constraint: constraint.new do + mount MountedRackApp => "/foo" + end + end + + assert_equal [ + " Prefix Verb URI Pattern Controller#Action", + "mounted_rack_app /foo MountedRackApp {:constraint=>( my custom constraint )}" + ], output + end + + def test_rails_routes_dont_show_app_mounted_in_assets_prefix + output = draw do + get "/sprockets" => MountedRackApp + end + assert_no_match(/MountedRackApp/, output.first) + assert_no_match(/\/sprockets/, output.first) + end + + def test_rails_routes_shows_route_defined_in_under_assets_prefix + output = draw do + scope "/sprockets" do + get "/foo" => "foo#bar" + end + end + assert_equal [ + "Prefix Verb URI Pattern Controller#Action", + " foo GET /sprockets/foo(.:format) foo#bar" + ], output + end + + def test_redirect + output = draw do + get "/foo" => redirect("/foo/bar"), :constraints => { subdomain: "admin" } + get "/bar" => redirect(path: "/foo/bar", status: 307) + get "/foobar" => redirect { "/foo/bar" } + end + + assert_equal [ + "Prefix Verb URI Pattern Controller#Action", + " foo GET /foo(.:format) redirect(301, /foo/bar) {:subdomain=>\"admin\"}", + " bar GET /bar(.:format) redirect(307, path: /foo/bar)", + "foobar GET /foobar(.:format) redirect(301)" + ], output + end + + def test_routes_can_be_filtered + output = draw(grep: "posts") do + resources :articles + resources :posts + end + + assert_equal [" Prefix Verb URI Pattern Controller#Action", + " posts GET /posts(.:format) posts#index", + " POST /posts(.:format) posts#create", + " new_post GET /posts/new(.:format) posts#new", + "edit_post GET /posts/:id/edit(.:format) posts#edit", + " post GET /posts/:id(.:format) posts#show", + " PATCH /posts/:id(.:format) posts#update", + " PUT /posts/:id(.:format) posts#update", + " DELETE /posts/:id(.:format) posts#destroy"], output + end + + def test_routes_when_expanded + previous_console_winsize = IO.console.winsize + IO.console.winsize = [0, 23] + + engine = Class.new(Rails::Engine) do + def self.inspect + "Blog::Engine" + end + end + engine.routes.draw do + get "/cart", to: "cart#show" + end + + output = draw(formatter: ActionDispatch::Routing::ConsoleFormatter::Expanded.new) do + get "/custom/assets", to: "custom_assets#show" + get "/custom/furnitures", to: "custom_furnitures#show" + mount engine => "/blog", :as => "blog" + end + + assert_equal ["--[ Route 1 ]----------", + "Prefix | custom_assets", + "Verb | GET", + "URI | /custom/assets(.:format)", + "Controller#Action | custom_assets#show", + "--[ Route 2 ]----------", + "Prefix | custom_furnitures", + "Verb | GET", + "URI | /custom/furnitures(.:format)", + "Controller#Action | custom_furnitures#show", + "--[ Route 3 ]----------", + "Prefix | blog", + "Verb | ", + "URI | /blog", + "Controller#Action | Blog::Engine", + "", + "[ Routes for Blog::Engine ]", + "--[ Route 1 ]----------", + "Prefix | cart", + "Verb | GET", + "URI | /cart(.:format)", + "Controller#Action | cart#show"], output + ensure + IO.console.winsize = previous_console_winsize + end + + def test_no_routes_matched_filter_when_expanded + output = draw(grep: "rails/dummy", formatter: ActionDispatch::Routing::ConsoleFormatter::Expanded.new) do + get "photos/:id" => "photos#show", :id => /[A-Z]\d{5}/ + end + + assert_equal [ + "No routes were found for this grep pattern.", + "For more information about routes, see the Rails guide: https://guides.rubyonrails.org/routing.html." + ], output + end + + def test_not_routes_when_expanded + output = draw(grep: "rails/dummy", formatter: ActionDispatch::Routing::ConsoleFormatter::Expanded.new) { } + + assert_equal [ + "You don't have any routes defined!", + "", + "Please add some routes in config/routes.rb.", + "", + "For more information about routes, see the Rails guide: https://guides.rubyonrails.org/routing.html." + ], output + end + + def test_routes_can_be_filtered_with_namespaced_controllers + output = draw(grep: "admin/posts") do + resources :articles + namespace :admin do + resources :posts + end + end + + assert_equal [" Prefix Verb URI Pattern Controller#Action", + " admin_posts GET /admin/posts(.:format) admin/posts#index", + " POST /admin/posts(.:format) admin/posts#create", + " new_admin_post GET /admin/posts/new(.:format) admin/posts#new", + "edit_admin_post GET /admin/posts/:id/edit(.:format) admin/posts#edit", + " admin_post GET /admin/posts/:id(.:format) admin/posts#show", + " PATCH /admin/posts/:id(.:format) admin/posts#update", + " PUT /admin/posts/:id(.:format) admin/posts#update", + " DELETE /admin/posts/:id(.:format) admin/posts#destroy"], output + end + + def test_regression_route_with_controller_regexp + output = draw do + ActiveSupport::Deprecation.silence do + get ":controller(/:action)", controller: /api\/[^\/]+/, format: false + end + end + + assert_equal ["Prefix Verb URI Pattern Controller#Action", + " GET /:controller(/:action) :controller#:action"], output + end + + def test_inspect_routes_shows_resources_route_when_assets_disabled + @set = ActionDispatch::Routing::RouteSet.new + + output = draw do + get "/cart", to: "cart#show" + end + + assert_equal [ + "Prefix Verb URI Pattern Controller#Action", + " cart GET /cart(.:format) cart#show" + ], output + end + + def test_routes_with_undefined_filter + output = draw(controller: "Rails::MissingController") do + get "photos/:id" => "photos#show", :id => /[A-Z]\d{5}/ + end + + assert_equal [ + "No routes were found for this controller.", + "For more information about routes, see the Rails guide: https://guides.rubyonrails.org/routing.html." + ], output + end + + def test_no_routes_matched_filter + output = draw(grep: "rails/dummy") do + get "photos/:id" => "photos#show", :id => /[A-Z]\d{5}/ + end + + assert_equal [ + "No routes were found for this grep pattern.", + "For more information about routes, see the Rails guide: https://guides.rubyonrails.org/routing.html." + ], output + end + + def test_no_routes_were_defined + output = draw(grep: "Rails::DummyController") { } + + assert_equal [ + "You don't have any routes defined!", + "", + "Please add some routes in config/routes.rb.", + "", + "For more information about routes, see the Rails guide: https://guides.rubyonrails.org/routing.html." + ], output + end + + def test_displaying_routes_for_internal_engines + engine = Class.new(Rails::Engine) do + def self.inspect + "Blog::Engine" + end + end + engine.routes.draw do + get "/cart", to: "cart#show" + post "/cart", to: "cart#create" + patch "/cart", to: "cart#update" + end + + output = draw do + get "/custom/assets", to: "custom_assets#show" + mount engine => "/blog", as: "blog", internal: true + end + + assert_equal [ + " Prefix Verb URI Pattern Controller#Action", + "custom_assets GET /custom/assets(.:format) custom_assets#show", + ], output + end + + private + def draw(formatter: ActionDispatch::Routing::ConsoleFormatter::Sheet.new, **options, &block) + @set.draw(&block) + inspector = ActionDispatch::Routing::RoutesInspector.new(@set.routes) + inspector.format(formatter, options).split("\n") + end + end + end +end |