module ActionDispatch::Assertions::RoutingAssertions

def assert_generates(expected_path, options, defaults = {}, extras = {}, message = nil)

assert_generates "changesets/12", { controller: 'scm', action: 'show_diff', revision: "12" }
# Asserts that the generated route gives us our custom route

assert_generates "/items/list/1", { controller: "items", action: "list", id: "1" }
# Tests the generation of a route with a parameter

assert_generates "/items/list", controller: "items", action: "list"
# Tests that the list action is properly routed

assert_generates "/items", controller: "items", action: "index"
# Asserts that the default action is generated for a route with no action

The +defaults+ parameter is unused.

a query string. The +message+ parameter allows you to specify a custom error message for assertion failures.
The +extras+ parameter is used to tell the request the names and values of additional request parameters that would be in
Asserts that the provided options can be used to generate the provided path. This is the inverse of +assert_recognizes+.
def assert_generates(expected_path, options, defaults = {}, extras = {}, message = nil)
  if expected_path.include?("://")
    fail_on(URI::InvalidURIError, message) do
      uri = URI.parse(expected_path)
      expected_path = uri.path.to_s.empty? ? "/" : uri.path
    end
  else
    expected_path = "/#{expected_path}" unless expected_path.start_with?("/")
  end
  options = options.clone
  generated_path, query_string_keys = @routes.generate_extras(options, defaults)
  found_extras = options.reject { |k, _| ! query_string_keys.include? k }
  msg = message || sprintf("found extras <%s>, not <%s>", found_extras, extras)
  assert_equal(extras, found_extras, msg)
  msg = message || sprintf("The generated path <%s> did not match <%s>", generated_path,
      expected_path)
  assert_equal(expected_path, generated_path, msg)
end

def assert_recognizes(expected_options, path, extras = {}, msg = nil)

assert_recognizes({controller: 'items', action: 'show', id: '1'}, 'view/item1')
# Test a custom route

assert_recognizes({controller: 'items', action: 'destroy', id: '1'}, 'items/destroy/1')
# Test an action with a parameter

assert_recognizes({controller: 'items', action: 'list'}, 'items/list')
# Test a specific action

assert_recognizes({controller: 'items', action: 'index'}, 'items')
# Check the default route (i.e., the index action)

The +message+ parameter allows you to pass in an error message that is displayed upon failure.

assert_recognizes({controller: 'items', action: 'list', id: '1', view: 'print'}, 'items/list/1', { view: "print" })
# Asserts that a path of '/items/list/1?view=print' returns the correct options

argument because appending the query string on the path directly will not work. For example:
to assert that values in the query string will end up in the params hash correctly. To test query strings you must use the extras
You can also pass in +extras+ with a hash containing URL parameters that would normally be in the query string. This can be used

assert_recognizes({controller: 'items', action: 'create'}, {path: 'items', method: :post})
# Asserts that POSTing to /items will call the create action on ItemsController

and a +:method+ containing the required HTTP verb.
requiring a specific HTTP method. The hash should contain a +:path+ with the incoming request path
Pass a hash in the second argument (+path+) to specify the request method. This is useful for routes

match +path+. Basically, it asserts that \Rails recognizes the route given by +expected_options+.
Asserts that the routing of the given +path+ was handled correctly and that the parsed options (given in the +expected_options+ hash)
def assert_recognizes(expected_options, path, extras = {}, msg = nil)
  if path.is_a?(Hash) && path[:method].to_s == "all"
    [:get, :post, :put, :delete].each do |method|
      assert_recognizes(expected_options, path.merge(method: method), extras, msg)
    end
  else
    request = recognized_request_for(path, extras, msg)
    expected_options = expected_options.clone
    expected_options.stringify_keys!
    msg = message(msg, "") {
      sprintf("The recognized options <%s> did not match <%s>, difference:",
              request.path_parameters, expected_options)
    }
    assert_equal(expected_options, request.path_parameters, msg)
  end
end

def assert_routing(path, options, defaults = {}, extras = {}, message = nil)

assert_routing({ method: 'put', path: '/product/321' }, { controller: "product", action: "update", id: "321" })
# Tests a route with an HTTP method

assert_routing 'controller/action/9', {id: "9", item: "square"}, {controller: "controller", action: "action"}, {}, {item: "square"}
# Tests a route, providing a defaults hash

assert_routing '/store', { controller: 'store', action: 'index' }, {}, {}, 'Route for store index not generated properly'
# Asserts a basic route (controller + default action), with an error message if it fails

assert_routing '/entries/show/23', controller: 'entries', action: 'show', id: 23
# Test a route generated with a specific controller, action, and parameter (id)

assert_routing '/home', controller: 'home', action: 'index'
# Asserts a basic route: a controller with the default action (index)

+message+ parameter allows you to specify a custom error message to display upon failure.
The +extras+ hash allows you to specify options that would normally be provided as a query string to the action. The

and +assert_generates+ into one step.
options and then that options generates path. This essentially combines +assert_recognizes+
Asserts that path and options match both ways; in other words, it verifies that path generates
def assert_routing(path, options, defaults = {}, extras = {}, message = nil)
  assert_recognizes(options, path, extras, message)
  controller, default_controller = options[:controller], defaults[:controller]
  if controller && controller.include?(?/) && default_controller && default_controller.include?(?/)
    options[:controller] = "/#{controller}"
  end
  generate_options = options.dup.delete_if { |k, _| defaults.key?(k) }
  assert_generates(path.is_a?(Hash) ? path[:path] : path, generate_options, defaults, extras, message)
end

def create_routes

def create_routes
  @routes = ActionDispatch::Routing::RouteSet.new
  if defined?(@controller) && @controller
    @controller = @controller.clone
    _routes = @routes
    @controller.singleton_class.include(_routes.url_helpers)
    if @controller.respond_to? :view_context_class
      view_context_class = Class.new(@controller.view_context_class) do
        include _routes.url_helpers
      end
      custom_view_context = Module.new {
        define_method(:view_context_class) do
          view_context_class
        end
      }
      @controller.extend(custom_view_context)
    end
  end
  yield @routes
end

def fail_on(exception_class, message)

def fail_on(exception_class, message)
  yield
rescue exception_class => e
  raise Minitest::Assertion, message || e.message
end

def method_missing(selector, *args, &block)

ROUTES TODO: These assertions should really work in an integration context
def method_missing(selector, *args, &block)
  if defined?(@controller) && @controller && defined?(@routes) && @routes && @routes.named_routes.route_defined?(selector)
    @controller.public_send(selector, *args, &block)
  else
    super
  end
end

def recognized_request_for(path, extras = {}, msg)

Recognizes the route for a given path.
def recognized_request_for(path, extras = {}, msg)
  if path.is_a?(Hash)
    method = path[:method]
    path   = path[:path]
  else
    method = :get
  end
  controller = @controller if defined?(@controller)
  request = ActionController::TestRequest.create controller&.class
  if path.include?("://")
    fail_on(URI::InvalidURIError, msg) do
      uri = URI.parse(path)
      request.env["rack.url_scheme"] = uri.scheme || "http"
      request.host = uri.host if uri.host
      request.port = uri.port if uri.port
      request.path = uri.path.to_s.empty? ? "/" : uri.path
    end
  else
    path = "/#{path}" unless path.start_with?("/")
    request.path = path
  end
  request.request_method = method if method
  params = fail_on(ActionController::RoutingError, msg) do
    @routes.recognize_path(path, method: method, extras: extras)
  end
  request.path_parameters = params.with_indifferent_access
  request
end

def reset_routes(old_routes, old_controller)

def reset_routes(old_routes, old_controller)
  @routes = old_routes
  if defined?(@controller) && @controller
    @controller = old_controller
  end
end

def setup # :nodoc:

:nodoc:
def setup # :nodoc:
  @routes ||= nil
  super
end

def with_routing(&block)


end
assert_equal "/users", users_path
end
resources :users
set.draw do
with_routing do |set|

will create some routes using set.draw { match ... }:
The new instance is yielded to the passed block. Typically the block

This method temporarily replaces @routes with a new RouteSet instance.
A helper to make it easier to test different route configurations.
def with_routing(&block)
  old_routes, old_controller = @routes, @controller
  create_routes(&block)
ensure
  reset_routes(old_routes, old_controller)
end