Skip to content

Conversation

@ChristopherDedominici
Copy link
Contributor

@ChristopherDedominici ChristopherDedominici commented Oct 8, 2025

Link to internal design doc: https://www.notion.so/nomicfoundation/Code-coverage-HTML-report-286578cdeaf580bcad22db58ce54fb47?source=copy_link

As listed in the design doc, this PR addresses point number 1 out of 3:

  1. create the HTML report
  2. investigate and fix the coverage bug
  3. refactor the code to separate coverage data collection and report generation

TODOs before merge

  • add mention to vendored code

NOTEs for review

  • All the code inside the folder v-next/hardhat-vendored/src/coverage-module has been copied from vendored packages, so there’s no need for a deep review, a quick scan will be sufficient

@changeset-bot
Copy link

changeset-bot bot commented Oct 8, 2025

🦋 Changeset detected

Latest commit: b26e193

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions
Copy link
Contributor

github-actions bot commented Oct 8, 2025

hardhat

Total size of the bundle: 236M
Total number of dependencies (including transitive): 48

List of dependencies (sorted by size)
229M	total
35M	@nomicfoundation/edr-linux-x64-musl
35M	@nomicfoundation/edr-linux-x64-gnu
32M	@nomicfoundation/edr-linux-arm64-musl
32M	@nomicfoundation/edr-linux-arm64-gnu
24M	@nomicfoundation/edr-win32-x64-msvc
24M	@nomicfoundation/edr-darwin-x64
20M	@nomicfoundation/edr-darwin-arm64
7.3M	@sentry/core
5.2M	zod
2.7M	micro-eth-signer
1.9M	@noble/curves
1.7M	undici
1.2M	@noble/hashes
1020K	@nomicfoundation/hardhat-utils
868K	@nomicfoundation/hardhat-vendored
864K	@streamparser/json
624K	micro-packed
592K	tsx
548K	@nomicfoundation/hardhat-errors
492K	@scure/bip39
464K	@nomicfoundation/edr
452K	fast-equals
408K	json-stream-stringify
368K	ethereum-cryptography
332K	@streamparser/json-node
320K	enquirer
320K	@nomicfoundation/hardhat-zod-utils
288K	semver
200K	ws
180K	chokidar
176K	get-tsconfig
168K	@scure/base
160K	esbuild
136K	adm-zip
96K	@scure/bip32
92K	chalk
72K	@nomicfoundation/solidity-analyzer
68K	debug
60K	readdirp
56K	rfdc
48K	ansi-colors
44K	resolve.exports
40K	resolve-pkg-maps
36K	p-map
24K	strip-ansi
24K	env-paths
24K	ansi-regex
20K	ms

@@ -0,0 +1,2 @@
import libCoverage from "./lib-coverage/index.cjs";
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a "bridge" to expose the common js code into ESM js code, so that the ts file can then import it

"pretest": "pnpm build",
"pretest:only": "pnpm build",
"build": "tsc --build .",
"postbuild": "node dist/src/copy-assets.js",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This step is required to copy the assets folder, which contains the CSS and JS files used to generate the report, into the dist folder after compilation

@@ -0,0 +1,33 @@
import { cp } from "node:fs/promises";
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is invoked by the postbuild in the package.json file.

Used to copy the assets folder, which contains the CSS and JS files used to generate the report, into the dist folder after compilation

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm open to better ideas to solve this issue

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested this PR with verdaccio and there were no issues, so this seems to work fine and it's simple enough.

@@ -0,0 +1,13 @@
{
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need a double-check here. I copied the configuration from tsconfig.base.json, but removed all the properties that would cause errors during compilation, since this folder contains non-ESM files

report: Report,
htmlReportPath: string,
): Promise<void> {
const baseDir = process.cwd();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since there is a bug in how we generate coverage data, we currently only display executed and non-executed lines. The line counter is either 1 for executed lines or 0 for non-executed lines:

Image

This will be improved after fixing how we collect coverage data

@ChristopherDedominici ChristopherDedominici marked this pull request as ready for review October 28, 2025 13:36
@ChristopherDedominici ChristopherDedominici moved this from In Progress to In Review in Hardhat Oct 28, 2025
@ChristopherDedominici ChristopherDedominici added the no docs needed This PR doesn't require links to documentation label Nov 3, 2025
@ChristopherDedominici ChristopherDedominici linked an issue Nov 3, 2025 that may be closed by this pull request
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is intentionally empty to prevent build errors and avoid changing the default scripts in package.json

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a comment inside the file.

@ChristopherDedominici ChristopherDedominici changed the title [html coverage report] [html coverage report] Add vendored package + generate HTML report Nov 6, 2025
Comment on lines +2 to +3
"@nomicfoundation/hardhat": minor
"@nomicfoundation/hardhat-vendored": patch
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of things:

  • @nomicfoundation/hardhat should be hardhat
  • The changeset for Hardhat should be patch. I don't think this merits a minor bump.
  • @nomicfoundation/hardhat-vendored is a new package, so it shouldn't be included here. Otherwise its first version will be 3.0.1, not 3.0.0. I checked locally that changeset publish will publish hardhat-vendored even if it doesn't have a changeset, because it detects that it's not published yet. (I'm not entirely sure that the CI will have the same behavior, but I don't see why it wouldn't.)
Suggested change
"@nomicfoundation/hardhat": minor
"@nomicfoundation/hardhat-vendored": patch
"hardhat": patch

await writeUtf8File(lcovReportPath, lcovReport);
log(`Saved lcov report to ${lcovReportPath}`);

const htmlReportPath = path.join(this.#coveragePath, "html");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nyc, jest and vitest all dump the html inside the coverage directory, even when both the HTML and lcov reporters are used together. I personally assume that coverage/index.html will exist and was a bit surprised when it didn't.

I'm not against using a subdirectory for this (in fact, it would be my preference if we were doing this from scratch), but I think it's better to be consistent with other tools here.

Suggested change
const htmlReportPath = path.join(this.#coveragePath, "html");
const htmlReportPath = path.join(this.#coveragePath);

"@nomicfoundation/hardhat-vendored": patch
---

Added HTML coverage reporting and a new internal `hardhat-vendored` package ([7528](https://github.com/NomicFoundation/hardhat/pull/7528)).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changesets shouldn't include implementation details.

Suggested change
Added HTML coverage reporting and a new internal `hardhat-vendored` package ([7528](https://github.com/NomicFoundation/hardhat/pull/7528)).
Added HTML coverage reporting ([7528](https://github.com/NomicFoundation/hardhat/pull/7528)).


const htmlReportPath = path.join(this.#coveragePath, "html");
await this.#writeHtmlReport(report, htmlReportPath);
console.log(`Saved html report to ${htmlReportPath}`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you meant to use a debug log here.

Suggested change
console.log(`Saved html report to ${htmlReportPath}`);
log(`Saved html report to ${htmlReportPath}`);

// Construct coverage data for each tested file,
// detailing whether each line was executed or not.
for (const [p, fileCoverageInput] of Object.entries(report)) {
const testedFilePath = path.isAbsolute(p) ? p : path.join(baseDir, p);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a blocker, but: I am surprised about this. We generate the report, so we should know if the keys are relative or absolute paths. (The Report interface names the key relativePath, so I guess they are meant to be relative).

Another concern is that, if they are relative, it's unclear whether they are relative to the cwd or the project's root (IMO it should be the latter).

Again: I wouldn't do anything in this PR, but this seems like technical debt. Not sure how/if we are capturing those.

coverageMap,
});

reports.create("html", undefined).execute(context);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional parameter with default value.

Suggested change
reports.create("html", undefined).execute(context);
reports.create("html").execute(context);

continue;
}

// TODO: bug line count
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this mean?

"name": "@nomicfoundation/hardhat-vendored",
"version": "3.0.0",
"description": "Internal dependencies used by Hardhat that have been vendored to prevent bloating the main package",
"homepage": "https://github.com/nomicfoundation/hardhat/tree/v-next/v-next/hardhat-vendored",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are not using the v-next branch anymore.

Suggested change
"homepage": "https://github.com/nomicfoundation/hardhat/tree/v-next/v-next/hardhat-vendored",
"homepage": "https://github.com/nomicfoundation/hardhat/tree/main/v-next/hardhat-vendored",

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a comment inside the file.

@@ -0,0 +1,33 @@
import { cp } from "node:fs/promises";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested this PR with verdaccio and there were no issues, so this seems to work fine and it's simple enough.

@fvictorio
Copy link
Member

For the record: the way uncovered code looks is not great:

image

I think this is caused by us using lines instead of statements, or something along those lines. My guess is that we can work our way around this, but I wouldn't do it yet; I'd rather release this sooner.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no docs needed This PR doesn't require links to documentation

Projects

Status: In Review

Development

Successfully merging this pull request may close these issues.

Generate HTML coverage report

4 participants