simplecov_linter_formatter 0.1.0 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 483e6b37b14cb89c8d7d464115018180fa013dd672f8a9f965b5fea0dad83a3f
4
- data.tar.gz: 123ef1b96087793991debd9d356c30fffecefff1f081531bbd3679ed90369267
3
+ metadata.gz: 5f1ca65ad6bdacc453fa5df9593826cf34106da48e60886fd8ff69fccc523cad
4
+ data.tar.gz: e7b97571b7de89cf5babfde9695d06fcac5b3bb492f2e22036e1c566590b0d3e
5
5
  SHA512:
6
- metadata.gz: 90fe058c5340e29ddcb0ae7346781fee8b9cdc8464d6d0b5c8cac06d8ce135d9174d1746e1dcbde8ee5bcb99d4782137ada8cdf62a54f641f3dbeea69341fde6
7
- data.tar.gz: e605b920212343c9d65cdf0aaf9dc476b70bacf5fd5d6af6e27e11c98aaa7e4a7bcfa1c6d323fc85de0ea9897d31058009f669a6a964f51e7bd0532c1b12cfa0
6
+ metadata.gz: 2336fa2a71a62a6f60e99b82bbe1721254aa43269cfc362d97712190490d915d982e55a4d1f15914f433c50ff2d1fb823e6cc158d6967da906e976f51d424049
7
+ data.tar.gz: df7616fa9792a3ac67b84275430f523a8984c2066901c84ead8c5179ce2529010bdb421b6795c58298ef8446544d49889c43b11f02ea3a8cddb774a2d367c384
data/CHANGELOG.md CHANGED
@@ -2,7 +2,12 @@
2
2
  All notable changes to this project will be documented in this file.
3
3
  This project adheres to [Semantic Versioning](http://semver.org/).
4
4
 
5
- ### Unreleased
5
+ ### v0.2.0
6
+
7
+ #### Added
8
+
9
+ * Add on screen summary report.
10
+ * Use `git diff` if `reviewdog` is not installed.
6
11
 
7
12
  ### v0.1.0
8
13
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- simplecov_linter_formatter (0.1.0)
4
+ simplecov_linter_formatter (0.2.0)
5
+ rainbow
5
6
 
6
7
  GEM
7
8
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -5,9 +5,21 @@
5
5
 
6
6
  Linter formatter for SimpleCov code coverage tool
7
7
 
8
- <img src="./docs/assets/not-covered.png" witdh="300" />
9
- <img src="./docs/assets/partial-cov.png" witdh="300" />
10
- <img src="./docs/assets/covered.png" witdh="300" />
8
+ ***Note: To learn more about SimpleCov, check out the main repo at [https://github.com/simplecov-ruby/simplecov](https://github.com/colszowka/simplecov)***
9
+
10
+ This formatter has two features:
11
+
12
+ 1) It generates a json file to feed the [VSCode SimpleCov plugin](https://github.com/anykeyh/simplecov-vscode).
13
+
14
+ The plugin uses by default the json file produced by simplecov but, with this gem, we can filter the file to show code coverage related to our changes.
15
+
16
+ <img src="./docs/assets/not-covered.png" witdh="300" />
17
+ <img src="./docs/assets/partial-cov.png" witdh="300" />
18
+ <img src="./docs/assets/covered.png" witdh="300" />
19
+
20
+ 2) It shows a code coverage report on screen.
21
+
22
+ <img src="./docs/assets/report-example.png" witdh="300" />
11
23
 
12
24
  ## Installation
13
25
 
@@ -17,6 +29,8 @@ Linter formatter for SimpleCov code coverage tool
17
29
  brew install reviewdog/tap/reviewdog
18
30
  ```
19
31
 
32
+ > You can avoid this step and `git status` will be used to filter results instead.
33
+
20
34
  - Install [VSCode SimpleCov plugin](https://github.com/anykeyh/simplecov-vscode)
21
35
 
22
36
  You need to configure `SimpleCovLinterFormatter.json_filename = '.resultset.json'` to use the extension's default configuration.
@@ -41,8 +55,10 @@ Add the formatter to your `spec/spec_helper.rb`.
41
55
  require 'simplecov'
42
56
  require 'simplecov_linter_formatter'
43
57
 
44
- SimpleCovLinterFormatter.json_filename = '.resultset.json'
45
- SimpleCovLinterFormatter.scope = :all
58
+ SimpleCovLinterFormatter.setup do |config|
59
+ config.json_filename = '.resultset.json'
60
+ config.scope = :all
61
+ end
46
62
 
47
63
  SimpleCov.start 'rails' do
48
64
  # ...
@@ -58,6 +74,41 @@ end
58
74
 
59
75
  If you configure `SimpleCovLinterFormatter.scope = :own_changes` instead of `:all` you will see coverage warnings related to your changes only (it uses `git diff`).
60
76
 
77
+ ### Summary Report
78
+
79
+ - Turn on the on screen report with option: `SimpleCovLinterFormatter.summary_enabled = true`
80
+ - Scope variation will affect the report:
81
+ - `SimpleCovLinterFormatter.scope = :all`
82
+
83
+ <img src="./docs/assets/all-summary.png" witdh="300" />
84
+
85
+ - `SimpleCovLinterFormatter.scope = :own_changes`
86
+
87
+ <img src="./docs/assets/own-changes-summary.png" witdh="300" />
88
+
89
+ - Sort by `:alphabet` or, the default, `:coverage` option with `SimpleCovLinterFormatter.summary_files_sorting = :alphabet`
90
+
91
+ <img src="./docs/assets/sorted-summary.png" witdh="300" />
92
+
93
+ - Change the look of the report:
94
+ - Turn off the background with `SimpleCovLinterFormatter.summary_enabled_bg = false`
95
+
96
+ <img src="./docs/assets/no-bg-summary.png" witdh="300" />
97
+
98
+ - Change colors:
99
+
100
+ ```ruby
101
+ SimpleCovLinterFormatter.setup do |config|
102
+ config.summary_enabled_bg = true # you need enabled background
103
+ config.summary_covered_bg_color = :lightblue
104
+ config.summary_not_covered_bg_color = :pink
105
+ config.summary_text_color = :black
106
+ end
107
+ ```
108
+
109
+ <img src="./docs/assets/colors-summary.png" witdh="300" />
110
+
111
+
61
112
  ## Testing
62
113
 
63
114
  To run the specs you need to execute, **in the root path of the gem**, the following command:
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,63 @@
1
+ module SimpleCovLinterFormatter
2
+ class FileLine
3
+ attr_reader :file_name
4
+
5
+ def initialize(line)
6
+ @line = line
7
+ assign_attributes
8
+ end
9
+
10
+ def status
11
+ @status.to_sym
12
+ end
13
+
14
+ def line_number
15
+ @line_number.to_i
16
+ end
17
+
18
+ def line_number_idx
19
+ line_number - 1
20
+ end
21
+
22
+ def column
23
+ @column.to_i
24
+ end
25
+
26
+ def lines_count
27
+ @lines_count.to_i
28
+ end
29
+
30
+ def percentage
31
+ @percentage.to_f
32
+ end
33
+
34
+ def file_short_name
35
+ @file_short_name ||= file_name.gsub(project_path, "")
36
+ end
37
+
38
+ def file_int_percentage
39
+ @file_int_percentage ||= percentage.to_i
40
+ end
41
+
42
+ private
43
+
44
+ def project_path
45
+ root_path = ""
46
+ return root_path unless Object.const_defined?('Rails')
47
+ return root_path unless Rails.respond_to?(:root)
48
+
49
+ Rails.root.to_s
50
+ rescue NameError
51
+ ""
52
+ end
53
+
54
+ def assign_attributes
55
+ @file_name, @line_number, @column, status_lines_count = @line.split(
56
+ SimpleCovLinterFormatter::LINE_SECTIONS_DIVIDER
57
+ )
58
+ @status, @lines_count, @percentage = status_lines_count.split(
59
+ SimpleCovLinterFormatter::MSG_DIVIDER
60
+ )
61
+ end
62
+ end
63
+ end
@@ -8,19 +8,31 @@ module SimpleCovLinterFormatter
8
8
 
9
9
  def format
10
10
  lines.map do |line|
11
- build_message(line)
11
+ build_line_text(line)
12
12
  end
13
13
  end
14
14
 
15
15
  private
16
16
 
17
- def build_message(line)
17
+ def build_line_text(line)
18
18
  [
19
19
  @source_file.filename,
20
20
  line.line_number,
21
21
  FILE_COLUMN,
22
- "#{line.status}-#{lines_count}"
23
- ].map(&:to_s).join(":")
22
+ build_line_msg(line)
23
+ ].map(&:to_s).join(SimpleCovLinterFormatter::LINE_SECTIONS_DIVIDER)
24
+ end
25
+
26
+ def build_line_msg(line)
27
+ [
28
+ line.status,
29
+ lines_count,
30
+ stats.percent
31
+ ].map(&:to_s).join(SimpleCovLinterFormatter::MSG_DIVIDER)
32
+ end
33
+
34
+ def stats
35
+ @stats ||= @source_file.coverage_statistics[:line]
24
36
  end
25
37
 
26
38
  def lines_count
@@ -19,10 +19,9 @@ module SimpleCovLinterFormatter
19
19
  result = {}
20
20
 
21
21
  @lines.each do |line|
22
- file_name, line_number, _column, status_lines_count = line.split(":")
23
- status, lines_count = status_lines_count.split("-")
24
- result[file_name] ||= { lines: [nil] * lines_count.to_i }
25
- result[file_name][:lines][line_number.to_i - 1] = status.to_sym == :missed ? 0 : nil
22
+ file = SimpleCovLinterFormatter::FileLine.new(line)
23
+ result[file.file_name] ||= { lines: [nil] * file.lines_count }
24
+ result[file.file_name][:lines][file.line_number_idx] = file.status == :missed ? 0 : nil
26
25
  end
27
26
 
28
27
  result
@@ -0,0 +1,127 @@
1
+ module SimpleCovLinterFormatter
2
+ class SummaryBuilder
3
+ PERCENT_TEXT_SIZE = 3
4
+
5
+ def initialize(lines)
6
+ @lines = lines
7
+ @largest_file_name = 0
8
+ @largest_percentage = 0
9
+ end
10
+
11
+ def build
12
+ body = build_body
13
+ return body if body == ""
14
+
15
+ "#{build_title}\n#{body}#{divider}"
16
+ end
17
+
18
+ private
19
+
20
+ def build_title
21
+ "SimpleCov Report - #{build_coverage_title}:\n#{divider}"
22
+ end
23
+
24
+ def divider
25
+ '-' * report_width
26
+ end
27
+
28
+ def report_width
29
+ @largest_file_name + @largest_percentage + PERCENT_TEXT_SIZE
30
+ end
31
+
32
+ def build_coverage_title
33
+ if SimpleCovLinterFormatter.cover_all?
34
+ return "Total Coverage"
35
+ end
36
+
37
+ "Own Changes"
38
+ end
39
+
40
+ def build_body
41
+ result = ""
42
+
43
+ files.each do |file|
44
+ result += "#{build_line_output(file)}\n"
45
+ end
46
+
47
+ result
48
+ end
49
+
50
+ def files
51
+ unique_files = []
52
+ added_files = {}
53
+
54
+ @lines.each do |line|
55
+ file = SimpleCovLinterFormatter::FileLine.new(line)
56
+ next if added_files[file.file_short_name]
57
+
58
+ unique_files << file
59
+ added_files[file.file_short_name] = true
60
+ file_size = file.file_short_name.size
61
+ file_percentage = file.file_int_percentage.to_s.size
62
+ @largest_file_name = file_size if file_size > @largest_file_name
63
+ @largest_percentage = file_percentage if file_percentage > @largest_percentage
64
+ end
65
+
66
+ sort_files(unique_files)
67
+ end
68
+
69
+ def sort_files(files)
70
+ sorting_strategy = if SimpleCovLinterFormatter.summary_coverage_sorting?
71
+ Proc.new { |file| [file.percentage, file.file_short_name] }
72
+ else
73
+ Proc.new { |file| file.file_short_name }
74
+ end
75
+ files.sort_by { |file| sorting_strategy.call(file) }
76
+ end
77
+
78
+ def build_line_output(file)
79
+ file_name = adjusted_file_name(file)
80
+ covered_size = @largest_file_name * file.percentage / 100.0
81
+ covered_text = colorize_text(
82
+ covered_size.zero? ? "" : file_name[0..(covered_size - 1)],
83
+ :summary_covered_bg_color
84
+ )
85
+ not_covered_text = colorize_text(
86
+ file_name[covered_size..-1],
87
+ :summary_not_covered_bg_color
88
+ )
89
+ "#{build_percentage_output(file)} #{covered_text}#{not_covered_text}"
90
+ end
91
+
92
+ def colorize_text(text, bg_option)
93
+ text = Rainbow(text).color(SimpleCovLinterFormatter.summary_text_color)
94
+ return text unless SimpleCovLinterFormatter.summary_enabled_bg
95
+
96
+ text.bg(SimpleCovLinterFormatter.send(bg_option))
97
+ end
98
+
99
+ def build_percentage_output(file)
100
+ percentage_size = file.file_int_percentage.to_s.size
101
+ diff = @largest_percentage - percentage_size
102
+ Rainbow("#{' ' * diff}#{file.file_int_percentage} %").send(
103
+ get_percetage_color(file.file_int_percentage)
104
+ )
105
+ end
106
+
107
+ def get_percetage_color(percentage)
108
+ case percentage
109
+ when 100
110
+ :green
111
+ when 0
112
+ :red
113
+ else
114
+ :yellow
115
+ end
116
+ end
117
+
118
+ def adjusted_file_name(file)
119
+ diff = @largest_file_name - file.file_short_name.size
120
+ file.file_short_name + (" " * diff)
121
+ end
122
+
123
+ def covered_size(file)
124
+ @largest_file_name * file.percentage / 100.0
125
+ end
126
+ end
127
+ end
@@ -5,24 +5,51 @@ module SimpleCovLinterFormatter
5
5
  end
6
6
 
7
7
  def filter
8
- file_content = filter_result
9
- format_result(file_content)
8
+ return [] if text_content == ""
9
+ return filter_with_reviewdog if reviewdog?
10
+
11
+ filter_with_git_status
10
12
  end
11
13
 
12
14
  private
13
15
 
14
- def filter_result
15
- return "" if text_content == ""
16
+ def reviewdog?
17
+ silence_stream($stdout) { !!system("reviewdog --version") }
18
+ end
19
+
20
+ def filter_with_reviewdog
21
+ `echo "#{text_content}" | reviewdog -efm="#{efm_param}" -diff="git diff"`.to_s.split("\n")
22
+ end
23
+
24
+ def efm_param
25
+ %w{%f %l %c %m}.join(SimpleCovLinterFormatter::LINE_SECTIONS_DIVIDER)
26
+ end
27
+
28
+ def filter_with_git_status
29
+ status_files = status_to_lines(`git status --porcelain`)
30
+ regexp = /#{status_files.join('|')}/
31
+ @text_lines.grep(regexp)
32
+ end
16
33
 
17
- `echo "#{text_content}" | reviewdog -efm="%f:%l:%c:%m" -diff="git diff"`
34
+ def status_to_lines(status)
35
+ status.split("\n").map do |change|
36
+ file = change.split(" ").last
37
+ file.end_with?("/") ? nil : file
38
+ end.compact
18
39
  end
19
40
 
20
41
  def text_content
21
- @text_content ||= @text_lines.join('\n')
42
+ @text_content ||= @text_lines.join("\n")
22
43
  end
23
44
 
24
- def format_result(file_content)
25
- file_content.to_s.split("\n")
45
+ def silence_stream(stream)
46
+ old_stream = stream.dup
47
+ stream.reopen(File::NULL)
48
+ stream.sync = true
49
+ yield
50
+ ensure
51
+ stream.reopen(old_stream)
52
+ old_stream.close
26
53
  end
27
54
  end
28
55
  end
@@ -1,3 +1,3 @@
1
1
  module SimpleCovLinterFormatter
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -1,35 +1,89 @@
1
+ require 'rainbow'
2
+
1
3
  require 'simplecov_linter_formatter/version'
4
+ require 'simplecov_linter_formatter/file_line'
2
5
  require 'simplecov_linter_formatter/formatters/result_formatter'
3
6
  require 'simplecov_linter_formatter/formatters/source_file_formatter'
4
7
  require 'simplecov_linter_formatter/formatters/text_lines_formatter'
5
8
  require 'simplecov_linter_formatter/exporters/json_result_exporter'
6
9
  require 'simplecov_linter_formatter/text_lines_filter'
10
+ require 'simplecov_linter_formatter/summary_builder'
7
11
 
8
12
  module SimpleCovLinterFormatter
13
+ extend self
14
+
9
15
  SCOPES = [:all, :own_changes]
16
+ SORTING_MODES = [:coverage, :alphabet]
17
+ MSG_DIVIDER = "-"
18
+ LINE_SECTIONS_DIVIDER = ":"
10
19
 
11
- def self.json_filename=(value)
12
- @json_filename = value
13
- end
20
+ attr_writer(
21
+ :json_filename,
22
+ :summary_covered_bg_color,
23
+ :summary_not_covered_bg_color,
24
+ :summary_text_color,
25
+ :summary_enabled_bg,
26
+ :summary_enabled
27
+ )
14
28
 
15
- def self.json_filename
29
+ def json_filename
16
30
  @json_filename || 'coverage.linter.json'
17
31
  end
18
32
 
19
- def self.cover_all?
33
+ def scope=(value)
34
+ if !SCOPES.include?(value.to_sym)
35
+ raise "Invalid scope. Must be one of: #{SCOPES.map(&:to_s).join(', ')}"
36
+ end
37
+
38
+ @scope = value
39
+ end
40
+
41
+ def scope
42
+ (@scope || :all).to_sym
43
+ end
44
+
45
+ def cover_all?
20
46
  scope == :all
21
47
  end
22
48
 
23
- def self.scope=(value)
24
- if !SCOPES.include?(value)
25
- raise "Invalid scope. Must be one of: #{SCOPES.map(&:to_s).join('', '')}"
49
+ def summary_enabled
50
+ !!@summary_enabled
51
+ end
52
+
53
+ def summary_files_sorting=(value)
54
+ if !SORTING_MODES.include?(value.to_sym)
55
+ raise "Invalid summary_files_sorting. Must be one of: #{SORTING_MODES.map(&:to_s).join(', ')}"
26
56
  end
27
57
 
28
- @scope = value
58
+ @summary_files_sorting = value
59
+ end
60
+
61
+ def summary_files_sorting
62
+ (@summary_files_sorting || :coverage).to_sym
63
+ end
64
+
65
+ def summary_coverage_sorting?
66
+ summary_files_sorting == :coverage
67
+ end
68
+
69
+ def summary_enabled_bg
70
+ !!@summary_enabled_bg
71
+ end
72
+
73
+ def summary_covered_bg_color
74
+ (@summary_covered_bg_color || :darkgreen).to_sym
29
75
  end
30
76
 
31
- def self.scope
32
- @scope || :all
77
+ def summary_not_covered_bg_color
78
+ (@summary_not_covered_bg_color || :firebrick).to_sym
79
+ end
80
+
81
+ def summary_text_color
82
+ (@summary_text_color || :white).to_sym
83
+ end
84
+
85
+ def setup
86
+ yield self
33
87
  end
34
88
  end
35
89
 
@@ -38,6 +92,7 @@ module SimpleCov
38
92
  class LinterFormatter
39
93
  def format(simplecov_result)
40
94
  text_lines = get_text_lines(simplecov_result)
95
+ show_coverage_summary(text_lines)
41
96
  hash_result = format_text_lines(simplecov_result.command_name, text_lines)
42
97
  export_to_json(hash_result)
43
98
  nil
@@ -52,6 +107,12 @@ module SimpleCov
52
107
  filter_text_lines(text_lines)
53
108
  end
54
109
 
110
+ def show_coverage_summary(text_lines)
111
+ return unless SimpleCovLinterFormatter.summary_enabled
112
+
113
+ puts(SimpleCovLinterFormatter::SummaryBuilder.new(text_lines).build)
114
+ end
115
+
55
116
  def filter_text_lines(text_lines)
56
117
  SimpleCovLinterFormatter::TextLinesFilter.new(text_lines).filter
57
118
  end
@@ -17,6 +17,8 @@ Gem::Specification.new do |spec|
17
17
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
18
  spec.require_paths = ["lib"]
19
19
 
20
+ spec.add_dependency "rainbow"
21
+
20
22
  spec.add_development_dependency "bundler", "~> 2.2.15"
21
23
  spec.add_development_dependency "guard-rspec"
22
24
  spec.add_development_dependency "pry"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simplecov_linter_formatter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Platanus
@@ -9,8 +9,22 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2021-09-27 00:00:00.000000000 Z
12
+ date: 2021-10-04 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rainbow
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
14
28
  - !ruby/object:Gem::Dependency
15
29
  name: bundler
16
30
  requirement: !ruby/object:Gem::Requirement
@@ -162,14 +176,22 @@ files:
162
176
  - Rakefile
163
177
  - bin/console
164
178
  - bin/setup
179
+ - docs/assets/all-summary.png
180
+ - docs/assets/colors-summary.png
165
181
  - docs/assets/covered.png
182
+ - docs/assets/no-bg-summary.png
166
183
  - docs/assets/not-covered.png
184
+ - docs/assets/own-changes-summary.png
167
185
  - docs/assets/partial-cov.png
186
+ - docs/assets/report-example.png
187
+ - docs/assets/sorted-summary.png
168
188
  - lib/simplecov_linter_formatter.rb
169
189
  - lib/simplecov_linter_formatter/exporters/json_result_exporter.rb
190
+ - lib/simplecov_linter_formatter/file_line.rb
170
191
  - lib/simplecov_linter_formatter/formatters/result_formatter.rb
171
192
  - lib/simplecov_linter_formatter/formatters/source_file_formatter.rb
172
193
  - lib/simplecov_linter_formatter/formatters/text_lines_formatter.rb
194
+ - lib/simplecov_linter_formatter/summary_builder.rb
173
195
  - lib/simplecov_linter_formatter/text_lines_filter.rb
174
196
  - lib/simplecov_linter_formatter/version.rb
175
197
  - simplecov_linter_formatter.gemspec