diff --git a/.changeset/yellow-lands-kiss.md b/.changeset/yellow-lands-kiss.md new file mode 100644 index 00000000000..a0eabbc88c9 --- /dev/null +++ b/.changeset/yellow-lands-kiss.md @@ -0,0 +1,7 @@ +--- +"@nomicfoundation/hardhat-node-test-runner": patch +"@nomicfoundation/hardhat-mocha": patch +"hardhat": patch +--- + +Add `onTestRunStart`, `onTestWorkerDone`, and `onTestRunDone` test hooks. diff --git a/.peer-bumps.json b/.peer-bumps.json index 5ed8663a7f8..6855ae19351 100644 --- a/.peer-bumps.json +++ b/.peer-bumps.json @@ -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" + } + ] } diff --git a/v-next/hardhat-mocha/package.json b/v-next/hardhat-mocha/package.json index c89efe4005f..36d263f1a7d 100644 --- a/v-next/hardhat-mocha/package.json +++ b/v-next/hardhat-mocha/package.json @@ -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", diff --git a/v-next/hardhat-mocha/src/coverage.ts b/v-next/hardhat-mocha/src/coverage.ts deleted file mode 100644 index 0cd0b09250c..00000000000 --- a/v-next/hardhat-mocha/src/coverage.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { markTestWorkerDone } from "hardhat/internal/coverage"; - -export const mochaHooks = { - async afterAll(): Promise { - await markTestWorkerDone("mocha"); - }, -}; diff --git a/v-next/hardhat-mocha/src/gas-stats.ts b/v-next/hardhat-mocha/src/gas-stats.ts deleted file mode 100644 index ad0b0a497fc..00000000000 --- a/v-next/hardhat-mocha/src/gas-stats.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { markTestWorkerDone } from "hardhat/internal/gas-analytics"; - -export const mochaHooks = { - async afterAll(): Promise { - await markTestWorkerDone("mocha"); - }, -}; diff --git a/v-next/hardhat-mocha/src/task-action.ts b/v-next/hardhat-mocha/src/task-action.ts index 1343d03efb8..fd405a42d56 100644 --- a/v-next/hardhat-mocha/src/task-action.ts +++ b/v-next/hardhat-mocha/src/task-action.ts @@ -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"; @@ -121,21 +111,15 @@ const testWithHardhat: NewTaskActionFunction = 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 @@ -186,8 +170,12 @@ const testWithHardhat: NewTaskActionFunction = 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((resolve) => { @@ -199,13 +187,19 @@ const testWithHardhat: NewTaskActionFunction = 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"); diff --git a/v-next/hardhat-mocha/src/test-worker-done.ts b/v-next/hardhat-mocha/src/test-worker-done.ts new file mode 100644 index 00000000000..0c869cd8e13 --- /dev/null +++ b/v-next/hardhat-mocha/src/test-worker-done.ts @@ -0,0 +1,12 @@ +import hre from "hardhat"; + +export const mochaHooks = { + async afterAll(): Promise { + await hre.hooks.runHandlerChain( + "test", + "onTestWorkerDone", + ["mocha"], + async () => {}, + ); + }, +}; diff --git a/v-next/hardhat-node-test-runner/package.json b/v-next/hardhat-node-test-runner/package.json index b5f31315bdc..c07f3f49610 100644 --- a/v-next/hardhat-node-test-runner/package.json +++ b/v-next/hardhat-node-test-runner/package.json @@ -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", diff --git a/v-next/hardhat-node-test-runner/src/coverage.ts b/v-next/hardhat-node-test-runner/src/coverage.ts deleted file mode 100644 index d1f5a35d7ec..00000000000 --- a/v-next/hardhat-node-test-runner/src/coverage.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { after } from "node:test"; - -import { markTestWorkerDone } from "hardhat/internal/coverage"; - -after(async () => { - await markTestWorkerDone("nodejs"); -}); diff --git a/v-next/hardhat-node-test-runner/src/gas-stats.ts b/v-next/hardhat-node-test-runner/src/gas-stats.ts deleted file mode 100644 index ce2fb75ebd0..00000000000 --- a/v-next/hardhat-node-test-runner/src/gas-stats.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { after } from "node:test"; - -import { markTestWorkerDone } from "hardhat/internal/gas-analytics"; - -after(async () => { - await markTestWorkerDone("nodejs"); -}); diff --git a/v-next/hardhat-node-test-runner/src/task-action.ts b/v-next/hardhat-node-test-runner/src/task-action.ts index 29526387a21..c1a22b76107 100644 --- a/v-next/hardhat-node-test-runner/src/task-action.ts +++ b/v-next/hardhat-node-test-runner/src/task-action.ts @@ -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[]; @@ -92,20 +84,16 @@ const testWithHardhat: NewTaskActionFunction = 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 @@ -191,14 +179,21 @@ const testWithHardhat: NewTaskActionFunction = 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; diff --git a/v-next/hardhat-node-test-runner/src/test-worker-done.ts b/v-next/hardhat-node-test-runner/src/test-worker-done.ts new file mode 100644 index 00000000000..ad4e60b8a39 --- /dev/null +++ b/v-next/hardhat-node-test-runner/src/test-worker-done.ts @@ -0,0 +1,12 @@ +import { after } from "node:test"; + +import hre from "hardhat"; + +after(async () => { + await hre.hooks.runHandlerChain( + "test", + "onTestWorkerDone", + ["nodejs"], + async () => {}, + ); +}); diff --git a/v-next/hardhat/package.json b/v-next/hardhat/package.json index dbe90feaf54..0011d701846 100644 --- a/v-next/hardhat/package.json +++ b/v-next/hardhat/package.json @@ -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", diff --git a/v-next/hardhat/src/internal/builtin-plugins/coverage/exports.ts b/v-next/hardhat/src/internal/builtin-plugins/coverage/exports.ts deleted file mode 100644 index 021edb014d4..00000000000 --- a/v-next/hardhat/src/internal/builtin-plugins/coverage/exports.ts +++ /dev/null @@ -1,5 +0,0 @@ -export { - markTestRunStart, - markTestRunDone, - markTestWorkerDone, -} from "./helpers.js"; diff --git a/v-next/hardhat/src/internal/builtin-plugins/coverage/helpers.ts b/v-next/hardhat/src/internal/builtin-plugins/coverage/helpers.ts index bfbb5d23846..f45f2dcb731 100644 --- a/v-next/hardhat/src/internal/builtin-plugins/coverage/helpers.ts +++ b/v-next/hardhat/src/internal/builtin-plugins/coverage/helpers.ts @@ -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 { - 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 { - 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 { - 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); - } -} diff --git a/v-next/hardhat/src/internal/builtin-plugins/coverage/hook-handlers/test.ts b/v-next/hardhat/src/internal/builtin-plugins/coverage/hook-handlers/test.ts new file mode 100644 index 00000000000..08f8fb9c7ea --- /dev/null +++ b/v-next/hardhat/src/internal/builtin-plugins/coverage/hook-handlers/test.ts @@ -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> => ({ + 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); + } + }, +}); diff --git a/v-next/hardhat/src/internal/builtin-plugins/coverage/index.ts b/v-next/hardhat/src/internal/builtin-plugins/coverage/index.ts index c902a8e7d96..7ff67358d34 100644 --- a/v-next/hardhat/src/internal/builtin-plugins/coverage/index.ts +++ b/v-next/hardhat/src/internal/builtin-plugins/coverage/index.ts @@ -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", }; diff --git a/v-next/hardhat/src/internal/builtin-plugins/gas-analytics/exports.ts b/v-next/hardhat/src/internal/builtin-plugins/gas-analytics/exports.ts deleted file mode 100644 index 021edb014d4..00000000000 --- a/v-next/hardhat/src/internal/builtin-plugins/gas-analytics/exports.ts +++ /dev/null @@ -1,5 +0,0 @@ -export { - markTestRunStart, - markTestRunDone, - markTestWorkerDone, -} from "./helpers.js"; diff --git a/v-next/hardhat/src/internal/builtin-plugins/gas-analytics/helpers.ts b/v-next/hardhat/src/internal/builtin-plugins/gas-analytics/helpers.ts deleted file mode 100644 index 5cb8da3907b..00000000000 --- a/v-next/hardhat/src/internal/builtin-plugins/gas-analytics/helpers.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { assertHardhatInvariant } from "@nomicfoundation/hardhat-errors"; - -import { HardhatRuntimeEnvironmentImplementation } from "../../core/hre.js"; - -/** - * 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 { - const { default: hre } = await import("../../../index.js"); - if (hre.globalOptions.gasStats === true) { - assertHardhatInvariant( - hre instanceof HardhatRuntimeEnvironmentImplementation, - "Expected HRE to be an instance of HardhatRuntimeEnvironmentImplementation", - ); - await hre._gasAnalytics.clearGasMeasurements(id); - } -} - -export async function markTestWorkerDone(id: string): Promise { - const { default: hre } = await import("../../../index.js"); - if (hre.globalOptions.gasStats === true) { - assertHardhatInvariant( - hre instanceof HardhatRuntimeEnvironmentImplementation, - "Expected HRE to be an instance of HardhatRuntimeEnvironmentImplementation", - ); - await hre._gasAnalytics.saveGasMeasurements(id); - } -} - -export async function markTestRunDone(id: string): Promise { - const { default: hre } = await import("../../../index.js"); - if (hre.globalOptions.gasStats === true) { - assertHardhatInvariant( - hre instanceof HardhatRuntimeEnvironmentImplementation, - "Expected HRE to be an instance of HardhatRuntimeEnvironmentImplementation", - ); - await hre._gasAnalytics.reportGasStats(id); - } -} diff --git a/v-next/hardhat/src/internal/builtin-plugins/gas-analytics/hook-handlers/test.ts b/v-next/hardhat/src/internal/builtin-plugins/gas-analytics/hook-handlers/test.ts new file mode 100644 index 00000000000..99700f37fd1 --- /dev/null +++ b/v-next/hardhat/src/internal/builtin-plugins/gas-analytics/hook-handlers/test.ts @@ -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> => ({ + onTestRunStart: async (context, id, next) => { + await next(context, id); + + if (context.globalOptions.gasStats === true) { + assertHardhatInvariant( + context instanceof HardhatRuntimeEnvironmentImplementation, + "Expected context to be an instance of HardhatRuntimeEnvironmentImplementation", + ); + await context._gasAnalytics.clearGasMeasurements(id); + } + }, + + onTestWorkerDone: async (context, id, next) => { + await next(context, id); + + if (context.globalOptions.gasStats === true) { + assertHardhatInvariant( + context instanceof HardhatRuntimeEnvironmentImplementation, + "Expected context to be an instance of HardhatRuntimeEnvironmentImplementation", + ); + await context._gasAnalytics.saveGasMeasurements(id); + } + }, + + onTestRunDone: async (context, id, next) => { + await next(context, id); + + if (context.globalOptions.gasStats === true) { + assertHardhatInvariant( + context instanceof HardhatRuntimeEnvironmentImplementation, + "Expected context to be an instance of HardhatRuntimeEnvironmentImplementation", + ); + await context._gasAnalytics.reportGasStats(id); + } + }, +}); diff --git a/v-next/hardhat/src/internal/builtin-plugins/gas-analytics/index.ts b/v-next/hardhat/src/internal/builtin-plugins/gas-analytics/index.ts index 79c3a390464..caf18c10a3c 100644 --- a/v-next/hardhat/src/internal/builtin-plugins/gas-analytics/index.ts +++ b/v-next/hardhat/src/internal/builtin-plugins/gas-analytics/index.ts @@ -16,6 +16,7 @@ const hardhatPlugin: HardhatPlugin = { ], hookHandlers: { hre: () => import("./hook-handlers/hre.js"), + test: () => import("./hook-handlers/test.js"), }, npmPackage: "hardhat", }; diff --git a/v-next/hardhat/src/internal/builtin-plugins/solidity-test/task-action.ts b/v-next/hardhat/src/internal/builtin-plugins/solidity-test/task-action.ts index 87872c33567..0e0624adf6d 100644 --- a/v-next/hardhat/src/internal/builtin-plugins/solidity-test/task-action.ts +++ b/v-next/hardhat/src/internal/builtin-plugins/solidity-test/task-action.ts @@ -22,16 +22,6 @@ import { getFullyQualifiedName } from "../../../utils/contract-names.js"; import { HardhatRuntimeEnvironmentImplementation } from "../../core/hre.js"; import { isSupportedChainType } from "../../edr/chain-type.js"; import { ArtifactManagerImplementation } from "../artifacts/artifact-manager.js"; -import { - markTestRunStart as initCoverage, - markTestWorkerDone as saveCoverageData, - markTestRunDone as reportCoverage, -} from "../coverage/helpers.js"; -import { - markTestRunStart as initGasStats, - markTestWorkerDone as saveGasStatsData, - markTestRunDone as reportGasStats, -} from "../gas-analytics/helpers.js"; import { edrGasReportToHardhatGasMeasurements } from "../network-manager/edr/utils/convert-to-edr.js"; import { getEdrArtifacts, getBuildInfos } from "./edr-artifacts.js"; @@ -186,8 +176,12 @@ const runSolidityTests: NewTaskActionFunction = async ( const options: RunOptions = solidityTestConfigToRunOptions(solidityTestConfig); - await initCoverage("solidity"); - await initGasStats("solidity"); + await hre.hooks.runHandlerChain( + "test", + "onTestRunStart", + ["solidity"], + async () => {}, + ); const runStream = run( chainType, @@ -271,12 +265,19 @@ const runSolidityTests: NewTaskActionFunction = async ( includesErrors = true; } - await saveCoverageData("solidity"); - await saveGasStatsData("solidity"); + await hre.hooks.runHandlerChain( + "test", + "onTestWorkerDone", + ["solidity"], + async () => {}, + ); - // this may print coverage and gas statistics reports - await reportCoverage("solidity"); - await reportGasStats("solidity"); + await hre.hooks.runHandlerChain( + "test", + "onTestRunDone", + ["solidity"], + async () => {}, + ); if (includesFailures || includesErrors) { process.exitCode = 1; diff --git a/v-next/hardhat/src/internal/builtin-plugins/test/type-extensions.ts b/v-next/hardhat/src/internal/builtin-plugins/test/type-extensions.ts index 28f015820dc..b135c5a0801 100644 --- a/v-next/hardhat/src/internal/builtin-plugins/test/type-extensions.ts +++ b/v-next/hardhat/src/internal/builtin-plugins/test/type-extensions.ts @@ -39,5 +39,47 @@ declare module "../../../types/hooks.js" { filePath: string, ) => Promise, ) => Promise; + + /** + * This hook is triggered at the start of a test run, before tests execute. + * + * @param context The hook context. + * @param id A string identifier for the test runner (e.g., "solidity", "nodejs", "mocha"). + * @param next A function to call the next handler for this hook, or the + * default implementation if no more handlers exist. + */ + onTestRunStart: ( + context: HookContext, + id: string, + next: (nextContext: HookContext, id: string) => Promise, + ) => Promise; + + /** + * This hook is triggered when a test worker has finished executing. + * + * @param context The hook context. + * @param id A string identifier for the test runner (e.g., "solidity", "nodejs", "mocha"). + * @param next A function to call the next handler for this hook, or the + * default implementation if no more handlers exist. + */ + onTestWorkerDone: ( + context: HookContext, + id: string, + next: (nextContext: HookContext, id: string) => Promise, + ) => Promise; + + /** + * This hook is triggered at the end of a test run, after all tests have completed. + * + * @param context The hook context. + * @param id A string identifier for the test runner (e.g., "solidity", "nodejs", "mocha"). + * @param next A function to call the next handler for this hook, or the + * default implementation if no more handlers exist. + */ + onTestRunDone: ( + context: HookContext, + id: string, + next: (nextContext: HookContext, id: string) => Promise, + ) => Promise; } }