Created
November 29, 2022 16:19
-
-
Save kgilpin/0f86f7ca8bb815e105ce77d94adc61e0 to your computer and use it in GitHub Desktop.
Rake task to detect untested routes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Sort by path, then by method | |
compare_routes = lambda do |a,b| | |
compare = a[1] <=> b[1] | |
compare = a[0] <=> b[0] if compare == 0 | |
compare | |
end | |
normalize_method = lambda do |method| | |
method = method.upcase | |
# For Rails, HEAD request is served by 'show' (GET) | |
# Similarly, PUT request is served by 'update' (PATCH) | |
method = 'GET' if method == 'HEAD' | |
method = 'PATCH' if method == 'PUT' | |
method = 'GET' unless %w[GET CONNECT DELETE HEAD PUT POST PATCH OPTIONS TRACE].member?(method) | |
method | |
end | |
rails_routes = lambda do | |
`rails routes`.split("\n") | |
.map do |line| | |
tokens = line.split(/\s+/) | |
path_index = tokens.index { |token| token[0] == '/' } | |
next unless path_index | |
method = normalize_method.(tokens[path_index-1]) | |
path = tokens[path_index] | |
path.gsub!('(.:format)', '') | |
path.gsub!(/:[^\/]+/) { |match| [ '{', match[1..-1], '}' ].join('') } | |
[ method, path ] | |
end | |
.compact | |
.sort(&compare_routes) | |
.map { |route| route.join(' ') } | |
.uniq | |
end | |
openapi_routes = lambda do | |
# Assumes AppMap-generated OpenAPI in the file swagger/openapi.yaml | |
paths = YAML.load(File.read('swagger/openapi.yaml'))['paths'] | |
path_names = paths.keys | |
paths.map do |entry| | |
path_name, data = entry | |
methods = data.keys | |
methods.map do |method| | |
[ normalize_method.(method), path_name ] | |
end | |
end | |
.flatten(1) | |
.sort(&compare_routes) | |
.map { |route| route.join(' ') } | |
.uniq | |
end | |
namespace :appmap do | |
desc "Use information from swagger/openapi.yaml (generated by AppMap openapi command), and config/untested_routes.txt (a whitelist of routes to ignore) to determine which API routes are untested" | |
task :untested_routes do | |
# Create this files as empty, if it doesn't exist. | |
# To allow untested routes that won't print in the final report, add those routes to this file. | |
untested_routes_whitelist = File.read('config/untested_routes.txt') | |
.split("\n") | |
.select { |line| line.length > 0 && line[0] != '#' } | |
.map(&:strip) | |
untested_routes = rails_routes.() - openapi_routes.() - untested_routes_whitelist | |
undeclared_routes = openapi_routes.() - rails_routes.() | |
unless untested_routes.empty? | |
puts 'Untested routes' | |
puts '---------------' | |
puts untested_routes.join("\n") | |
end | |
unless undeclared_routes.empty? | |
puts unless untested_routes.empty? | |
puts 'Undeclared routes' | |
puts '-----------------' | |
puts undeclared_routes.join("\n") | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment