Skip to content

Commit

Permalink
Add main formatter
Browse files Browse the repository at this point in the history
  • Loading branch information
gondalez committed Aug 20, 2024
1 parent 24c0ca0 commit 520c8ab
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/simplecov/inline.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require_relative 'inline/version'
require_relative 'inline/formatter'

module SimpleCov
module Inline
Expand Down
101 changes: 101 additions & 0 deletions lib/simplecov/inline/formatter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
module Simplecov
module Inline
class Formatter
Result = Struct.new(:file, :start_line, :end_line, :type) do
def to_s
lines = [start_line, end_line].uniq.join('-')
"#{file}:#{lines} (#{type})"
end
end

Config = Struct.new(:files) do
def no_output!(reason:)
@no_output = reason
end

attr_reader :no_output
end

@config = Config.new

def self.config(&block)
return @config if block.nil?

block.call(@config)

return if @config.files.nil?

@config.files = @config.files.to_set.freeze
end

def format(result, putter: Kernel)
missing_coverage = process_files(filtered_files(result:).reject { |file| fully_covered?(file) })
success_message = build_success_message(missing_coverage:)

if success_message
putter.puts success_message
return
end

putter.puts
putter.puts 'Missing coverage:'.yellow
putter.puts missing_coverage.yellow
putter.puts
end

private

def build_success_message(missing_coverage:)
return "Coverage output skipped. Reason: #{self.class.config.no_output}.".yellow if self.class.config.no_output
return "All branches covered (#{human_filter} files) ✔ ".green if missing_coverage.empty?

nil
end

def fully_covered?(file)
[file.covered_percent, file.branches_coverage_percent].all? { |coverage| coverage == 100 }
end

def human_filter
self.class.config.files&.length || 'all'
end

def filtered_files(result:)
filter = self.class.config.files

return result.files if filter.nil?

result.files.filter { |file| filter.include?(file.filename) }
end

def process_files(files)
files.map do |file|
[
build_line_coverage(file),
build_branch_coverage(file),
]
end.flatten.compact.join("\n")
end

def build_line_coverage(file)
file.missed_lines.each_with_object([]) do |uncovered, object|
# uncovered is a SimpleCov::SourceFile::Line
cursor = object.last

if cursor&.end_line == uncovered.line_number - 1
cursor.end_line = uncovered.line_number
else
object.push(Result.new(file.project_filename, uncovered.line_number, uncovered.line_number, 'line'))
end
end
end

def build_branch_coverage(file)
file.missed_branches.map do |uncovered|
# uncovered is a SimpleCov::SourceFile::Branch
Result.new(file.project_filename, uncovered.report_line, uncovered.report_line, "branch:#{uncovered.type}")
end
end
end
end
end
36 changes: 36 additions & 0 deletions spec/lib/simplecov/inline/formatter_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
RSpec.describe Simplecov::Inline::Formatter do
describe '#format' do
subject { described_class.new.format(result, putter:) }

let(:result) do
SimpleCov::Result.new({
'file1.rb' => {'lines' => [nil, 1, 1]},
'file2.rb' => {'lines' => [1, nil]},
})
end

let(:putter) { instance_double(Kernel) }

before { allow(putter).to receive(:puts) }

it 'outputs missing lines and branches' do
subject

expect(putter).to have_received('Missing coverage:')
end
end

describe '.config' do
subject { described_class.config }

it { is_expected.to have_attributes files: nil }
it { is_expected.to respond_to :no_output! }

it 'can change the files' do
expect { described_class.config { |config| config.files = ['test.txt'] } }
.to change { described_class.config.files }
.from(nil)
.to(['test.txt'])
end
end
end

0 comments on commit 520c8ab

Please sign in to comment.