Module: SimpleCov::CLI::Report

Extended by:
CommandHelpers
Defined in:
lib/simplecov/cli/report.rb

Overview

simplecov report [--input PATH] — pretty-print the overall totals row plus per-group totals from a JSONFormatter coverage.json. Same numbers as the HTML report's totals row, for contexts where opening a browser isn't an option (CI logs, ssh sessions, terminal-only workflows).

Constant Summary collapse

TOTAL_LABEL =
"All Files"
SECTIONS =
[%w[Line lines], %w[Branch branches], %w[Method methods]].freeze

Constants included from CommandHelpers

CommandHelpers::STATS_ROW_FORMAT

Class Method Summary collapse

Methods included from CommandHelpers

command_name, common_options, error, parse_common, stats_row

Class Method Details

.collect_section(totals) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
# File 'lib/simplecov/cli/report.rb', line 84

def collect_section(totals)
  sections = {} #: Hash[String, untyped]
  SECTIONS.each_with_object(sections) do |(_, key), out|
    section = totals[key]
    next unless section.is_a?(Hash) && section["total"].to_i.positive?

    out[key.to_s] = {
      "percent" => section["percent"], "covered" => section["covered"], "total" => section["total"]
    }
  end
end

.emit_json(stdout, data) ⇒ Object



77
78
79
80
81
82
# File 'lib/simplecov/cli/report.rb', line 77

def emit_json(stdout, data)
  none = {} #: Hash[String, untyped]
  groups = data.fetch("groups", none).transform_values { |group| collect_section(group) }
  payload = {"total" => collect_section(data.fetch("total", none)), "groups" => groups}
  stdout.puts(JSON.pretty_generate(payload))
end

.emit_section(stdout, display, section, color) ⇒ Object



68
69
70
71
72
73
74
75
# File 'lib/simplecov/cli/report.rb', line 68

def emit_section(stdout, display, section, color)
  return unless section.is_a?(Hash) && section["total"].to_i.positive?

  stdout.puts(stats_row(display,
                        SimpleCov::Color.colorize_percent(section["percent"].to_f, enabled: color),
                        section["covered"],
                        section["total"]))
end

.emit_text(stdout, data, color) ⇒ Object



53
54
55
56
57
58
59
60
# File 'lib/simplecov/cli/report.rb', line 53

def emit_text(stdout, data, color)
  none = {} #: Hash[String, untyped]
  emit_totals(stdout, TOTAL_LABEL, data.fetch("total", none), color)
  data.fetch("groups", none).each do |name, group|
    label = name == TOTAL_LABEL ? "#{name} (group)" : name
    emit_totals(stdout, label, group, color)
  end
end

.emit_totals(stdout, label, totals, color) ⇒ Object



62
63
64
65
66
# File 'lib/simplecov/cli/report.rb', line 62

def emit_totals(stdout, label, totals, color)
  stdout.puts(label)
  SECTIONS.each { |display, key| emit_section(stdout, display, totals[key], color) }
  stdout.puts
end

.load_data(input, stderr) ⇒ Object

Valid JSON isn't enough: a wrong-typed "total" or "groups" (or a wrong-typed group entry) used to escape here and crash the emitters with a backtrace instead of the one-line error the sibling commands print.



38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/simplecov/cli/report.rb', line 38

def load_data(input, stderr)
  data = CoverageFile.load_document(input, command: "report", stderr: stderr)
  return unless data

  none = {} #: Hash[String, untyped]
  unless data.fetch("total", none).is_a?(Hash)
    return CoverageFile.report_invalid(stderr, "report", input, '"total" must be an object')
  end

  groups = data.fetch("groups", none)
  return data if groups.is_a?(Hash) && groups.each_value.all?(Hash)

  CoverageFile.report_invalid(stderr, "report", input, '"groups" must be an object of objects')
end

.run(args, stdout:, stderr:) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
# File 'lib/simplecov/cli/report.rb', line 22

def run(args, stdout:, stderr:)
  opts, = parse_common(args)
  return 1 unless (data = load_data(opts[:input], stderr))

  if opts[:json]
    emit_json(stdout, data)
  else
    emit_text(stdout, data, SimpleCov::CLI.color_enabled?(opts, stdout))
  end
  0
end