123456789_123456789_123456789_123456789_123456789_

Class: SimpleCov::Formatter::HTMLFormatter

Relationships & Source Files
Inherits: Object
Defined in: lib/simplecov/formatter/html_formatter.rb

Overview

Generates an HTML coverage report by writing a coverage_data.js file alongside pre-compiled static assets (index.html, application.js/css). Uses JSONFormatter.build_hash to serialize the result, then writes both coverage.json and coverage_data.js from the same in-memory hash.

Constant Summary

Class Method Summary

Instance Method Summary

Constructor Details

.new(silent: false, output_dir: nil) ⇒ HTMLFormatter

output_dir defaults to SimpleCov.coverage_path so the at_exit pipeline keeps working unchanged. Pass it explicitly to write somewhere else (handy for tests that don't want to clobber the project's coverage/ directory).

[ GitHub ]

  
# File 'lib/simplecov/formatter/html_formatter.rb', line 20

def initialize(silent: false, output_dir: nil)
  @silent = silent
  @output_dir = output_dir
end

Instance Method Details

#atomic_write(dest, content) (private)

Write content at dest via a uniquely-named temp file in the same directory, then File.rename onto the final path. rename is atomic and overwrite-safe, so:

  • parallel writers can't race on an unlink-then-write window, and
  • read-only existing files (e.g. assets shipped at 0444 from /nix/store) are replaced cleanly instead of triggering EACCES from opening the existing path for writing.
[ GitHub ]

  
# File 'lib/simplecov/formatter/html_formatter.rb', line 60

def atomic_write(dest, content)
  temp = "#{dest}.#{Process.pid}.#{rand(2**32).to_s(36)}"
  File.binwrite(temp, content)
  File.rename(temp, dest)
ensure
  FileUtils.rm_f(temp)
end

#copy_static_assets(dest_dir = output_path) (private)

[ GitHub ]

  
# File 'lib/simplecov/formatter/html_formatter.rb', line 47

def copy_static_assets(dest_dir = output_path)
  Dir[File.join(public_dir, "*")].each do |src|
    atomic_write(File.join(dest_dir, File.basename(src)), File.binread(src))
  end
end

#format(result)

[ GitHub ]

  
# File 'lib/simplecov/formatter/html_formatter.rb', line 25

def format(result)
  json = JSON.pretty_generate(JSONFormatter.build_hash(result))

  FileUtils.mkdir_p(output_path)
  atomic_write(File.join(output_path, JSONFormatter::FILENAME), json)
  atomic_write(File.join(output_path, DATA_FILENAME), "window.SIMPLECOV_DATA = #{json};\n")

  copy_static_assets
  puts output_message(result) unless @silent
end

#format_from_json(json_path, output_dir)

Generate HTML from a pre-existing coverage.json file without needing a live ::SimpleCov::Result or even a running test suite.

[ GitHub ]

  
# File 'lib/simplecov/formatter/html_formatter.rb', line 38

def format_from_json(json_path, output_dir)
  FileUtils.mkdir_p(output_dir)
  json = File.read(json_path)
  atomic_write(File.join(output_dir, DATA_FILENAME), "window.SIMPLECOV_DATA = #{json};\n")
  copy_static_assets(output_dir)
end

#output_message(result) (private)

[ GitHub ]

  
# File 'lib/simplecov/formatter/html_formatter.rb', line 68

def output_message(result)
  "Coverage report generated for #{result.command_name} to #{output_path}. " \
    "#{result.covered_lines} / #{result.total_lines} LOC " \
    "(#{SimpleCov.round_coverage(result.covered_percent)}%) covered."
end

#output_path (private)

[ GitHub ]

  
# File 'lib/simplecov/formatter/html_formatter.rb', line 74

def output_path
  @output_dir || SimpleCov.coverage_path
end

#public_dir (private)

[ GitHub ]

  
# File 'lib/simplecov/formatter/html_formatter.rb', line 78

def public_dir
  File.join(__dir__, "html_formatter/public/")
end