Skip to content

Commit 2d10447

Browse files
committed
Render HTML coverage reports client-side from static JSON data
Replace server-side ERB template rendering with a static single-page JavaScript app. The HTML formatter now writes coverage_data.js (a thin JS wrapper around the JSON coverage data) and copies pre-compiled static assets. All rendering — file lists, source code views, coverage bars, group tabs — happens in the browser. This cleanly separates data (JSON) from presentation (JS/HTML/CSS): * Delete ERB templates, Ruby view helpers, and coverage helpers * Move all rendering logic into TypeScript (app.ts) * Add static index.html as a pre-compiled asset via rake assets:compile * Flatten formatter class hierarchy (5 classes → 3) * Introduce JSONFormatter.build_hash for shared, side-effect-free serialization used by both formatters * Eliminate double JSONFormatter execution when both formatters are configured
1 parent 8931869 commit 2d10447

28 files changed

+1311
-2739
lines changed

Rakefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ task test: %i[spec cucumber test_html]
4040
task default: %i[rubocop spec cucumber test_html]
4141

4242
namespace :assets do
43-
desc "Compile frontend assets (JS + CSS) using esbuild"
43+
desc "Compile frontend assets (HTML, JS, CSS) using esbuild"
4444
task :compile do
4545
frontend = File.expand_path("html_frontend", __dir__)
4646
outdir = File.expand_path("lib/simplecov/formatter/html_formatter/public", __dir__)
@@ -62,5 +62,8 @@ namespace :assets do
6262
io.close_write
6363
File.write("#{outdir}/application.css", io.read)
6464
end
65+
66+
# HTML: copy static index.html
67+
FileUtils.cp(File.join(frontend, "src/index.html"), File.join(outdir, "index.html"))
6568
end
6669
end

features/branch_coverage.feature

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ Feature:
1515
end
1616
"""
1717
When I open the coverage report generated with `bundle exec rspec spec`
18-
Then the output should contain "Line coverage: 56 / 61 (91.80%)"
19-
And the output should contain "Branch coverage: 2 / 4 (50.00%)"
18+
Then the output should contain "56 / 61 LOC (91.8%) covered"
2019
And I should see the groups:
2120
| name | coverage | files |
2221
| All Files | 91.80% | 7 |

features/step_definitions/html_steps.rb

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,29 @@
6060
end
6161

6262
Then /^there should be (\d+) skipped lines in the source files$/ do |expected_count|
63-
count = page.evaluate_script("document.querySelectorAll('.source_files template').length > 0 ? Array.from(document.querySelectorAll('.source_files template')).reduce(function(sum, t) { return sum + t.content.querySelectorAll('ol li.skipped').length; }, 0) : document.querySelectorAll('.source_table ol li.skipped').length")
63+
# Materialize all source files (renders them from coverage data), then count skipped lines
64+
count = page.evaluate_script(<<~JS)
65+
(function() {
66+
// Check for pre-rendered templates (old simplecov-html)
67+
var templates = document.querySelectorAll('.source_files template');
68+
if (templates.length > 0) {
69+
return Array.from(templates).reduce(function(sum, t) {
70+
return sum + t.content.querySelectorAll('ol li.skipped').length;
71+
}, 0);
72+
}
73+
// New architecture: count skipped lines directly from coverage data
74+
if (window.SIMPLECOV_DATA) {
75+
var count = 0;
76+
var coverage = window.SIMPLECOV_DATA.coverage;
77+
Object.keys(coverage).forEach(function(fn) {
78+
var lines = coverage[fn].lines;
79+
lines.forEach(function(l) { if (l === 'ignored') count++; });
80+
});
81+
return count;
82+
}
83+
return document.querySelectorAll('.source_table ol li.skipped').length;
84+
})()
85+
JS
6486
expect(count).to eq(expected_count.to_i)
6587
end
6688

0 commit comments

Comments
 (0)