spec/support/matchers/have_nested_routes.rb
RSpec::Matchers.define :have_nested_routes do |association_routes, _options={}|
errors = []
match do |controller|
actual_to_manies = controller.send(:to_many_relationships)
expected_to_manies = association_routes
actual_to_manies.each do |association_name, attr|
expected_actions_for_association = Array(expected_to_manies[association_name])
actual_actions = Array(attr.route_for)
extra_actions = actual_actions - expected_actions_for_association
missing_actions = expected_actions_for_association - actual_actions
handle_errors(extra_actions, missing_actions, controller, association_name, errors)
end
expected_to_manies.each do |association_name, expected_actions|
missing_route = association_name unless actual_to_manies.include?(association_name)
if missing_route
route_should_exist_error(missing_route, errors)
else
actual_actions = Array(actual_to_manies[association_name].route_for)
extra_actions = expected_actions - actual_actions
missing_actions = actual_actions - expected_actions
handle_errors(missing_actions, extra_actions, controller, association_name, errors)
end
end
errors.empty?
end
failure_message do |_|
errors.join("\n")
end
private
def handle_errors(actions_that_should_not_exist, actions_that_should_exist, controller, association_name, errors)
error_root_path = "#{controller.path_guid}/#{association_name}"
error_full_path = "#{error_root_path}/:guid"
actions_that_should_not_exist.each do |action|
error_path = action == :get ? error_root_path : error_full_path
action_should_not_exist_error(error_path, errors)
end
actions_that_should_exist.each do |action|
error_path = action == :get ? error_root_path : error_full_path
action_should_exist_error(error_path, errors)
end
errors
end
def route_should_exist_error(route, errors)
errors << "expected #{route} to exist"
end
def action_should_exist_error(path, errors)
errors << "expected #{path} to exist"
end
def action_should_not_exist_error(path, errors)
errors << "expected #{path} not to exist"
end
end