File: simplecov-html.rb

package info (click to toggle)
ruby-simplecov-html 0.13.2-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 868 kB
  • sloc: javascript: 6,193; ruby: 128; makefile: 15
file content (164 lines) | stat: -rw-r--r-- 5,493 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# frozen_string_literal: true

require "erb"
require "fileutils"
require "digest/sha1"
require "time"

# Ensure we are using a compatible version of SimpleCov
major, minor, patch = SimpleCov::VERSION.scan(/\d+/).first(3).map(&:to_i)
if major < 0 || minor < 9 || patch < 0
  raise "The version of SimpleCov you are using is too old. " \
        "Please update with `gem install simplecov` or `bundle update simplecov`"
end

module SimpleCov
  module Formatter
    class HTMLFormatter
      # Only have a few content types, just hardcode them
      CONTENT_TYPES = {
        ".js" => "text/javascript",
        ".png" => "image/png",
        ".gif" => "image/gif",
        ".css" => "text/css",
      }.freeze

      def initialize
        @branchable_result = SimpleCov.branch_coverage?
        @templates = {}
        @inline_assets = !ENV["SIMPLECOV_INLINE_ASSETS"].nil?
        @public_assets_dir = File.join('/usr/share/ruby-simplecov-html/public/')
      end

      def format(result)
        unless @inline_assets
          Dir[File.join(@public_assets_dir, "*")].each do |path|
            FileUtils.cp_r(path, asset_output_path, remove_destination: true)
          end
        end

        File.open(File.join(output_path, "index.html"), "wb") do |file|
          file.puts template("layout").result(binding)
        end
        puts output_message(result)
      end

    private

      def branchable_result?
        # cached in initialize because we truly look it up a whole bunch of times
        # and it's easier to cache here then in SimpleCov because there we might
        # still enable/disable branch coverage criterion
        @branchable_result
      end

      def line_status?(source_file, line)
        if branchable_result? && source_file.line_with_missed_branch?(line.number)
          "missed-branch"
        else
          line.status
        end
      end

      def output_message(result)
        output = "Coverage report generated for #{result.command_name} to #{output_path}."
        output += "\nLine Coverage: #{result.covered_percent.round(2)}% (#{result.covered_lines} / #{result.total_lines})"
        output += "\nBranch Coverage: #{result.coverage_statistics[:branch].percent.round(2)}% (#{result.covered_branches} / #{result.total_branches})" if branchable_result?
        output
      end

      # Returns the an erb instance for the template of given name
      def template(name)
        @templates[name] ||= ERB.new(File.read(File.join('/usr/share/ruby-simplecov-html/views/', "#{name}.erb")))
      end

      def output_path
        SimpleCov.coverage_path
      end

      def asset_output_path
        return @asset_output_path if defined?(@asset_output_path) && @asset_output_path

        @asset_output_path = File.join(output_path, "assets", SimpleCov::Formatter::HTMLFormatter::VERSION)
        FileUtils.mkdir_p(@asset_output_path)
        @asset_output_path
      end

      def assets_path(name)
        return asset_inline(name) if @inline_assets

        File.join("./assets", SimpleCov::Formatter::HTMLFormatter::VERSION, name)
      end

      def asset_inline(name)
        path = File.join(@public_assets_dir, name)
        # Equivalent to `Base64.strict_encode64(File.read(path))` but without depending on Base64
        base64_content = [File.read(path)].pack("m0")

        content_type = CONTENT_TYPES[File.extname(name)]

        "data:#{content_type};base64,#{base64_content}"
      end

      # Returns the html for the given source_file
      def formatted_source_file(source_file)
        template("source_file").result(binding)
      rescue Encoding::CompatibilityError => e
        puts "Encoding problems with file #{source_file.filename}. Simplecov/ERB can't handle non ASCII characters in filenames. Error: #{e.message}."
      end

      # Returns a table containing the given source files
      def formatted_file_list(title, source_files)
        title_id = title.gsub(/^[^a-zA-Z]+/, "").gsub(/[^a-zA-Z0-9\-_]/, "")
        # Silence a warning by using the following variable to assign to itself:
        # "warning: possibly useless use of a variable in void context"
        # The variable is used by ERB via binding.
        title_id = title_id # rubocop:disable Lint/SelfAssignment
        template("file_list").result(binding)
      end

      def covered_percent(percent)
        template("covered_percent").result(binding)
      end

      def coverage_css_class(covered_percent)
        if covered_percent > 90
          "green"
        elsif covered_percent > 80
          "yellow"
        else
          "red"
        end
      end

      def strength_css_class(covered_strength)
        if covered_strength > 1
          "green"
        elsif covered_strength == 1
          "yellow"
        else
          "red"
        end
      end

      # Return a (kind of) unique id for the source file given. Uses SHA1 on path for the id
      def id(source_file)
        Digest::SHA1.hexdigest(source_file.filename)
      end

      def timeago(time)
        "<abbr class=\"timeago\" title=\"#{time.iso8601}\">#{time.iso8601}</abbr>"
      end

      def shortened_filename(source_file)
        source_file.filename.sub(SimpleCov.root, ".").gsub(/^\.\//, "")
      end

      def link_to_source_file(source_file)
        %(<a href="##{id source_file}" class="src_link" title="#{shortened_filename source_file}">#{shortened_filename source_file}</a>)
      end
    end
  end
end

require "simplecov-html/version"