Skip to content

Commit 594c4c5

Browse files
authored
hook manager tests (#5393)
Add unit tests around the HookManager in ./v-next/core/src/internal/Hook-Manager.ts. It applies some small refactoring to the HookManager swapping in assertion instead of conditionals throwing errors, and replacing a plain Error with a specific HardhatError. Resolves #5231.
1 parent 228fcd1 commit 594c4c5

File tree

4 files changed

+1011
-26
lines changed

4 files changed

+1011
-26
lines changed

v-next/core/src/internal/hook-manager.ts

+32-26
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ import type {
1212
import type { HardhatPlugin } from "../types/plugins.js";
1313
import type { LastParameter, Return } from "../types/utils.js";
1414

15+
import {
16+
HardhatError,
17+
assertHardhatInvariant,
18+
} from "@nomicfoundation/hardhat-errors";
19+
1520
export class HookManagerImplementation implements HookManager {
1621
readonly #pluginsInReverseOrder: HardhatPlugin[];
1722

@@ -108,10 +113,10 @@ export class HookManagerImplementation implements HookManager {
108113

109114
let handlerParams: Parameters<typeof defaultImplementation>;
110115
if (hookCategoryName !== "config") {
111-
// TODO: assert that this.#context is not undefinded
112-
if (this.#context === undefined) {
113-
throw new Error(`Context must be set before running non-config hooks`);
114-
}
116+
assertHardhatInvariant(
117+
this.#context !== undefined,
118+
"Context must be set before running non-config hooks",
119+
);
115120

116121
handlerParams = [this.#context, ...params] as any;
117122
} else {
@@ -147,10 +152,10 @@ export class HookManagerImplementation implements HookManager {
147152

148153
let handlerParams: any;
149154
if (hookCategoryName !== "config") {
150-
// TODO: assert that this.#context is not undefinded
151-
if (this.#context === undefined) {
152-
throw new Error(`Context must be set before running non-config hooks`);
153-
}
155+
assertHardhatInvariant(
156+
this.#context !== undefined,
157+
"Context must be set before running non-config hooks",
158+
);
154159

155160
handlerParams = [this.#context, ...params];
156161
} else {
@@ -180,10 +185,10 @@ export class HookManagerImplementation implements HookManager {
180185

181186
let handlerParams: any;
182187
if (hookCategoryName !== "config") {
183-
// TODO: assert that this.#context is not undefinded
184-
if (this.#context === undefined) {
185-
throw new Error(`Context must be set before running non-config hooks`);
186-
}
188+
assertHardhatInvariant(
189+
this.#context !== undefined,
190+
"Context must be set before running non-config hooks",
191+
);
187192

188193
handlerParams = [this.#context, ...params];
189194
} else {
@@ -288,30 +293,31 @@ export class HookManagerImplementation implements HookManager {
288293
path: string,
289294
): Promise<Partial<HardhatHooks[HookCategoryNameT]>> {
290295
if (!path.startsWith("file://")) {
291-
throw new Error(
292-
`Plugin ${pluginId} hook factory for ${hookCategoryName} is not a valid file:// URL: ${path}`,
296+
throw new HardhatError(
297+
HardhatError.ERRORS.HOOKS.INVALID_HOOK_FACTORY_PATH,
298+
{
299+
pluginId,
300+
hookCategoryName,
301+
path,
302+
},
293303
);
294304
}
295305

296306
const mod = await import(path);
297307

298308
const factory = mod.default;
299309

300-
// TODO: Assert that the factory is a function
301-
if (typeof factory !== "function") {
302-
throw new Error(
303-
`Plugin ${pluginId} doesn't export a hook factory for category ${hookCategoryName} in ${path}`,
304-
);
305-
}
310+
assertHardhatInvariant(
311+
typeof factory === "function",
312+
`Plugin ${pluginId} doesn't export a hook factory for category ${hookCategoryName} in ${path}`,
313+
);
306314

307315
const category = await factory();
308316

309-
// TODO: Assert that category is not undefined and it's an object -- should use !isObject(category)
310-
if (typeof category !== "object" || category === null) {
311-
throw new Error(
312-
`Plugin ${pluginId} doesn't export a valid factory for category ${hookCategoryName} in ${path}, it didn't return an object`,
313-
);
314-
}
317+
assertHardhatInvariant(
318+
category !== null && typeof category === "object",
319+
`Plugin ${pluginId} doesn't export a valid factory for category ${hookCategoryName} in ${path}, it didn't return an object`,
320+
);
315321

316322
return category;
317323
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import type { HardhatUserConfig } from "../../../src/types/config.js";
2+
import type {
3+
ConfigHooks,
4+
HardhatUserConfigValidationError,
5+
} from "../../../src/types/hooks.js";
6+
7+
export default async () => {
8+
const handlers: Partial<ConfigHooks> = {
9+
validateUserConfig: async (
10+
_config: HardhatUserConfig,
11+
): Promise<HardhatUserConfigValidationError[]> => {
12+
return [
13+
{
14+
message: "FromLoadedPlugin",
15+
path: [],
16+
},
17+
];
18+
},
19+
};
20+
21+
return handlers;
22+
};

0 commit comments

Comments
 (0)