routes_coverage 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/README.md +1 -0
- data/lib/routes_coverage/adapters/atexit.rb +6 -3
- data/lib/routes_coverage/adapters/rspec.rb +19 -5
- data/lib/routes_coverage/adapters/simplecov.rb +6 -2
- data/lib/routes_coverage/formatters/base.rb +4 -4
- data/lib/routes_coverage/formatters/full_text.rb +39 -37
- data/lib/routes_coverage/formatters/html.rb +20 -27
- data/lib/routes_coverage/formatters/summary_text.rb +10 -7
- data/lib/routes_coverage/middleware.rb +16 -15
- data/lib/routes_coverage/result.rb +37 -45
- data/lib/routes_coverage/version.rb +3 -1
- data/lib/routes_coverage.rb +89 -76
- data/routes_coverage.gemspec +14 -8
- metadata +20 -44
- data/.gitattributes +0 -1
- data/.gitignore +0 -11
- data/.travis.yml +0 -5
- data/Appraisals +0 -33
- data/Gemfile +0 -15
- data/Rakefile +0 -36
- data/bin/console +0 -15
- data/bin/setup +0 -7
- data/gemfiles/.bundle/config +0 -2
- data/gemfiles/rails_3.gemfile +0 -11
- data/gemfiles/rails_3.gemfile.lock +0 -117
- data/gemfiles/rails_40.gemfile +0 -10
- data/gemfiles/rails_40.gemfile.lock +0 -100
- data/gemfiles/rails_40_rspec.gemfile +0 -11
- data/gemfiles/rails_40_rspec.gemfile.lock +0 -119
- data/gemfiles/rails_40_simplecov.gemfile +0 -10
- data/gemfiles/rails_40_simplecov.gemfile.lock +0 -100
- data/gemfiles/rails_42.gemfile +0 -10
- data/gemfiles/rails_42.gemfile.lock +0 -129
- data/gemfiles/rails_5.gemfile +0 -10
- data/gemfiles/rails_5.gemfile.lock +0 -135
- data/gemfiles/rails_51.gemfile +0 -10
- data/gemfiles/rails_51.gemfile.lock +0 -135
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 576b62caebf21a9e1448f549a213eaf5770ca8486c1ad94183c1bd8617bb9916
|
4
|
+
data.tar.gz: 9a150fe8e215e92ba00dee273700ebe69f08baca5606cc7980b09fcc854c0969
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1695cd9694f9388c438814a990127af84930e39413694d15fec8a35bb5f12b1217c1c4a4e8d9fd3b1289a0f91543cc11d772142354481907508337c736f2217e
|
7
|
+
data.tar.gz: 4197958e82df3eceee17d222f441cbf7106d4de67d5fafb3bcdb4d16b0e59159c4678f2420c679483379aeb28a3304b246b77a8215026034aca936af7b4cb797
|
data/README.md
CHANGED
@@ -41,6 +41,7 @@ RSpec.configure do |config|
|
|
41
41
|
config.routes_coverage.exclude_namespaces << 'somenamespace' # excludes /somenamespace/*
|
42
42
|
|
43
43
|
config.routes_coverage.groups["Some Route group title"] = %r{^/somespace/}
|
44
|
+
config.routes_coverage.groups["Subdomain"] = { constraints: { subdomain: 'some_subdomain' }, path: '/' }
|
44
45
|
config.routes_coverage.groups["Admin"] = Regexp.union([
|
45
46
|
%r{^/admin/},
|
46
47
|
%r{^/secret_place/},
|
@@ -1,14 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RoutesCoverage
|
2
4
|
module Adapters
|
3
5
|
class AtExit
|
4
|
-
def self.use
|
5
|
-
#NB: at_exit order is important, for example minitest uses it to run, need to install our handler before it
|
6
|
+
def self.use(_coverer = nil)
|
7
|
+
# NB: at_exit order is important, for example minitest uses it to run, need to install our handler before it
|
6
8
|
|
7
9
|
RoutesCoverage.reset!
|
8
10
|
at_exit do
|
9
11
|
next if RoutesCoverage.pid != Process.pid
|
12
|
+
|
10
13
|
RoutesCoverage.perform_report
|
11
|
-
exit
|
14
|
+
exit # rubocop:disable Rails/Exit
|
12
15
|
end
|
13
16
|
end
|
14
17
|
end
|
@@ -1,12 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rspec/core'
|
4
|
+
|
1
5
|
RSpec.configure do |config|
|
2
6
|
config.add_setting :routes_coverage
|
3
7
|
config.routes_coverage = RoutesCoverage.settings
|
8
|
+
end
|
4
9
|
|
5
|
-
|
6
|
-
|
7
|
-
|
10
|
+
module RoutesCoverage
|
11
|
+
module Adapters
|
12
|
+
class RSpec
|
13
|
+
def self.use
|
14
|
+
::RSpec.configure do |config|
|
15
|
+
config.before(:suite) do
|
16
|
+
RoutesCoverage.reset!
|
17
|
+
end
|
8
18
|
|
9
|
-
|
10
|
-
|
19
|
+
config.after(:suite) do
|
20
|
+
RoutesCoverage.perform_report
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
11
25
|
end
|
12
26
|
end
|
@@ -1,11 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RoutesCoverage
|
2
4
|
module Adapters
|
3
5
|
class SimpleCov
|
4
6
|
def self.use
|
5
7
|
RoutesCoverage.reset!
|
6
|
-
::SimpleCov.at_exit
|
8
|
+
prev_block = ::SimpleCov.at_exit
|
9
|
+
::SimpleCov.at_exit do
|
7
10
|
RoutesCoverage.perform_report
|
8
|
-
|
11
|
+
prev_block.call
|
12
|
+
end
|
9
13
|
end
|
10
14
|
end
|
11
15
|
end
|
@@ -1,15 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RoutesCoverage
|
2
4
|
module Formatters
|
3
5
|
class Base
|
4
|
-
def initialize
|
6
|
+
def initialize(result, groups, settings)
|
5
7
|
@result = result
|
6
8
|
@groups = groups
|
7
9
|
@settings = settings
|
8
10
|
end
|
9
11
|
|
10
|
-
attr_reader :result
|
11
|
-
attr_reader :groups
|
12
|
-
attr_reader :settings
|
12
|
+
attr_reader :result, :groups, :settings
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
@@ -1,11 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RoutesCoverage
|
2
4
|
module Formatters
|
3
5
|
class FullText < SummaryText
|
4
|
-
|
5
6
|
class RouteFormatter
|
6
7
|
attr_reader :buffer
|
7
8
|
|
8
|
-
def initialize
|
9
|
+
def initialize(result = nil, _settings = nil, output_hits: false)
|
9
10
|
@buffer = []
|
10
11
|
@result = result
|
11
12
|
@output_hits = output_hits
|
@@ -28,49 +29,47 @@ module RoutesCoverage
|
|
28
29
|
@buffer << draw_header(routes)
|
29
30
|
end
|
30
31
|
|
31
|
-
def no_routes
|
32
|
+
def no_routes(_routes_from_rails5 = nil)
|
32
33
|
@buffer << "\tNone"
|
33
34
|
end
|
34
35
|
|
35
36
|
private
|
36
|
-
|
37
|
+
|
38
|
+
HEADER = ['Prefix', 'Verb', 'URI Pattern', 'Controller#Action'].freeze
|
37
39
|
def draw_section(routes)
|
38
40
|
header_lengths = HEADER.map(&:length)
|
39
41
|
name_width, verb_width, path_width, reqs_width = widths(routes).zip(header_lengths).map(&:max)
|
40
42
|
|
41
|
-
hits = nil
|
42
43
|
routes.map do |r|
|
43
|
-
#
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
original_route = r[:original]
|
50
|
-
end
|
51
|
-
hits = " #{@result.route_hit_counts[original_route]}"
|
52
|
-
end
|
53
|
-
"#{r[:name].rjust(name_width) if @output_prefix} #{r[:verb].ljust(verb_width)} #{r[:path].ljust(path_width)} #{r[:reqs].ljust(reqs_width)}#{hits}"
|
44
|
+
# unwrap SimpleDelegator
|
45
|
+
original_route = r[:original].respond_to?(:__getobj__) ? r[:original].__getobj__ : r[:original]
|
46
|
+
|
47
|
+
"#{r[:name].rjust(name_width) if @output_prefix} "\
|
48
|
+
"#{r[:verb].ljust(verb_width)} #{r[:path].ljust(path_width)} #{r[:reqs].ljust(reqs_width)}"\
|
49
|
+
"#{" #{@result.route_hit_counts[original_route]}" if @output_hits}"
|
54
50
|
end
|
55
51
|
end
|
56
52
|
|
57
53
|
def draw_header(routes)
|
58
54
|
name_width, verb_width, path_width, reqs_width = widths(routes)
|
59
55
|
|
60
|
-
|
56
|
+
[
|
57
|
+
('Prefix'.rjust(name_width) if @output_prefix),
|
58
|
+
'Verb'.ljust(verb_width),
|
59
|
+
'URI Pattern'.ljust(path_width),
|
60
|
+
'Controller#Action'.ljust(reqs_width),
|
61
|
+
('Hits' if @output_hits)
|
62
|
+
].compact.join(' ')
|
61
63
|
end
|
62
64
|
|
63
65
|
def widths(routes)
|
64
|
-
[
|
65
|
-
|
66
|
-
|
67
|
-
routes.map { |r| r[:reqs].length }.max || 0,
|
68
|
-
]
|
66
|
+
%i[name verb path reqs].map do |key|
|
67
|
+
routes.map { |r| r[key].length }.max.to_i
|
68
|
+
end
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
-
|
73
|
-
def routes_section formatter, title, routes
|
72
|
+
def routes_section(formatter, title, routes)
|
74
73
|
formatter.buffer << title
|
75
74
|
|
76
75
|
if routes.none?
|
@@ -83,24 +82,27 @@ module RoutesCoverage
|
|
83
82
|
formatter.result
|
84
83
|
end
|
85
84
|
|
86
|
-
def
|
87
|
-
|
85
|
+
def collect_routes(routes)
|
86
|
+
# rails 3
|
87
|
+
return Result::Inspector.new.collect_all_routes(routes) unless Result::Inspector::NEW_RAILS
|
88
|
+
|
89
|
+
Result::Inspector.new(routes).collect_all_routes
|
90
|
+
end
|
91
|
+
|
92
|
+
def hit_routes_details
|
88
93
|
# engine routes now are in the same list
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
#
|
94
|
-
hit_routes = Result::Inspector.new.collect_all_routes(result.hit_routes)
|
95
|
-
pending_routes = Result::Inspector.new.collect_all_routes(result.pending_routes)
|
96
|
-
end
|
94
|
+
hit_routes = collect_routes(result.hit_routes)
|
95
|
+
pending_routes = collect_routes(result.pending_routes)
|
96
|
+
|
97
|
+
<<~TXT
|
98
|
+
#{routes_section(RouteFormatter.new(result, settings, output_hits: true), 'Covered routes:', hit_routes)}
|
97
99
|
|
98
|
-
|
99
|
-
|
100
|
+
#{routes_section(RouteFormatter.new(result, settings), 'Pending routes:', pending_routes)}
|
101
|
+
TXT
|
100
102
|
end
|
101
103
|
|
102
104
|
def format
|
103
|
-
"#{super}\n\n#{
|
105
|
+
"#{super}\n\n#{hit_routes_details}"
|
104
106
|
end
|
105
107
|
end
|
106
108
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "erb"
|
2
4
|
require "cgi"
|
3
5
|
require "fileutils"
|
@@ -23,24 +25,25 @@ module RoutesCoverage
|
|
23
25
|
ERB.new(File.read(File.join(File.dirname(__FILE__), "html_views", "#{name}.erb")))
|
24
26
|
end
|
25
27
|
|
26
|
-
|
27
28
|
def root(root = nil)
|
28
|
-
#TODO: config for this
|
29
|
+
# TODO: config for this
|
29
30
|
return SimpleCov.root if defined? SimpleCov
|
30
31
|
return @root if defined?(@root) && root.nil?
|
32
|
+
|
31
33
|
@root = File.expand_path(root || Dir.getwd)
|
32
34
|
end
|
33
35
|
|
34
36
|
def coverage_dir(dir = nil)
|
35
|
-
#TODO: config for this
|
37
|
+
# TODO: config for this
|
36
38
|
return SimpleCov.coverage_dir if defined? SimpleCov
|
37
39
|
return @coverage_dir if defined?(@coverage_dir) && dir.nil?
|
38
|
-
|
40
|
+
|
41
|
+
@output_path = nil # invalidate cache
|
39
42
|
@coverage_dir = (dir || "coverage")
|
40
43
|
end
|
41
44
|
|
42
45
|
def output_path
|
43
|
-
@
|
46
|
+
@output_path ||= File.expand_path(coverage_dir, root).tap do |path|
|
44
47
|
FileUtils.mkdir_p path
|
45
48
|
end
|
46
49
|
end
|
@@ -51,8 +54,8 @@ module RoutesCoverage
|
|
51
54
|
@project_name ||= File.basename(root.split("/").last).capitalize.tr("_", " ")
|
52
55
|
end
|
53
56
|
|
54
|
-
def asset_content
|
55
|
-
File.read(File.expand_path("../../../compiled_assets/#{name}",
|
57
|
+
def asset_content(name)
|
58
|
+
File.read(File.expand_path("../../../compiled_assets/#{name}", __dir__))
|
56
59
|
end
|
57
60
|
|
58
61
|
def style_asset_link
|
@@ -83,33 +86,23 @@ module RoutesCoverage
|
|
83
86
|
end
|
84
87
|
end
|
85
88
|
|
86
|
-
def hits_css_class
|
87
|
-
hits
|
89
|
+
def hits_css_class(hits)
|
90
|
+
hits.positive? ? 'cov' : 'uncov'
|
88
91
|
end
|
89
92
|
|
90
93
|
def timeago(time)
|
91
94
|
"<abbr class=\"timeago\" title=\"#{time.iso8601}\">#{time.iso8601}</abbr>"
|
92
95
|
end
|
93
96
|
|
94
|
-
|
95
97
|
def all_result_groups
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
@all_result_groups += groups.map do |group_name, group_result|
|
105
|
-
{
|
106
|
-
id: group_name.gsub(/^[^a-zA-Z]+/, "").gsub(/[^a-zA-Z0-9\-\_]/, ""),
|
107
|
-
name: group_name,
|
108
|
-
result: group_result,
|
109
|
-
}
|
110
|
-
end
|
111
|
-
|
112
|
-
@all_result_groups
|
98
|
+
@all_result_groups ||= [{ id: 'all_routes', name: 'All Routes', result: result }] +
|
99
|
+
groups.map do |group_name, group_result|
|
100
|
+
{
|
101
|
+
id: group_name.gsub(/^[^a-zA-Z]+/, "").gsub(/[^a-zA-Z0-9\-_]/, ""),
|
102
|
+
name: group_name,
|
103
|
+
result: group_result
|
104
|
+
}
|
105
|
+
end
|
113
106
|
end
|
114
107
|
end
|
115
108
|
end
|
@@ -1,15 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RoutesCoverage
|
2
4
|
module Formatters
|
3
5
|
class SummaryText < Base
|
4
|
-
def hits_count
|
5
|
-
"#{result.hit_routes_count} of #{result.expected_routes_count}
|
6
|
+
def hits_count(result)
|
7
|
+
"#{result.hit_routes_count} of #{result.expected_routes_count}"\
|
8
|
+
"#{"(#{result.total_count} total)" if result.expected_routes_count != result.total_count}"\
|
9
|
+
" routes hit#{" at #{result.avg_hits} hits average" if result.hit_routes_count.positive?}"
|
6
10
|
end
|
7
11
|
|
8
12
|
def status
|
9
13
|
return unless settings.minimum_coverage
|
10
|
-
|
11
|
-
|
12
|
-
end
|
14
|
+
|
15
|
+
"Coverage is too low" unless result.coverage_pass?
|
13
16
|
end
|
14
17
|
|
15
18
|
def format
|
@@ -18,9 +21,9 @@ module RoutesCoverage
|
|
18
21
|
]
|
19
22
|
|
20
23
|
if groups.any?
|
21
|
-
buffer += groups.map
|
24
|
+
buffer += groups.map do |group_name, group_result|
|
22
25
|
" #{group_name}: #{group_result.coverage}% (#{hits_count group_result})"
|
23
|
-
|
26
|
+
end
|
24
27
|
end
|
25
28
|
|
26
29
|
buffer << status
|
@@ -1,26 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RoutesCoverage
|
2
4
|
class Middleware
|
3
|
-
def initialize
|
5
|
+
def initialize(app)
|
4
6
|
@app = app
|
5
7
|
end
|
6
8
|
|
7
|
-
def call
|
9
|
+
def call(original_env)
|
8
10
|
# router changes env/request during recognition so need a copy:
|
9
|
-
|
10
|
-
::Rails.application.routes.
|
11
|
+
env = original_env.dup
|
12
|
+
req = ::Rails.application.routes.request_class.new env
|
13
|
+
::Rails.application.routes.router.recognize(req) do |route, parameters5, parameters4|
|
14
|
+
parameters = parameters5 || parameters4
|
11
15
|
dispatcher = route.app
|
12
16
|
if dispatcher.respond_to?(:dispatcher?)
|
13
|
-
|
14
|
-
|
15
|
-
end
|
17
|
+
req.path_parameters = parameters
|
18
|
+
dispatcher = nil unless dispatcher.matches?(req) # && dispatcher.dispatcher?
|
16
19
|
else # rails < 4.2
|
17
20
|
dispatcher = route.app
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
dispatcher = nil
|
23
|
-
end
|
21
|
+
req.env['action_dispatch.request.path_parameters'] =
|
22
|
+
(env['action_dispatch.request.path_parameters'] || {}).merge(parameters)
|
23
|
+
while dispatcher.is_a?(ActionDispatch::Routing::Mapper::Constraints)
|
24
|
+
dispatcher = (dispatcher.app if dispatcher.matches?(env))
|
24
25
|
end
|
25
26
|
end
|
26
27
|
next unless dispatcher
|
@@ -29,8 +30,8 @@ module RoutesCoverage
|
|
29
30
|
# there may be multiple matching routes - we should match only first
|
30
31
|
break
|
31
32
|
end
|
32
|
-
#TODO: detect 404s? and maybe other route errors?
|
33
|
-
@app.call(
|
33
|
+
# TODO: detect 404s? and maybe other route errors?
|
34
|
+
@app.call(original_env)
|
34
35
|
end
|
35
36
|
end
|
36
37
|
end
|
@@ -1,19 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_support/core_ext/string' # needed for rails5 version of inspector
|
2
4
|
|
3
5
|
module RoutesCoverage
|
4
6
|
class Result
|
5
|
-
|
6
7
|
begin
|
7
8
|
require 'action_dispatch/routing/inspector'
|
8
9
|
class Inspector < ActionDispatch::Routing::RoutesInspector
|
9
10
|
NEW_RAILS = true
|
10
11
|
def collect_all_routes
|
11
12
|
res = collect_routes(@routes)
|
12
|
-
#TODO: test with engines
|
13
|
+
# TODO: test with engines
|
13
14
|
@engines.each do |engine_name, engine_routes|
|
14
|
-
res += engine_routes.map
|
15
|
+
res += engine_routes.map do |er|
|
15
16
|
er.merge({ engine_name: engine_name })
|
16
|
-
|
17
|
+
end
|
17
18
|
end
|
18
19
|
res
|
19
20
|
end
|
@@ -21,39 +22,35 @@ module RoutesCoverage
|
|
21
22
|
def collect_routes(routes)
|
22
23
|
routes.collect do |route|
|
23
24
|
ActionDispatch::Routing::RouteWrapper.new(route)
|
24
|
-
end.reject do |route|
|
25
|
-
route.internal?
|
26
|
-
end.collect do |route|
|
25
|
+
end.reject(&:internal?).collect do |route| # rubocop:disable Style/MultilineBlockChain
|
27
26
|
collect_engine_routes(route)
|
28
27
|
|
29
|
-
{ name:
|
30
|
-
verb:
|
31
|
-
path:
|
32
|
-
reqs:
|
28
|
+
{ name: route.name,
|
29
|
+
verb: route.verb,
|
30
|
+
path: route.path,
|
31
|
+
reqs: route.reqs,
|
33
32
|
# regexp: route.json_regexp, # removed, this is not present in rails5
|
34
33
|
# added:
|
35
|
-
original: route
|
36
|
-
}
|
34
|
+
original: route }
|
37
35
|
end
|
38
36
|
end
|
39
37
|
end
|
40
|
-
|
41
38
|
rescue LoadError
|
42
|
-
#rails 3
|
39
|
+
# rails 3
|
43
40
|
require 'rails/application/route_inspector'
|
44
41
|
class Inspector < Rails::Application::RouteInspector
|
45
42
|
NEW_RAILS = false
|
46
|
-
def collect_all_routes(routes)
|
43
|
+
def collect_all_routes(routes) # rubocop:disable Lint/DuplicateMethods
|
47
44
|
res = collect_routes(routes)
|
48
45
|
@engines.each do |engine_name, engine_routes|
|
49
|
-
res += engine_routes.map
|
46
|
+
res += engine_routes.map do |er|
|
50
47
|
er.merge({ engine_name: engine_name })
|
51
|
-
|
48
|
+
end
|
52
49
|
end
|
53
50
|
res
|
54
51
|
end
|
55
52
|
|
56
|
-
def collect_routes(routes)
|
53
|
+
def collect_routes(routes) # rubocop:disable Lint/DuplicateMethods
|
57
54
|
routes = routes.collect do |route|
|
58
55
|
route_reqs = route.requirements
|
59
56
|
|
@@ -70,44 +67,40 @@ module RoutesCoverage
|
|
70
67
|
|
71
68
|
collect_engine_routes(reqs, rack_app)
|
72
69
|
|
73
|
-
{ name:
|
74
|
-
verb:
|
75
|
-
path:
|
76
|
-
reqs:
|
70
|
+
{ name: route.name.to_s,
|
71
|
+
verb: route.verb.source.gsub(/[$^]/, ''),
|
72
|
+
path: route.path.spec.to_s,
|
73
|
+
reqs: reqs,
|
77
74
|
# added:
|
78
|
-
original: route
|
79
|
-
}
|
75
|
+
original: route }
|
80
76
|
end
|
81
77
|
|
82
78
|
# Skip the route if it's internal info route
|
83
79
|
routes.reject { |r| r[:path] =~ %r{/rails/info/properties|^#{Rails.application.config.assets.prefix}} }
|
84
80
|
end
|
85
81
|
end
|
86
|
-
|
87
82
|
end
|
88
83
|
|
89
|
-
def initialize
|
84
|
+
def initialize(all_routes, hit_routes, settings)
|
90
85
|
@all_routes = all_routes
|
91
86
|
@route_hit_counts = hit_routes
|
92
87
|
@settings = settings
|
93
88
|
end
|
94
89
|
|
95
|
-
attr_reader :all_routes
|
96
|
-
|
97
|
-
attr_reader :route_hit_counts
|
90
|
+
attr_reader :all_routes, :route_hit_counts
|
98
91
|
|
99
92
|
def expected_routes
|
100
93
|
return @expected_routes if @expected_routes
|
101
94
|
|
102
95
|
filter_regex = Regexp.union(@settings.exclude_patterns)
|
103
|
-
namespaces_regex = Regexp.union(@settings.exclude_namespaces.map{|n|
|
96
|
+
namespaces_regex = Regexp.union(@settings.exclude_namespaces.map { |n| %r{^/#{n}} })
|
104
97
|
|
105
|
-
routes_groups = all_routes.group_by
|
106
|
-
|
98
|
+
routes_groups = all_routes.group_by do |r|
|
99
|
+
(
|
107
100
|
("#{r.verb.to_s[8..-3]} #{r.path.spec}".strip =~ filter_regex) ||
|
108
101
|
(r.path.spec.to_s =~ namespaces_regex)
|
109
|
-
)
|
110
|
-
|
102
|
+
).present?
|
103
|
+
end
|
111
104
|
|
112
105
|
@excluded_routes = routes_groups[true] || []
|
113
106
|
@expected_routes = routes_groups[false] || []
|
@@ -123,11 +116,10 @@ module RoutesCoverage
|
|
123
116
|
end
|
124
117
|
|
125
118
|
def hit_routes
|
126
|
-
#TODO: sort?
|
119
|
+
# TODO: sort?
|
127
120
|
@route_hit_counts.keys
|
128
121
|
end
|
129
122
|
|
130
|
-
|
131
123
|
def hit_routes_count
|
132
124
|
@route_hit_counts.size
|
133
125
|
end
|
@@ -146,6 +138,7 @@ module RoutesCoverage
|
|
146
138
|
|
147
139
|
def coverage
|
148
140
|
return 0 unless expected_routes.any?
|
141
|
+
|
149
142
|
(hit_routes_count * 100.0 / expected_routes_count).round(@settings.round_precision)
|
150
143
|
end
|
151
144
|
|
@@ -158,16 +151,15 @@ module RoutesCoverage
|
|
158
151
|
end
|
159
152
|
|
160
153
|
def all_routes_with_hits
|
161
|
-
if Inspector::NEW_RAILS
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
res.each
|
154
|
+
res = if Inspector::NEW_RAILS
|
155
|
+
Inspector.new(all_routes).collect_all_routes
|
156
|
+
else
|
157
|
+
Inspector.new.collect_all_routes(all_routes)
|
158
|
+
end
|
159
|
+
res.each do |val|
|
167
160
|
val[:hits] = @route_hit_counts[val[:original]] || 0
|
168
|
-
|
161
|
+
end
|
169
162
|
res
|
170
163
|
end
|
171
|
-
|
172
164
|
end
|
173
165
|
end
|