Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/yellow-lands-kiss.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@nomicfoundation/hardhat-node-test-runner": patch
"@nomicfoundation/hardhat-mocha": patch
"hardhat": patch
---

Add `onTestRunStart`, `onTestWorkerDone`, and `onTestRunDone` test hooks.
13 changes: 12 additions & 1 deletion .peer-bumps.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,16 @@
"v-next/hardhat/templates",
"v-next/config"
],
"bumps": []
"bumps": [
{
"package": "@nomicfoundation/hardhat-mocha",
"peer": "hardhat",
"reason": "It depends on the new TestHooks#onTestRunStart, TestHooks#onTestWorkerDone, and TestHooks#onTestRunDone hooks"
},
{
"package": "@nomicfoundation/hardhat-node-test-runner",
"peer": "hardhat",
"reason": "It depends on the new TestHooks#onTestRunStart, TestHooks#onTestWorkerDone, and TestHooks#onTestRunDone hooks"
}
]
}
3 changes: 1 addition & 2 deletions v-next/hardhat-mocha/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@
"type": "module",
"exports": {
".": "./dist/src/index.js",
"./coverage": "./dist/src/coverage.js",
"./gas-stats": "./dist/src/gas-stats.js"
"./test-worker-done": "./dist/src/test-worker-done.js"
},
"keywords": [
"ethereum",
Expand Down
7 changes: 0 additions & 7 deletions v-next/hardhat-mocha/src/coverage.ts

This file was deleted.

7 changes: 0 additions & 7 deletions v-next/hardhat-mocha/src/gas-stats.ts

This file was deleted.

56 changes: 25 additions & 31 deletions v-next/hardhat-mocha/src/task-action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,6 @@ import { HardhatError } from "@nomicfoundation/hardhat-errors";
import { setGlobalOptionsAsEnvVariables } from "@nomicfoundation/hardhat-utils/env";
import { getAllFilesMatching } from "@nomicfoundation/hardhat-utils/fs";
import debug from "debug";
import {
markTestRunStart as initCoverage,
markTestWorkerDone as saveCoverageData,
markTestRunDone as reportCoverage,
} from "hardhat/internal/coverage";
import {
markTestRunStart as initGasStats,
markTestWorkerDone as saveGasStats,
markTestRunDone as reportGasStats,
} from "hardhat/internal/gas-analytics";

import { createPerformanceTracker } from "./performance.js";

Expand Down Expand Up @@ -121,21 +111,15 @@ const testWithHardhat: NewTaskActionFunction<TestActionArguments> = async (
hre.config.test.mocha.require = hre.config.test.mocha.require ?? [];
hre.config.test.mocha.require.push(unhandledRejectionHook.href);

if (hre.globalOptions.coverage === true) {
const coverage = new URL(
import.meta.resolve("@nomicfoundation/hardhat-mocha/coverage"),
if (
hre.globalOptions.coverage === true ||
hre.globalOptions.gasStats === true
) {
const testWorkerDone = new URL(
import.meta.resolve("@nomicfoundation/hardhat-mocha/test-worker-done"),
);

hre.config.test.mocha.require.push(coverage.href);
}

if (hre.globalOptions.gasStats === true) {
const gasStats = new URL(
import.meta.resolve("@nomicfoundation/hardhat-mocha/gas-stats"),
);

hre.config.test.mocha.require = hre.config.test.mocha.require ?? [];
hre.config.test.mocha.require.push(gasStats.href);
hre.config.test.mocha.require.push(testWorkerDone.href);
}

process.env.NODE_OPTIONS = imports
Expand Down Expand Up @@ -186,8 +170,12 @@ const testWithHardhat: NewTaskActionFunction<TestActionArguments> = async (
perf.endPhase("Test file loading");
perf.startPhase("Test execution");

await initCoverage("mocha");
await initGasStats("mocha");
await hre.hooks.runHandlerChain(
"test",
"onTestRunStart",
["mocha"],
async () => {},
);

let total = 0;
const testFailures = await new Promise<number>((resolve) => {
Expand All @@ -199,13 +187,19 @@ const testWithHardhat: NewTaskActionFunction<TestActionArguments> = async (
perf.startPhase("Reporting");

if (hre.config.test.mocha.parallel !== true) {
// NOTE: We execute mocha tests in the main process.
await saveCoverageData("mocha");
await saveGasStats("mocha");
await hre.hooks.runHandlerChain(
"test",
"onTestWorkerDone",
["mocha"],
async () => {},
);
}
// NOTE: This might print a coverage report.
await reportCoverage("mocha");
await reportGasStats("mocha");
await hre.hooks.runHandlerChain(
"test",
"onTestRunDone",
["mocha"],
async () => {},
);

perf.endPhase("Reporting");

Expand Down
12 changes: 12 additions & 0 deletions v-next/hardhat-mocha/src/test-worker-done.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import hre from "hardhat";

export const mochaHooks = {
async afterAll(): Promise<void> {
await hre.hooks.runHandlerChain(
"test",
"onTestWorkerDone",
["mocha"],
async () => {},
);
},
};
3 changes: 1 addition & 2 deletions v-next/hardhat-node-test-runner/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@
"type": "module",
"exports": {
".": "./dist/src/index.js",
"./coverage": "./dist/src/coverage.js",
"./gas-stats": "./dist/src/gas-stats.js"
"./test-worker-done": "./dist/src/test-worker-done.js"
},
"keywords": [
"ethereum",
Expand Down
7 changes: 0 additions & 7 deletions v-next/hardhat-node-test-runner/src/coverage.ts

This file was deleted.

7 changes: 0 additions & 7 deletions v-next/hardhat-node-test-runner/src/gas-stats.ts

This file was deleted.

43 changes: 19 additions & 24 deletions v-next/hardhat-node-test-runner/src/task-action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,6 @@ import { hardhatTestReporter } from "@nomicfoundation/hardhat-node-test-reporter
import { setGlobalOptionsAsEnvVariables } from "@nomicfoundation/hardhat-utils/env";
import { getAllFilesMatching } from "@nomicfoundation/hardhat-utils/fs";
import { createNonClosingWriter } from "@nomicfoundation/hardhat-utils/stream";
import {
markTestRunStart as initCoverage,
markTestRunDone as reportCoverage,
} from "hardhat/internal/coverage";
import {
markTestRunStart as initGasStats,
markTestRunDone as reportGasStats,
} from "hardhat/internal/gas-analytics";

interface TestActionArguments {
testFiles: string[];
Expand Down Expand Up @@ -92,20 +84,16 @@ const testWithHardhat: NewTaskActionFunction<TestActionArguments> = async (
const tsx = new URL(import.meta.resolve("tsx/esm"));
imports.push(tsx.href);

if (hre.globalOptions.coverage === true) {
const coverage = new URL(
import.meta.resolve("@nomicfoundation/hardhat-node-test-runner/coverage"),
);
imports.push(coverage.href);
}

if (hre.globalOptions.gasStats === true) {
const gasStats = new URL(
if (
hre.globalOptions.coverage === true ||
hre.globalOptions.gasStats === true
) {
const testWorkerDone = new URL(
import.meta.resolve(
"@nomicfoundation/hardhat-node-test-runner/gas-stats",
"@nomicfoundation/hardhat-node-test-runner/test-worker-done",
),
);
imports.push(gasStats.href);
imports.push(testWorkerDone.href);
}

process.env.NODE_OPTIONS = imports
Expand Down Expand Up @@ -191,14 +179,21 @@ const testWithHardhat: NewTaskActionFunction<TestActionArguments> = async (
};
}

await initCoverage("nodejs");
await initGasStats("nodejs");
await hre.hooks.runHandlerChain(
"test",
"onTestRunStart",
["nodejs"],
async () => {},
);

const testResults = await runTests();

// NOTE: This might print a coverage report.
await reportCoverage("nodejs");
await reportGasStats("nodejs");
await hre.hooks.runHandlerChain(
"test",
"onTestRunDone",
["nodejs"],
async () => {},
);

if (testResults.failed > 0) {
process.exitCode = 1;
Expand Down
12 changes: 12 additions & 0 deletions v-next/hardhat-node-test-runner/src/test-worker-done.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { after } from "node:test";

import hre from "hardhat";

after(async () => {
await hre.hooks.runHandlerChain(
"test",
"onTestWorkerDone",
["nodejs"],
async () => {},
);
});
2 changes: 0 additions & 2 deletions v-next/hardhat/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@
"./types/utils": "./dist/src/types/utils.js",
"./types/solidity": "./dist/src/types/solidity.js",
"./console.sol": "./console.sol",
"./internal/coverage": "./dist/src/internal/builtin-plugins/coverage/exports.js",
"./internal/gas-analytics": "./dist/src/internal/builtin-plugins/gas-analytics/exports.js",
"./utils/contract-names": "./dist/src/utils/contract-names.js",
"./types/runtime": "./dist/src/internal/deprecated-module-imported-from-hardhat2-plugin.js",
"./builtin-tasks/task-names": "./dist/src/internal/deprecated-module-imported-from-hardhat2-plugin.js",
Expand Down

This file was deleted.

45 changes: 0 additions & 45 deletions v-next/hardhat/src/internal/builtin-plugins/coverage/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,5 @@
import path from "node:path";

import { assertHardhatInvariant } from "@nomicfoundation/hardhat-errors";

import { HardhatRuntimeEnvironmentImplementation } from "../../core/hre.js";

export function getCoveragePath(rootPath: string): string {
return path.join(rootPath, "coverage");
}

/**
* NOTE: The following helpers interact with the global HRE instance only;
* This is OK because:
* - They are intended for the internal use only. They are exposed via the
* internal public API only.
* - We know the HRE has been initialized by the time they are used.
*/

export async function markTestRunStart(id: string): Promise<void> {
const { default: hre } = await import("../../../index.js");
if (hre.globalOptions.coverage === true) {
assertHardhatInvariant(
hre instanceof HardhatRuntimeEnvironmentImplementation,
"Expected HRE to be an instance of HardhatRuntimeEnvironmentImplementation",
);
await hre._coverage.clearData(id);
}
}

export async function markTestWorkerDone(id: string): Promise<void> {
const { default: hre } = await import("../../../index.js");
if (hre.globalOptions.coverage === true) {
assertHardhatInvariant(
hre instanceof HardhatRuntimeEnvironmentImplementation,
"Expected HRE to be an instance of HardhatRuntimeEnvironmentImplementation",
);
await hre._coverage.saveData(id);
}
}

export async function markTestRunDone(id: string): Promise<void> {
const { default: hre } = await import("../../../index.js");
if (hre.globalOptions.coverage === true) {
assertHardhatInvariant(
hre instanceof HardhatRuntimeEnvironmentImplementation,
"Expected HRE to be an instance of HardhatRuntimeEnvironmentImplementation",
);
await hre._coverage.report(id);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import type { TestHooks } from "../../../../types/hooks.js";

import { assertHardhatInvariant } from "@nomicfoundation/hardhat-errors";

import { HardhatRuntimeEnvironmentImplementation } from "../../../core/hre.js";

export default async (): Promise<Partial<TestHooks>> => ({
onTestRunStart: async (context, id, next) => {
await next(context, id);

if (context.globalOptions.coverage === true) {
assertHardhatInvariant(
context instanceof HardhatRuntimeEnvironmentImplementation,
"Expected context to be an instance of HardhatRuntimeEnvironmentImplementation",
);
await context._coverage.clearData(id);
}
},

onTestWorkerDone: async (context, id, next) => {
await next(context, id);

if (context.globalOptions.coverage === true) {
assertHardhatInvariant(
context instanceof HardhatRuntimeEnvironmentImplementation,
"Expected context to be an instance of HardhatRuntimeEnvironmentImplementation",
);
await context._coverage.saveData(id);
}
},

onTestRunDone: async (context, id, next) => {
await next(context, id);

if (context.globalOptions.coverage === true) {
assertHardhatInvariant(
context instanceof HardhatRuntimeEnvironmentImplementation,
"Expected context to be an instance of HardhatRuntimeEnvironmentImplementation",
);
await context._coverage.report(id);
}
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const hardhatPlugin: HardhatPlugin = {
clean: () => import("./hook-handlers/clean.js"),
hre: () => import("./hook-handlers/hre.js"),
solidity: () => import("./hook-handlers/solidity.js"),
test: () => import("./hook-handlers/test.js"),
},
npmPackage: "hardhat",
};
Expand Down

This file was deleted.

Loading
Loading