coverband 6.0.3.rc.3 → 6.0.3.rc.4
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 +4 -4
- data/coverband.gemspec +3 -2
- data/lib/coverband/adapters/hash_redis_store.rb +29 -33
- data/lib/coverband/configuration.rb +5 -1
- data/lib/coverband/reporters/json_report.rb +20 -8
- data/lib/coverband/reporters/web.rb +11 -4
- data/lib/coverband/utils/html_formatter.rb +2 -8
- data/lib/coverband/utils/results.rb +2 -0
- data/lib/coverband/version.rb +1 -1
- data/lib/coverband.rb +2 -18
- data/public/application.css +24 -1
- data/public/application.js +65 -80
- data/test/coverband/reporters/json_test.rb +1 -1
- data/test/coverband/utils/results_test.rb +17 -2
- metadata +2 -4
- data/lib/coverband/reporters/web_pager.rb +0 -28
- data/views/source_file_loader.erb +0 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cf0b6bab823d8155a5e15d361c3acbbef271f84e79947b9818a650e640a61fc7
|
|
4
|
+
data.tar.gz: 25cd0843b3c1e852794bcc008be165bfcbf7e476f373ab681cbff7861f050904
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d2ae2023667369ac1e7be83ec41898c6e77662545f6226c02417ef9a43e75a4e2950ad0d775e18c96d800270d81da104162d4414b13768ac98c14bcff431acd1
|
|
7
|
+
data.tar.gz: 64ddff4e59042a6ee22cd4839e6e7ac57dff4cf289b02a8f6801c144aafea7edd417ed918c38309b61173176cb177ce548dbf6302963d4b53464d8901cb05d30
|
data/coverband.gemspec
CHANGED
|
@@ -34,12 +34,13 @@ Gem::Specification.new do |spec|
|
|
|
34
34
|
spec.add_development_dependency "capybara"
|
|
35
35
|
spec.add_development_dependency "m"
|
|
36
36
|
spec.add_development_dependency "memory_profiler"
|
|
37
|
-
# breaking change in minitest and mocha
|
|
37
|
+
# breaking change in minitest and mocha...
|
|
38
|
+
# note: we are also adding 'spy' as mocha doesn't want us to spy on redis calls...
|
|
39
|
+
# ^^^ probably need a large test cleanup refactor
|
|
38
40
|
spec.add_development_dependency "minitest", "= 5.18.1"
|
|
39
41
|
spec.add_development_dependency "minitest-fork_executor"
|
|
40
42
|
spec.add_development_dependency "minitest-stub-const"
|
|
41
43
|
spec.add_development_dependency "mocha", "~> 1.7.0"
|
|
42
|
-
# spec.add_development_dependency "spy"
|
|
43
44
|
spec.add_development_dependency "rack"
|
|
44
45
|
spec.add_development_dependency "rack-test"
|
|
45
46
|
spec.add_development_dependency "rake"
|
|
@@ -89,7 +89,7 @@ module Coverband
|
|
|
89
89
|
# used to store data to redis. It is changed only when breaking changes to our
|
|
90
90
|
# redis format are required.
|
|
91
91
|
###
|
|
92
|
-
REDIS_STORAGE_FORMAT_VERSION = "
|
|
92
|
+
REDIS_STORAGE_FORMAT_VERSION = "coverband_hash_4_0"
|
|
93
93
|
|
|
94
94
|
JSON_PAYLOAD_EXPIRATION = 5 * 60
|
|
95
95
|
|
|
@@ -107,7 +107,7 @@ module Coverband
|
|
|
107
107
|
@relative_file_converter = opts[:relative_file_converter] || Utils::RelativeFileConverter
|
|
108
108
|
|
|
109
109
|
@get_coverage_cache = if opts[:get_coverage_cache]
|
|
110
|
-
key_prefix = [REDIS_STORAGE_FORMAT_VERSION, @redis_namespace
|
|
110
|
+
key_prefix = [REDIS_STORAGE_FORMAT_VERSION, @redis_namespace].compact.join(".")
|
|
111
111
|
GetCoverageRedisCacheStore.new(redis, key_prefix)
|
|
112
112
|
else
|
|
113
113
|
GetCoverageNullCacheStore
|
|
@@ -172,19 +172,21 @@ module Coverband
|
|
|
172
172
|
@redis.sadd(files_key, keys) if keys.any?
|
|
173
173
|
end
|
|
174
174
|
|
|
175
|
-
#
|
|
175
|
+
# NOTE: This method should be used for full coverage or filename coverage look ups
|
|
176
|
+
# When paging code should use coverage_for_types and pull eager and runtime together as matched pairs
|
|
176
177
|
def coverage(local_type = nil, opts = {})
|
|
177
178
|
page_size = opts[:page_size] || 250
|
|
178
179
|
cached_results = @get_coverage_cache.fetch(local_type || type) do |sleep_time|
|
|
179
180
|
files_set = if opts[:page]
|
|
180
|
-
|
|
181
|
+
raise "call coverage_for_types with paging"
|
|
181
182
|
elsif opts[:filename]
|
|
182
|
-
|
|
183
|
-
|
|
183
|
+
type_key_prefix = key_prefix(local_type)
|
|
184
|
+
# NOTE: a better way to extract filename from key would be better
|
|
185
|
+
files_set(local_type).select { |cache_key| cache_key.sub(type_key_prefix, "").match(short_name(opts[:filename])) } || {}
|
|
184
186
|
else
|
|
185
187
|
files_set(local_type)
|
|
186
188
|
end
|
|
187
|
-
#
|
|
189
|
+
# below uses batches with a sleep in between to avoid overloading redis
|
|
188
190
|
files_set.each_slice(page_size).flat_map do |key_batch|
|
|
189
191
|
sleep sleep_time
|
|
190
192
|
@redis.pipelined do |pipeline|
|
|
@@ -200,33 +202,25 @@ module Coverband
|
|
|
200
202
|
end
|
|
201
203
|
end
|
|
202
204
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
205
|
+
def split_coverage(types, coverage_cache, options = {})
|
|
206
|
+
if types.is_a?(Array) && !options[:filename] && options[:page]
|
|
207
|
+
data = coverage_for_types(types, options)
|
|
208
|
+
coverage_cache[Coverband::RUNTIME_TYPE] = data[Coverband::RUNTIME_TYPE]
|
|
209
|
+
coverage_cache[Coverband::EAGER_TYPE] = data[Coverband::EAGER_TYPE]
|
|
210
|
+
data
|
|
211
|
+
else
|
|
212
|
+
super
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
214
216
|
def coverage_for_types(types, opts = {})
|
|
215
217
|
page_size = opts[:page_size] || 250
|
|
216
218
|
|
|
217
219
|
local_type = Coverband::RUNTIME_TYPE
|
|
218
220
|
hash_data = {}
|
|
219
221
|
|
|
220
|
-
runtime_file_set =
|
|
221
|
-
|
|
222
|
-
elsif opts[:filename]
|
|
223
|
-
# TODO: this probably needs to be an exact match of the parsed cache key section
|
|
224
|
-
# match is a hack that will only kind of work
|
|
225
|
-
files_set(local_type).select{ |cache_key| cache_key.match(short_name(opts[:filename])) } || {}
|
|
226
|
-
else
|
|
227
|
-
files_set(local_type)
|
|
228
|
-
end
|
|
229
|
-
|
|
222
|
+
runtime_file_set = files_set(local_type).each_slice(page_size).to_a[opts[:page] - 1] || []
|
|
223
|
+
|
|
230
224
|
hash_data[Coverband::RUNTIME_TYPE] = runtime_file_set.each_slice(page_size).flat_map do |key_batch|
|
|
231
225
|
@redis.pipelined do |pipeline|
|
|
232
226
|
key_batch.each do |key|
|
|
@@ -235,12 +229,14 @@ module Coverband
|
|
|
235
229
|
end
|
|
236
230
|
end
|
|
237
231
|
|
|
238
|
-
|
|
239
|
-
|
|
232
|
+
eager_key_pre = key_prefix(Coverband::EAGER_TYPE)
|
|
233
|
+
runtime_key_pre = key_prefix(Coverband::RUNTIME_TYPE)
|
|
240
234
|
matched_file_set = files_set(Coverband::EAGER_TYPE)
|
|
241
|
-
.select { |eager_key, val|
|
|
242
|
-
|
|
243
|
-
|
|
235
|
+
.select { |eager_key, val|
|
|
236
|
+
runtime_file_set.any? { |runtime_key|
|
|
237
|
+
(eager_key.sub(eager_key_pre, "") == runtime_key.sub(runtime_key_pre, ""))
|
|
238
|
+
}
|
|
239
|
+
} || []
|
|
244
240
|
hash_data[Coverband::EAGER_TYPE] = matched_file_set.each_slice(page_size).flat_map do |key_batch|
|
|
245
241
|
@redis.pipelined do |pipeline|
|
|
246
242
|
key_batch.each do |key|
|
|
@@ -17,7 +17,7 @@ module Coverband
|
|
|
17
17
|
:s3_secret_access_key, :password, :api_key, :service_url, :coverband_timeout, :service_dev_mode,
|
|
18
18
|
:service_test_mode, :process_type, :track_views, :redis_url,
|
|
19
19
|
:background_reporting_sleep_seconds, :reporting_wiggle,
|
|
20
|
-
:send_deferred_eager_loading_data
|
|
20
|
+
:send_deferred_eager_loading_data, :paged_reporting
|
|
21
21
|
|
|
22
22
|
attr_reader :track_gems, :ignore, :use_oneshot_lines_coverage
|
|
23
23
|
|
|
@@ -293,6 +293,10 @@ module Coverband
|
|
|
293
293
|
@send_deferred_eager_loading_data
|
|
294
294
|
end
|
|
295
295
|
|
|
296
|
+
def paged_reporting
|
|
297
|
+
!!@paged_reporting
|
|
298
|
+
end
|
|
299
|
+
|
|
296
300
|
def service_disabled_dev_test_env?
|
|
297
301
|
return false unless service?
|
|
298
302
|
|
|
@@ -30,6 +30,18 @@ module Coverband
|
|
|
30
30
|
|
|
31
31
|
private
|
|
32
32
|
|
|
33
|
+
def coverage_css_class(covered_percent)
|
|
34
|
+
if covered_percent.nil?
|
|
35
|
+
""
|
|
36
|
+
elsif covered_percent > 90
|
|
37
|
+
"green"
|
|
38
|
+
elsif covered_percent > 80
|
|
39
|
+
"yellow"
|
|
40
|
+
else
|
|
41
|
+
"red"
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
33
45
|
def report_as_json
|
|
34
46
|
result = Coverband::Utils::Results.new(filtered_report_files)
|
|
35
47
|
source_files = result.source_files
|
|
@@ -42,16 +54,16 @@ module Coverband
|
|
|
42
54
|
if as_report
|
|
43
55
|
row_data = []
|
|
44
56
|
data[:files].each_pair do |key, data|
|
|
45
|
-
source_class = data[:never_loaded] ?
|
|
46
|
-
data_loader_url="#{base_path}load_file_details?filename=#{data[:filename]}"
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
# class
|
|
57
|
+
source_class = data[:never_loaded] ? "strong red" : "strong"
|
|
58
|
+
data_loader_url = "#{base_path}load_file_details?filename=#{data[:filename]}"
|
|
59
|
+
link = "<a href=\"##{data[:hash]}\" class=\"src_link #{source_class} cboxElement\" title=\"#{key}\" data-loader-url=\"#{data_loader_url}\" onclick=\"src_link_click(this)\">#{key}</a>"
|
|
60
|
+
# Hack to ensure the sorting works on percentage columns, the span is hidden but colors the cell and the text is used for sorting
|
|
61
|
+
covered_percent = "#{data[:covered_percent]} <span class=\"#{coverage_css_class(data[:covered_percent])}\"> </span>"
|
|
62
|
+
runtime_percentage = "#{data[:runtime_percentage]}<span class=\"#{coverage_css_class(data[:runtime_percentage])}\"> </span>"
|
|
51
63
|
row_data << [
|
|
52
64
|
link,
|
|
53
|
-
|
|
54
|
-
|
|
65
|
+
covered_percent,
|
|
66
|
+
runtime_percentage,
|
|
55
67
|
data[:lines_of_code].to_s,
|
|
56
68
|
(data[:lines_covered] + data[:lines_missed]).to_s,
|
|
57
69
|
data[:lines_covered].to_s,
|
|
@@ -112,11 +112,16 @@ module Coverband
|
|
|
112
112
|
def index
|
|
113
113
|
notice = "<strong>Notice:</strong> #{Rack::Utils.escape_html(request.params["notice"])}<br/>"
|
|
114
114
|
notice = request.params["notice"] ? notice : ""
|
|
115
|
-
|
|
115
|
+
page = (request.params["page"] || 1).to_i
|
|
116
|
+
options = {
|
|
116
117
|
static: false,
|
|
117
118
|
base_path: base_path,
|
|
118
119
|
notice: notice,
|
|
119
|
-
open_report: false
|
|
120
|
+
open_report: false
|
|
121
|
+
}
|
|
122
|
+
options[:page] = page if Coverband.configuration.paged_reporting
|
|
123
|
+
Coverband::Reporters::HTMLReport.new(Coverband.configuration.store,
|
|
124
|
+
options).report
|
|
120
125
|
end
|
|
121
126
|
|
|
122
127
|
def json
|
|
@@ -142,10 +147,12 @@ module Coverband
|
|
|
142
147
|
def display_abstract_tracker(tracker)
|
|
143
148
|
notice = "<strong>Notice:</strong> #{Rack::Utils.escape_html(request.params["notice"])}<br/>"
|
|
144
149
|
notice = request.params["notice"] ? notice : ""
|
|
145
|
-
|
|
150
|
+
options = {
|
|
146
151
|
tracker: tracker,
|
|
147
152
|
notice: notice,
|
|
148
|
-
base_path: base_path
|
|
153
|
+
base_path: base_path
|
|
154
|
+
}
|
|
155
|
+
Coverband::Utils::HTMLFormatter.new(nil, options).format_abstract_tracker!
|
|
149
156
|
end
|
|
150
157
|
|
|
151
158
|
def view_tracker_data
|
|
@@ -117,13 +117,6 @@ module Coverband
|
|
|
117
117
|
puts "Encoding error file:#{source_file.filename} Coverband/ERB error #{e.message}."
|
|
118
118
|
end
|
|
119
119
|
|
|
120
|
-
# Returns the html to ajax load a given source_file
|
|
121
|
-
def formatted_source_file_loader(result, source_file)
|
|
122
|
-
template("source_file_loader").result(binding)
|
|
123
|
-
rescue Encoding::CompatibilityError => e
|
|
124
|
-
puts "Encoding error file:#{source_file.filename} Coverband/ERB error #{e.message}."
|
|
125
|
-
end
|
|
126
|
-
|
|
127
120
|
# Returns a table containing the given source files
|
|
128
121
|
def formatted_file_list(title, result, source_files, options = {})
|
|
129
122
|
title_id = title.gsub(/^[^a-zA-Z]+/, "").gsub(/[^a-zA-Z0-9\-\_]/, "")
|
|
@@ -175,7 +168,8 @@ module Coverband
|
|
|
175
168
|
end
|
|
176
169
|
|
|
177
170
|
def link_to_source_file(source_file)
|
|
178
|
-
|
|
171
|
+
data_loader_url = "#{base_path}load_file_details?filename=#{source_file.filename}"
|
|
172
|
+
%(<a href="##{id source_file}" class="src_link" title="#{shortened_filename source_file}" data-loader-url="#{data_loader_url}" onclick="src_link_click(this)">#{shortened_filename source_file}</a>)
|
|
179
173
|
end
|
|
180
174
|
end
|
|
181
175
|
end
|
|
@@ -44,6 +44,8 @@ module Coverband
|
|
|
44
44
|
eager_file = get_eager_file(source_file)
|
|
45
45
|
runtime_file = get_runtime_file(source_file)
|
|
46
46
|
|
|
47
|
+
return 0 unless runtime_file
|
|
48
|
+
|
|
47
49
|
return runtime_file.covered_lines_count unless eager_file
|
|
48
50
|
|
|
49
51
|
eager_file.relevant_lines - eager_file.covered_lines_count
|
data/lib/coverband/version.rb
CHANGED
data/lib/coverband.rb
CHANGED
|
@@ -91,8 +91,8 @@ module Coverband
|
|
|
91
91
|
coverage_instance.eager_loading!
|
|
92
92
|
end
|
|
93
93
|
|
|
94
|
-
def self.eager_loading_coverage(
|
|
95
|
-
coverage_instance.eager_loading(
|
|
94
|
+
def self.eager_loading_coverage(...)
|
|
95
|
+
coverage_instance.eager_loading(...)
|
|
96
96
|
end
|
|
97
97
|
|
|
98
98
|
def self.runtime_coverage!
|
|
@@ -130,7 +130,6 @@ module Coverband
|
|
|
130
130
|
###
|
|
131
131
|
def initialize
|
|
132
132
|
require "coverband/reporters/web"
|
|
133
|
-
require "coverband/reporters/web_pager"
|
|
134
133
|
require "coverband/utils/html_formatter"
|
|
135
134
|
require "coverband/utils/result"
|
|
136
135
|
require "coverband/utils/file_list"
|
|
@@ -148,19 +147,4 @@ module Coverband
|
|
|
148
147
|
end
|
|
149
148
|
end
|
|
150
149
|
end
|
|
151
|
-
|
|
152
|
-
module Reporters
|
|
153
|
-
class WebPager < Web
|
|
154
|
-
def initialize
|
|
155
|
-
require "coverband/reporters/web"
|
|
156
|
-
require "coverband/reporters/web_pager"
|
|
157
|
-
super
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
def self.call(env)
|
|
161
|
-
@app ||= new
|
|
162
|
-
@app.call(env)
|
|
163
|
-
end
|
|
164
|
-
end
|
|
165
|
-
end
|
|
166
150
|
end
|
data/public/application.css
CHANGED
|
@@ -687,9 +687,17 @@ a.src_link {
|
|
|
687
687
|
background: url("./magnify.png") no-repeat left 50%;
|
|
688
688
|
padding-left: 18px; }
|
|
689
689
|
|
|
690
|
+
a.src_link.strong {
|
|
691
|
+
font-weight: bold;
|
|
692
|
+
}
|
|
693
|
+
|
|
690
694
|
.red a.src_link {
|
|
691
695
|
color: #990000;
|
|
692
|
-
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
a.src_link.red {
|
|
699
|
+
color: #990000;
|
|
700
|
+
}
|
|
693
701
|
|
|
694
702
|
tr, td {
|
|
695
703
|
margin: 0;
|
|
@@ -817,6 +825,21 @@ td {
|
|
|
817
825
|
.red {
|
|
818
826
|
color: #990000; }
|
|
819
827
|
|
|
828
|
+
span.red {
|
|
829
|
+
color: #990000; }
|
|
830
|
+
|
|
831
|
+
td:has(> span.red) {
|
|
832
|
+
color: #990000;
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
td:has(> span.yellow) {
|
|
836
|
+
color: #ddaa00;
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
td:has(> span.green) {
|
|
840
|
+
color: #009900;
|
|
841
|
+
}
|
|
842
|
+
|
|
820
843
|
.yellow {
|
|
821
844
|
color: #ddaa00; }
|
|
822
845
|
|
data/public/application.js
CHANGED
|
@@ -16,7 +16,7 @@ $(document).ready(function() {
|
|
|
16
16
|
});
|
|
17
17
|
|
|
18
18
|
// Configuration for fancy sortable tables for source file groups
|
|
19
|
-
|
|
19
|
+
var tableOptions = {
|
|
20
20
|
aaSorting: [[1, "asc"]],
|
|
21
21
|
bPaginate: false,
|
|
22
22
|
bJQueryUI: true,
|
|
@@ -30,19 +30,25 @@ $(document).ready(function() {
|
|
|
30
30
|
null,
|
|
31
31
|
null,
|
|
32
32
|
null
|
|
33
|
-
]
|
|
34
|
-
}
|
|
33
|
+
],
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
$(".file_list").dataTable(tableOptions);
|
|
35
37
|
|
|
36
|
-
// TODO: add support for searching
|
|
37
|
-
// hmm should I just use manual paging? or load more...
|
|
38
|
+
// TODO: add support for searching on server side
|
|
38
39
|
// best docs on our version of datatables 1.7 https://datatables.net/beta/1.7/examples/server_side/server_side.html
|
|
39
|
-
// TODO: fix bug where we hardcoded /coverage we need to pull it from the path it is mounted on
|
|
40
40
|
if ($(".file_list.unsorted").length == 1) {
|
|
41
|
+
$(".dataTables_empty").html("loading...");
|
|
41
42
|
var current_rows = 0;
|
|
42
43
|
var total_rows = 0;
|
|
43
44
|
var page = 1;
|
|
45
|
+
|
|
46
|
+
// load and render page content before we start the loop
|
|
47
|
+
// perhaps move this into a datatable ready event
|
|
48
|
+
setTimeout(() => {
|
|
49
|
+
get_page(page);
|
|
50
|
+
}, 1250);
|
|
44
51
|
|
|
45
|
-
// write a function to get a page of data and add it to the table
|
|
46
52
|
function get_page(page) {
|
|
47
53
|
$.ajax({
|
|
48
54
|
url: `${$(".file_list").data("coverageurl")}/report_json?page=${page}`,
|
|
@@ -54,92 +60,52 @@ $(document).ready(function() {
|
|
|
54
60
|
// so we don't get back 250 per page... to ensure we we need to account for filtered out and empty files
|
|
55
61
|
// this 250 at the moment is synced to the 250 in the hash redis store
|
|
56
62
|
current_rows += 250; //data["aaData"].length;
|
|
57
|
-
console.log(current_rows);
|
|
58
|
-
console.log(total_rows);
|
|
59
63
|
$(".file_list.unsorted").dataTable().fnAddData(data["aaData"]);
|
|
60
64
|
page += 1;
|
|
65
|
+
// allow rendering to complete before we click the anchor
|
|
66
|
+
setTimeout(() => {
|
|
67
|
+
if (window.auto_click_anchor && $(window.auto_click_anchor).length > 0) {
|
|
68
|
+
$(window.auto_click_anchor).click();
|
|
69
|
+
}
|
|
70
|
+
}, 50);
|
|
61
71
|
// the page less than 100 is to stop infinite loop in case of folks never clearing out old coverage reports
|
|
62
72
|
if (page < 100 && current_rows < total_rows) {
|
|
63
|
-
|
|
73
|
+
setTimeout(() => {
|
|
74
|
+
get_page(page);
|
|
75
|
+
}, 200);
|
|
64
76
|
}
|
|
65
77
|
}
|
|
66
78
|
});
|
|
67
79
|
}
|
|
68
|
-
get_page(page);
|
|
69
80
|
}
|
|
70
81
|
|
|
71
|
-
|
|
72
|
-
// Syntax highlight all files up front - deactivated
|
|
73
|
-
// $('.source_table pre code').each(function(i, e) {hljs.highlightBlock(e, ' ')});
|
|
74
82
|
src_link_click = (trigger_element) => {
|
|
75
|
-
// Get the source file element that corresponds to the clicked element
|
|
76
|
-
var source_table = $(".shared_source_table");
|
|
77
83
|
var loader_url = $(trigger_element).attr("data-loader-url");
|
|
84
|
+
auto_click_anchor = null;
|
|
78
85
|
$(trigger_element).colorbox(jQuery.extend(colorbox_options, { href: loader_url}));
|
|
79
|
-
|
|
80
|
-
// If not highlighted yet, do it!
|
|
81
|
-
if (!source_table.hasClass("highlighted")) {
|
|
82
|
-
source_table.find("pre code").each(function(i, e) {
|
|
83
|
-
hljs.highlightBlock(e, " ");
|
|
84
|
-
});
|
|
85
|
-
source_table.addClass("highlighted");
|
|
86
|
-
}
|
|
87
86
|
};
|
|
88
|
-
window.src_link_click = src_link_click;
|
|
89
87
|
|
|
90
|
-
// Syntax highlight source files on first toggle of the file view popup
|
|
91
|
-
$("a.src_link").click(src_link_click(this));
|
|
92
|
-
|
|
93
|
-
var prev_anchor;
|
|
94
|
-
var curr_anchor;
|
|
95
88
|
var colorbox_options = {
|
|
96
|
-
open: true,
|
|
97
89
|
transition: "none",
|
|
98
|
-
// inline: true,
|
|
99
90
|
opacity: 1,
|
|
100
91
|
width: "95%",
|
|
101
92
|
height: "95%",
|
|
102
93
|
onLoad: function() {
|
|
103
|
-
//
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
94
|
+
// If not highlighted yet, do it!
|
|
95
|
+
var source_table = $(".shared_source_table");
|
|
96
|
+
if (!source_table.hasClass("highlighted")) {
|
|
97
|
+
source_table.find("pre code").each(function(i, e) {
|
|
98
|
+
hljs.highlightBlock(e, " ");
|
|
99
|
+
});
|
|
100
|
+
source_table.addClass("highlighted");
|
|
101
|
+
}
|
|
102
|
+
window.location.hash = this.href.split("#")[1];
|
|
107
103
|
},
|
|
108
104
|
onCleanup: function() {
|
|
109
|
-
|
|
110
|
-
$('a[href="#' + prev_anchor + '"]').click();
|
|
111
|
-
curr_anchor = prev_anchor;
|
|
112
|
-
} else {
|
|
113
|
-
$(".group_tabs a:first").click();
|
|
114
|
-
prev_anchor = curr_anchor;
|
|
115
|
-
curr_anchor = $(".group_tabs a:first").attr("href");
|
|
116
|
-
}
|
|
117
|
-
window.location.hash = curr_anchor;
|
|
105
|
+
window.location.hash = $(".group_tabs a:first").attr("href");
|
|
118
106
|
}
|
|
119
107
|
}
|
|
120
108
|
|
|
121
|
-
src_link_colorbox = (trigger_element) => {
|
|
122
|
-
$(trigger_element).colorbox(colorbox_options);
|
|
123
|
-
};
|
|
124
|
-
window.src_link_colorbox = src_link_colorbox;
|
|
125
|
-
|
|
126
|
-
// Set-up of popup for source file views
|
|
127
|
-
// TODO: drop the static source view even for not paged coverband, then delete all this
|
|
128
|
-
$("a.src_link").colorbox(colorbox_options);
|
|
129
|
-
|
|
130
|
-
window.onpopstate = function(event) {
|
|
131
|
-
if (location.hash.substring(0, 2) == "#_") {
|
|
132
|
-
$.colorbox.close();
|
|
133
|
-
curr_anchor = jQuery.url.attr("anchor");
|
|
134
|
-
} else {
|
|
135
|
-
if ($("#colorbox").is(":hidden")) {
|
|
136
|
-
console.log("pop");
|
|
137
|
-
// $('a.src_link[href="' + location.hash + '"]').colorbox({ open: true });
|
|
138
|
-
$('.shared_source_table').colorbox({ open: true });
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
};
|
|
142
|
-
|
|
143
109
|
// Hide src files and file list container after load
|
|
144
110
|
$(".source_files").hide();
|
|
145
111
|
$(".file_list_container").hide();
|
|
@@ -157,15 +123,20 @@ $(document).ready(function() {
|
|
|
157
123
|
.find(".covered_percent")
|
|
158
124
|
.first()
|
|
159
125
|
.html();
|
|
126
|
+
if (covered_percent) {
|
|
127
|
+
covered_percent = "(" + covered_percent + ")";
|
|
128
|
+
} else {
|
|
129
|
+
covered_percent = "";
|
|
130
|
+
}
|
|
160
131
|
|
|
161
132
|
$(".group_tabs").append(
|
|
162
133
|
'<li><a href="#' +
|
|
163
134
|
container_id +
|
|
164
135
|
'">' +
|
|
165
136
|
group_name +
|
|
166
|
-
"
|
|
137
|
+
" " +
|
|
167
138
|
covered_percent +
|
|
168
|
-
"
|
|
139
|
+
"</a></li>"
|
|
169
140
|
);
|
|
170
141
|
});
|
|
171
142
|
|
|
@@ -197,15 +168,26 @@ $(document).ready(function() {
|
|
|
197
168
|
.addClass("active");
|
|
198
169
|
}
|
|
199
170
|
$(".file_list_container").hide();
|
|
200
|
-
$(".file_list_container" + $(this).attr("href")).show()
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
.
|
|
205
|
-
|
|
206
|
-
|
|
171
|
+
$(".file_list_container" + $(this).attr("href")).show(function() {
|
|
172
|
+
// If we have an anchor to click, click it
|
|
173
|
+
// allow rendering to complete before we click the anchor
|
|
174
|
+
setTimeout(() => {
|
|
175
|
+
if (window.auto_click_anchor && $(window.auto_click_anchor).length > 0) {
|
|
176
|
+
$(window.auto_click_anchor).click();
|
|
177
|
+
}
|
|
178
|
+
}, 30);
|
|
179
|
+
});
|
|
180
|
+
// Below the #_ is a hack to show we have processed the hash change
|
|
181
|
+
if (!window.auto_click_anchor) {
|
|
182
|
+
window.location.href =
|
|
183
|
+
window.location.href.split("#")[0] +
|
|
184
|
+
$(this)
|
|
185
|
+
.attr("href")
|
|
186
|
+
.replace("#", "#_");
|
|
187
|
+
}
|
|
188
|
+
|
|
207
189
|
// Force favicon reload - otherwise the location change containing anchor would drop the favicon...
|
|
208
|
-
// Works only on firefox, but still... - Anyone know a better solution to force favicon on local file?
|
|
190
|
+
// Works only on firefox, but still... - Anyone know a better solution to force favicon on local relative file path?
|
|
209
191
|
$('link[rel="shortcut icon"]').remove();
|
|
210
192
|
$("head").append(
|
|
211
193
|
'<link rel="shortcut icon" type="image/png" href="' +
|
|
@@ -215,18 +197,21 @@ $(document).ready(function() {
|
|
|
215
197
|
return false;
|
|
216
198
|
});
|
|
217
199
|
|
|
200
|
+
// The below function handles turning initial anchors in links to navigate to correct tab
|
|
218
201
|
if (jQuery.url.attr("anchor")) {
|
|
219
202
|
var anchor = jQuery.url.attr("anchor");
|
|
220
|
-
// source file hash
|
|
221
203
|
if (anchor.length == 40) {
|
|
222
|
-
|
|
223
|
-
|
|
204
|
+
// handles deep links to source files
|
|
205
|
+
window.auto_click_anchor = "a.src_link[href=#" + anchor + "]";
|
|
206
|
+
$(".group_tabs a:first").click();
|
|
224
207
|
} else {
|
|
208
|
+
// handles a # anchor that needs to be processed into a #_ completed action
|
|
225
209
|
if ($(".group_tabs a." + anchor.replace("_", "")).length > 0) {
|
|
226
210
|
$(".group_tabs a." + anchor.replace("_", "")).click();
|
|
227
211
|
}
|
|
228
212
|
}
|
|
229
213
|
} else {
|
|
214
|
+
// No anchor, so click the first navigation tab
|
|
230
215
|
$(".group_tabs a:first").click();
|
|
231
216
|
}
|
|
232
217
|
|
|
@@ -38,7 +38,7 @@ class ReportJSONTest < Minitest::Test
|
|
|
38
38
|
json = Coverband::Reporters::JSONReport.new(@store).report
|
|
39
39
|
parsed = JSON.parse(json)
|
|
40
40
|
|
|
41
|
-
expected_keys = ["never_loaded", "runtime_percentage", "lines_of_code", "lines_covered", "lines_runtime", "lines_missed", "covered_percent", "covered_strength"]
|
|
41
|
+
expected_keys = ["filename", "hash", "never_loaded", "runtime_percentage", "lines_of_code", "lines_covered", "lines_runtime", "lines_missed", "covered_percent", "covered_strength"]
|
|
42
42
|
|
|
43
43
|
assert_equal parsed["files"].length, 2
|
|
44
44
|
parsed["files"].keys.each do |file|
|
|
@@ -7,12 +7,14 @@ describe "results" do
|
|
|
7
7
|
let(:source_file) { Coverband::Utils::SourceFile.new(source_fixture("app/models/user.rb"), run_lines) }
|
|
8
8
|
let(:eager_lines) { [nil, 1, 1, 0, nil, nil, 1, 0, nil, nil] }
|
|
9
9
|
let(:run_lines) { [nil, nil, nil, 1, nil, nil, nil, nil, nil, nil] }
|
|
10
|
+
let(:missing_run_coverage_file) { false }
|
|
10
11
|
let(:original_result) do
|
|
11
12
|
orig = {
|
|
12
13
|
Coverband::MERGED_TYPE => {source_fixture("app/models/user.rb") => eager_lines}
|
|
13
14
|
}
|
|
14
15
|
orig[Coverband::EAGER_TYPE] = {source_fixture("app/models/user.rb") => eager_lines} if eager_lines
|
|
15
16
|
orig[Coverband::RUNTIME_TYPE] = {source_fixture("app/models/user.rb") => run_lines} if run_lines
|
|
17
|
+
orig[Coverband::RUNTIME_TYPE] = {"random.rb" => [nil, 1, nil]} if missing_run_coverage_file
|
|
16
18
|
orig
|
|
17
19
|
end
|
|
18
20
|
subject { Coverband::Utils::Results.new(original_result) }
|
|
@@ -27,15 +29,28 @@ describe "results" do
|
|
|
27
29
|
end
|
|
28
30
|
end
|
|
29
31
|
|
|
30
|
-
describe "runtime relevant lines when no runtime coverage
|
|
32
|
+
describe "runtime relevant lines when no runtime coverage file matches" do
|
|
31
33
|
let(:run_lines) { nil }
|
|
32
34
|
|
|
35
|
+
it "has correct runtime relevant coverage" do
|
|
36
|
+
assert_equal 0, subject.runtime_relevant_coverage(source_file)
|
|
37
|
+
end
|
|
38
|
+
|
|
33
39
|
it "has correct runtime relevant lines" do
|
|
40
|
+
assert_equal 0, subject.runtime_relavent_lines(source_file)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
describe "runtime relevant lines when no runtime coverage exists" do
|
|
45
|
+
let(:run_lines) { nil }
|
|
46
|
+
let(:missing_run_coverage_file) { true }
|
|
47
|
+
|
|
48
|
+
it "has correct runtime relevant coverage" do
|
|
34
49
|
assert_equal 0.0, subject.runtime_relevant_coverage(source_file)
|
|
35
50
|
end
|
|
36
51
|
|
|
37
52
|
it "has correct runtime relevant lines" do
|
|
38
|
-
assert_equal
|
|
53
|
+
assert_equal 0, subject.runtime_relavent_lines(source_file)
|
|
39
54
|
end
|
|
40
55
|
end
|
|
41
56
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: coverband
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 6.0.3.rc.
|
|
4
|
+
version: 6.0.3.rc.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dan Mayer
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2024-
|
|
12
|
+
date: 2024-04-09 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: benchmark-ips
|
|
@@ -307,7 +307,6 @@ files:
|
|
|
307
307
|
- lib/coverband/reporters/html_report.rb
|
|
308
308
|
- lib/coverband/reporters/json_report.rb
|
|
309
309
|
- lib/coverband/reporters/web.rb
|
|
310
|
-
- lib/coverband/reporters/web_pager.rb
|
|
311
310
|
- lib/coverband/utils/absolute_file_converter.rb
|
|
312
311
|
- lib/coverband/utils/configuration_template.rb
|
|
313
312
|
- lib/coverband/utils/dead_methods.rb
|
|
@@ -490,7 +489,6 @@ files:
|
|
|
490
489
|
- views/nav.erb
|
|
491
490
|
- views/settings.erb
|
|
492
491
|
- views/source_file.erb
|
|
493
|
-
- views/source_file_loader.erb
|
|
494
492
|
homepage: https://github.com/danmayer/coverband
|
|
495
493
|
licenses:
|
|
496
494
|
- MIT
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "base64"
|
|
4
|
-
require "coverband"
|
|
5
|
-
|
|
6
|
-
begin
|
|
7
|
-
require "rack"
|
|
8
|
-
rescue LoadError
|
|
9
|
-
puts "error loading Coverband web reporter as Rack is not available"
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
module Coverband
|
|
13
|
-
module Reporters
|
|
14
|
-
class WebPager < Web
|
|
15
|
-
def index
|
|
16
|
-
notice = "<strong>Notice:</strong> #{Rack::Utils.escape_html(request.params["notice"])}<br/>"
|
|
17
|
-
notice = request.params["notice"] ? notice : ""
|
|
18
|
-
# TODO: remove the call to the store render empty table
|
|
19
|
-
Coverband::Reporters::HTMLReport.new(Coverband.configuration.store,
|
|
20
|
-
page: (request.params["page"] || 1).to_i,
|
|
21
|
-
static: false,
|
|
22
|
-
base_path: base_path,
|
|
23
|
-
notice: notice,
|
|
24
|
-
open_report: false).report
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
<div class="source_table" id="<%= id source_file %>" data-loader-url="<%= base_path %>load_file_details?filename=<%= source_file.filename %>">
|
|
2
|
-
<div class='loader'>
|
|
3
|
-
loading source data...
|
|
4
|
-
<br/>
|
|
5
|
-
<img src="<%= assets_path('loading.gif') %>" alt="loading"/>
|
|
6
|
-
</div>
|
|
7
|
-
</div>
|