coverband 6.0.3.rc.3 → 6.0.3.rc.4
Sign up to get free protection for your applications and to get access to all the features.
- 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>
|