From 9bc3a6c233ca3a94338278652b59b415bc7385e3 Mon Sep 17 00:00:00 2001 From: Luis Schaab Date: Wed, 19 Jun 2024 18:56:02 -0300 Subject: [PATCH 1/8] Add camelToSnakeCase --- v-next/hardhat-utils/src/string.ts | 10 ++++++++++ v-next/hardhat-utils/test/string.ts | 18 +++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/v-next/hardhat-utils/src/string.ts b/v-next/hardhat-utils/src/string.ts index 9b8365c5bf..b0aeeff961 100644 --- a/v-next/hardhat-utils/src/string.ts +++ b/v-next/hardhat-utils/src/string.ts @@ -40,3 +40,13 @@ export function capitalize(str: string): string { export function kebabToCamelCase(str: string): string { return str.replace(/-./g, (match) => match.charAt(1).toUpperCase()); } + +/** + * Converts a camelCase string to snake_case. + * + * @param str The camelCase string to convert. + * @returns The snake_case string. + */ +export function camelToSnakeCase(str: string): string { + return str.replace(/[A-Z]/g, (match) => `_${match.toLowerCase()}`); +} diff --git a/v-next/hardhat-utils/test/string.ts b/v-next/hardhat-utils/test/string.ts index dabaee0a58..73e397d579 100644 --- a/v-next/hardhat-utils/test/string.ts +++ b/v-next/hardhat-utils/test/string.ts @@ -1,7 +1,12 @@ import assert from "node:assert/strict"; import { describe, it } from "node:test"; -import { pluralize, capitalize, kebabToCamelCase } from "../src/string.js"; +import { + pluralize, + capitalize, + kebabToCamelCase, + camelToSnakeCase, +} from "../src/string.js"; describe("string", () => { describe("pluralize", () => { @@ -44,4 +49,15 @@ describe("string", () => { ); }); }); + + describe("camelToSnakeCase", () => { + it("Should convert a camelCase string to snake_case", () => { + assert.equal(camelToSnakeCase("camelcasestring"), "camelcasestring"); + assert.equal(camelToSnakeCase("camelCaseString"), "camel_case_string"); + assert.equal( + camelToSnakeCase("camelCASESTRING"), + "camel_c_a_s_e_s_t_r_i_n_g", + ); + }); + }); }); From 0f5453a9ec1b890e45500befdf123d97a84d8510 Mon Sep 17 00:00:00 2001 From: Luis Schaab Date: Wed, 19 Jun 2024 18:56:34 -0300 Subject: [PATCH 2/8] Add parameter parsing --- v-next/core/src/internal/parameters.ts | 100 +++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/v-next/core/src/internal/parameters.ts b/v-next/core/src/internal/parameters.ts index 11ad812149..c3735073b0 100644 --- a/v-next/core/src/internal/parameters.ts +++ b/v-next/core/src/internal/parameters.ts @@ -1,3 +1,7 @@ +import type { ParameterValue } from "../types/common.js"; + +import { HardhatError } from "@nomicfoundation/hardhat-errors"; + import { ParameterType } from "../types/common.js"; /** @@ -54,3 +58,99 @@ const parameterTypeValidators: Record< [ParameterType.FLOAT]: (value): value is number => typeof value === "number", [ParameterType.FILE]: (value): value is string => typeof value === "string", }; + +/** + * Parses a parameter value from a string to the corresponding type. + */ +// TODO: this code is duplicated in v-next/hardhat/src/internal/cli/main.ts +// we should move it to a shared place and add tests +export function parseParameterValue( + value: string, + type: ParameterType, + name: string, +): ParameterValue { + switch (type) { + case ParameterType.STRING: + case ParameterType.FILE: + return value; + case ParameterType.INT: + return validateAndParseInt(name, value); + case ParameterType.FLOAT: + return validateAndParseFloat(name, value); + case ParameterType.BIGINT: + return validateAndParseBigInt(name, value); + case ParameterType.BOOLEAN: + return validateAndParseBoolean(name, value); + } +} + +function validateAndParseInt(name: string, value: string): number { + const decimalPattern = /^\d+(?:[eE]\d+)?$/; + const hexPattern = /^0[xX][\dABCDEabcde]+$/; + + if (!decimalPattern.test(value) && !hexPattern.test(value)) { + throw new HardhatError( + HardhatError.ERRORS.ARGUMENTS.INVALID_VALUE_FOR_TYPE, + { + value, + name, + type: ParameterType.INT, + }, + ); + } + + return Number(value); +} + +function validateAndParseFloat(name: string, value: string): number { + const decimalPattern = /^(?:\d+(?:\.\d*)?|\.\d+)(?:[eE]\d+)?$/; + const hexPattern = /^0[xX][\dABCDEabcde]+$/; + + if (!decimalPattern.test(value) && !hexPattern.test(value)) { + throw new HardhatError( + HardhatError.ERRORS.ARGUMENTS.INVALID_VALUE_FOR_TYPE, + { + value, + name, + type: ParameterType.FLOAT, + }, + ); + } + + return Number(value); +} + +function validateAndParseBigInt(name: string, value: string): bigint { + const decimalPattern = /^\d+(?:n)?$/; + const hexPattern = /^0[xX][\dABCDEabcde]+$/; + + if (!decimalPattern.test(value) && !hexPattern.test(value)) { + throw new HardhatError( + HardhatError.ERRORS.ARGUMENTS.INVALID_VALUE_FOR_TYPE, + { + value, + name, + type: ParameterType.BIGINT, + }, + ); + } + + return BigInt(value.replace("n", "")); +} + +function validateAndParseBoolean(name: string, value: string): boolean { + const normalizedValue = value.toLowerCase(); + + if (normalizedValue !== "true" && normalizedValue !== "false") { + throw new HardhatError( + HardhatError.ERRORS.ARGUMENTS.INVALID_VALUE_FOR_TYPE, + { + value, + name, + type: ParameterType.BOOLEAN, + }, + ); + } + + return normalizedValue === "true"; +} From 5fc1ba3aed8e27245b93241ef5fe67b33aa24553 Mon Sep 17 00:00:00 2001 From: Luis Schaab Date: Wed, 19 Jun 2024 18:56:49 -0300 Subject: [PATCH 3/8] Improve types --- v-next/core/src/types/global-options.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/v-next/core/src/types/global-options.ts b/v-next/core/src/types/global-options.ts index ef40e2d0ba..0850668cd9 100644 --- a/v-next/core/src/types/global-options.ts +++ b/v-next/core/src/types/global-options.ts @@ -1,4 +1,8 @@ -import type { ParameterType, ParameterTypeToValueType } from "./common.js"; +import type { + ParameterType, + ParameterTypeToValueType, + ParameterValue, +} from "./common.js"; /** * A global option with an associated value and a default if not provided by @@ -25,7 +29,7 @@ export interface GlobalOption { * Runtime Environment. */ // eslint-disable-next-line @typescript-eslint/no-empty-interface -- To be used through module augmentation -export interface GlobalOptions {} +export interface GlobalOptions extends Record {} /** * An entry in the global options map. From 02d6b971d10d978886433b026c55f28f1ee43180 Mon Sep 17 00:00:00 2001 From: Luis Schaab Date: Wed, 19 Jun 2024 18:57:27 -0300 Subject: [PATCH 4/8] Add global args resolution --- v-next/core/src/internal/global-options.ts | 63 +++++++++++++++++++--- 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/v-next/core/src/internal/global-options.ts b/v-next/core/src/internal/global-options.ts index ca9c767bce..5a4cbd02fd 100644 --- a/v-next/core/src/internal/global-options.ts +++ b/v-next/core/src/internal/global-options.ts @@ -1,4 +1,7 @@ -import type { ParameterTypeToValueType } from "../types/common.js"; +import type { + ParameterTypeToValueType, + ParameterValue, +} from "../types/common.js"; import type { GlobalOptions, GlobalOption, @@ -7,6 +10,7 @@ import type { import type { HardhatPlugin } from "../types/plugins.js"; import { HardhatError } from "@nomicfoundation/hardhat-errors"; +import { camelToSnakeCase } from "@nomicfoundation/hardhat-utils/string"; import { ParameterType } from "../types/common.js"; @@ -14,14 +18,16 @@ import { RESERVED_PARAMETER_NAMES, isParameterValueValid, isValidParamNameCasing, + parseParameterValue, } from "./parameters.js"; /** - * Builds a map of the global options, validating them. + * Builds a map of the global option definitions by going through all the + * plugins and validating the global options they define. * * Note: this function can be used before initializing the HRE, so the plugins * shouldn't be consider validated. Hence, we should validate the global - * parameters. + * options. */ export function buildGlobalOptionsMap( resolvedPlugins: HardhatPlugin[], @@ -60,6 +66,10 @@ export function buildGlobalOptionsMap( return globalOptionsMap; } +/** + * Builds a global option definition, validating the name, type, and default + * value. + */ export function buildGlobalOptionDefinition({ name, description, @@ -104,13 +114,50 @@ export function buildGlobalOptionDefinition({ }; } +/** + * Resolves global options by merging user-provided options with environment + * variables, adhering to predefined global option definitions. This function + * ensures that only options specified in the globalOptionsMap are considered. + * Each option is validated against its definition in the map, with + * user-provided options taking precedence over environment variables. If an + * option is not provided by the user or set as an environment variable, its + * default value (as specified in the globalOptionsMap) is used. + * + * @param userProvidedGlobalOptions The options explicitly provided by the + * user. These take precedence over equivalent environment variables. + * @param globalOptionsMap A map defining valid global options, their default + * values, and expected types. This map is used to validate and parse the options. + * @returns {GlobalOptions} An object containing the resolved global options, + * with each option adhering to its definition in the globalOptionsMap. + * @throws {HardhatError} with descriptor + * {@link HardhatError.ERRORS.ARGUMENTS.INVALID_VALUE_FOR_TYPE} if a user-provided + * option has an invalid value for its type. + */ export function resolveGlobalOptions( userProvidedGlobalOptions: Partial, - _globalOptionsMap: GlobalOptionsMap, + globalOptionsMap: GlobalOptionsMap, ): GlobalOptions { - // TODO: Validate the userProvidedGlobalOptions and get the remaining ones - // from env variables + const globalOptions: GlobalOptions = {}; + // iterate over the definitions to parse and validate the arguments + for (const [name, { option }] of globalOptionsMap) { + let value = + /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions + -- GlobalOptions is empty for user extension, so we need to cast it to + assign the value. */ + (userProvidedGlobalOptions as Record)[name]; + if (value === undefined) { + value = process.env[`HARDHAT_${camelToSnakeCase(name).toUpperCase()}`]; + } + + let parsedValue: ParameterValue; + if (value !== undefined) { + parsedValue = parseParameterValue(value, option.parameterType, name); + } else { + parsedValue = option.defaultValue; + } + + globalOptions[name] = parsedValue; + } - // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- TODO - return userProvidedGlobalOptions as GlobalOptions; + return globalOptions; } From d33a2233611fde75984c864518402189c1ebdc4c Mon Sep 17 00:00:00 2001 From: Luis Schaab Date: Wed, 19 Jun 2024 18:57:40 -0300 Subject: [PATCH 5/8] Add tests to resolveGlobalArguments --- v-next/core/test/internal/global-options.ts | 201 +++++++++++++++++++- v-next/core/test/utils.ts | 30 +++ 2 files changed, 229 insertions(+), 2 deletions(-) create mode 100644 v-next/core/test/utils.ts diff --git a/v-next/core/test/internal/global-options.ts b/v-next/core/test/internal/global-options.ts index 67490c222b..e3a8cd9abc 100644 --- a/v-next/core/test/internal/global-options.ts +++ b/v-next/core/test/internal/global-options.ts @@ -7,8 +7,10 @@ import { ParameterType } from "../../src/config.js"; import { buildGlobalOptionsMap, buildGlobalOptionDefinition, + resolveGlobalOptions, } from "../../src/internal/global-options.js"; import { RESERVED_PARAMETER_NAMES } from "../../src/internal/parameters.js"; +import { createTestEnvManager } from "../utils.js"; describe("Global Options", () => { describe("buildGlobalOptionsMap", () => { @@ -240,7 +242,202 @@ describe("Global Options", () => { }); }); - describe.todo("resolveGlobalOptions", () => { - // TODO: Implement tests. + describe("resolveGlobalOptions", () => { + const { setEnvVar } = createTestEnvManager(); + + it("should resolve to the default values when no options are provided", () => { + const globalOptionsMap = buildGlobalOptionsMap([ + { + id: "plugin1", + globalOptions: [ + buildGlobalOptionDefinition({ + name: "param1", + description: "param1 description", + parameterType: ParameterType.BOOLEAN, + defaultValue: true, + }), + buildGlobalOptionDefinition({ + name: "param2", + description: "param2 description", + defaultValue: "default", + }), + ], + }, + ]); + + const globalOptions = resolveGlobalOptions({}, globalOptionsMap); + + assert.deepEqual(globalOptions, { + param1: true, + param2: "default", + }); + }); + + it("should resolve to the user provided options and env variables", () => { + const globalOptionsMap = buildGlobalOptionsMap([ + { + id: "plugin1", + globalOptions: [ + buildGlobalOptionDefinition({ + name: "param1", + description: "param1 description", + parameterType: ParameterType.BOOLEAN, + defaultValue: true, + }), + buildGlobalOptionDefinition({ + name: "param2", + description: "param2 description", + defaultValue: "default", + }), + buildGlobalOptionDefinition({ + name: "param3", + description: "param3 description", + parameterType: ParameterType.BIGINT, + defaultValue: 0n, + }), + ], + }, + ]); + + setEnvVar("HARDHAT_PARAM3", "5n"); + + const globalOptions = resolveGlobalOptions( + { + param1: "false", + param2: "user", + }, + globalOptionsMap, + ); + + assert.deepEqual(globalOptions, { + param1: false, + param2: "user", + param3: 5n, + }); + }); + + it("should resolve to the user provided options over the environment variables", () => { + const globalOptionsMap = buildGlobalOptionsMap([ + { + id: "plugin1", + globalOptions: [ + buildGlobalOptionDefinition({ + name: "param1", + description: "param1 description", + parameterType: ParameterType.BOOLEAN, + defaultValue: true, + }), + buildGlobalOptionDefinition({ + name: "param2", + description: "param2 description", + defaultValue: "default", + }), + ], + }, + ]); + + setEnvVar("HARDHAT_PARAM2", "env"); + + const globalOptions = resolveGlobalOptions( + { + param1: "false", + param2: "user", + }, + globalOptionsMap, + ); + + assert.deepEqual(globalOptions, { + param1: false, + param2: "user", + }); + }); + + it("should ignore options that are not defined in the global option map", () => { + const globalOptionsMap = buildGlobalOptionsMap([ + { + id: "plugin1", + globalOptions: [ + buildGlobalOptionDefinition({ + name: "param1", + description: "param1 description", + parameterType: ParameterType.BOOLEAN, + defaultValue: true, + }), + ], + }, + ]); + + setEnvVar("HARDHAT_PARAM3", "env"); + + const globalOptions = resolveGlobalOptions( + { + param1: "false", + param2: "user", + }, + globalOptionsMap, + ); + + assert.deepEqual(globalOptions, { + param1: false, + }); + }); + + it("should throw if the provided option is not valid", () => { + const globalOptionsMap = buildGlobalOptionsMap([ + { + id: "plugin1", + globalOptions: [ + buildGlobalOptionDefinition({ + name: "param1", + description: "param1 description", + parameterType: ParameterType.BOOLEAN, + defaultValue: true, + }), + ], + }, + ]); + + assert.throws( + () => + resolveGlobalOptions( + { + param1: "not a boolean", + }, + globalOptionsMap, + ), + new HardhatError(HardhatError.ERRORS.ARGUMENTS.INVALID_VALUE_FOR_TYPE, { + value: "not a boolean", + name: "param1", + type: ParameterType.BOOLEAN, + }), + ); + }); + + it("should throw if the environment variable is not valid", () => { + const globalOptionsMap = buildGlobalOptionsMap([ + { + id: "plugin1", + globalOptions: [ + buildGlobalOptionDefinition({ + name: "param1", + description: "param1 description", + parameterType: ParameterType.BOOLEAN, + defaultValue: true, + }), + ], + }, + ]); + + setEnvVar("HARDHAT_PARAM1", "not a boolean"); + + assert.throws( + () => resolveGlobalOptions({}, globalOptionsMap), + new HardhatError(HardhatError.ERRORS.ARGUMENTS.INVALID_VALUE_FOR_TYPE, { + value: "not a boolean", + name: "param1", + type: ParameterType.BOOLEAN, + }), + ); + }); }); }); diff --git a/v-next/core/test/utils.ts b/v-next/core/test/utils.ts new file mode 100644 index 0000000000..7e4d80fb69 --- /dev/null +++ b/v-next/core/test/utils.ts @@ -0,0 +1,30 @@ +import { afterEach } from "node:test"; + +export function createTestEnvManager() { + const changes = new Set(); + const originalValues = new Map(); + + afterEach(() => { + // Revert changes to process.env based on the originalValues Map entries + changes.forEach((key) => { + const originalValue = originalValues.get(key); + if (originalValue === undefined) { + delete process.env[key]; + } else { + process.env[key] = originalValue; + } + }); + changes.clear(); + }); + + return { + setEnvVar(name: string, value: string) { + // Before setting a new value, save the original value if it hasn't been saved yet + if (!changes.has(name)) { + originalValues.set(name, process.env[name]); + changes.add(name); + } + process.env[name] = value; + }, + }; +} From 0eca4fad40b0e86fa83b4a2482a0d10b67bc185e Mon Sep 17 00:00:00 2001 From: Luis Schaab Date: Mon, 24 Jun 2024 10:38:28 -0300 Subject: [PATCH 6/8] Fix build errors --- v-next/hardhat/src/internal/cli/main.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/v-next/hardhat/src/internal/cli/main.ts b/v-next/hardhat/src/internal/cli/main.ts index 66a71ddf9e..e0c7db0243 100644 --- a/v-next/hardhat/src/internal/cli/main.ts +++ b/v-next/hardhat/src/internal/cli/main.ts @@ -71,7 +71,7 @@ export async function main(cliArguments: string[], print = console.log) { ); const globalOptionsMap = buildGlobalOptionsMap(resolvedPlugins); - const userProvidedGlobalOptions = parseGlobalOptions( + const userProvidedGlobalOptions = await parseGlobalOptions( globalOptionsMap, cliArguments, usedCliArguments, @@ -378,7 +378,7 @@ function parseDoubleDashArgs( cliArguments: string[], usedCliArguments: boolean[], optionsMap: Map, - argumentsMap: TaskArguments, + argumentsMap: TaskArguments | Partial, ignoreUnknownParameter = false, ) { for (let i = 0; i < cliArguments.length; i++) { @@ -525,7 +525,7 @@ function parsePositionalAndVariadicParameters( function validateRequiredParameters( parameters: TaskParameter[], - taskArguments: TaskArguments, + taskArguments: TaskArguments | Partial, ) { const missingRequiredParam = parameters.find( (param) => From 22abbd50240a9fcb3ac488c72b64b5dc0fce4ec8 Mon Sep 17 00:00:00 2001 From: Luis Schaab Date: Tue, 25 Jun 2024 11:25:51 -0300 Subject: [PATCH 7/8] Fix type error --- v-next/core/src/internal/global-options.ts | 5 ++++- v-next/core/src/types/global-options.ts | 8 ++------ v-next/hardhat/src/internal/cli/main.ts | 4 ++-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/v-next/core/src/internal/global-options.ts b/v-next/core/src/internal/global-options.ts index 5a4cbd02fd..ef6f073241 100644 --- a/v-next/core/src/internal/global-options.ts +++ b/v-next/core/src/internal/global-options.ts @@ -156,7 +156,10 @@ export function resolveGlobalOptions( parsedValue = option.defaultValue; } - globalOptions[name] = parsedValue; + /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions + -- GlobalOptions is empty for user extension, so we need to cast it to + assign the value. */ + (globalOptions as Record)[name] = parsedValue; } return globalOptions; diff --git a/v-next/core/src/types/global-options.ts b/v-next/core/src/types/global-options.ts index 0850668cd9..ef40e2d0ba 100644 --- a/v-next/core/src/types/global-options.ts +++ b/v-next/core/src/types/global-options.ts @@ -1,8 +1,4 @@ -import type { - ParameterType, - ParameterTypeToValueType, - ParameterValue, -} from "./common.js"; +import type { ParameterType, ParameterTypeToValueType } from "./common.js"; /** * A global option with an associated value and a default if not provided by @@ -29,7 +25,7 @@ export interface GlobalOption { * Runtime Environment. */ // eslint-disable-next-line @typescript-eslint/no-empty-interface -- To be used through module augmentation -export interface GlobalOptions extends Record {} +export interface GlobalOptions {} /** * An entry in the global options map. diff --git a/v-next/hardhat/src/internal/cli/main.ts b/v-next/hardhat/src/internal/cli/main.ts index e0c7db0243..3433a05160 100644 --- a/v-next/hardhat/src/internal/cli/main.ts +++ b/v-next/hardhat/src/internal/cli/main.ts @@ -378,7 +378,7 @@ function parseDoubleDashArgs( cliArguments: string[], usedCliArguments: boolean[], optionsMap: Map, - argumentsMap: TaskArguments | Partial, + argumentsMap: TaskArguments, ignoreUnknownParameter = false, ) { for (let i = 0; i < cliArguments.length; i++) { @@ -525,7 +525,7 @@ function parsePositionalAndVariadicParameters( function validateRequiredParameters( parameters: TaskParameter[], - taskArguments: TaskArguments | Partial, + taskArguments: TaskArguments, ) { const missingRequiredParam = parameters.find( (param) => From 665a755469f337054bcb80d64bcba9d4c3c64aaf Mon Sep 17 00:00:00 2001 From: Luis Schaab Date: Tue, 25 Jun 2024 11:26:03 -0300 Subject: [PATCH 8/8] Parse only env vars --- v-next/core/src/internal/global-options.ts | 16 ++++++--- v-next/core/test/internal/global-options.ts | 37 ++------------------- 2 files changed, 14 insertions(+), 39 deletions(-) diff --git a/v-next/core/src/internal/global-options.ts b/v-next/core/src/internal/global-options.ts index ef6f073241..07d7004c30 100644 --- a/v-next/core/src/internal/global-options.ts +++ b/v-next/core/src/internal/global-options.ts @@ -145,15 +145,21 @@ export function resolveGlobalOptions( -- GlobalOptions is empty for user extension, so we need to cast it to assign the value. */ (userProvidedGlobalOptions as Record)[name]; - if (value === undefined) { - value = process.env[`HARDHAT_${camelToSnakeCase(name).toUpperCase()}`]; - } let parsedValue: ParameterValue; + // if the value is provided in the user options, it's already parsed + // and it takes precedence over env vars if (value !== undefined) { - parsedValue = parseParameterValue(value, option.parameterType, name); + parsedValue = value; } else { - parsedValue = option.defaultValue; + value = process.env[`HARDHAT_${camelToSnakeCase(name).toUpperCase()}`]; + if (value !== undefined) { + // if the value is provided via an env var, it needs to be parsed + parsedValue = parseParameterValue(value, option.parameterType, name); + } else { + // if the value is not provided by the user or env var, use the default + parsedValue = option.defaultValue; + } } /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions diff --git a/v-next/core/test/internal/global-options.ts b/v-next/core/test/internal/global-options.ts index e3a8cd9abc..b8dfef14ec 100644 --- a/v-next/core/test/internal/global-options.ts +++ b/v-next/core/test/internal/global-options.ts @@ -303,7 +303,7 @@ describe("Global Options", () => { const globalOptions = resolveGlobalOptions( { - param1: "false", + param1: false, param2: "user", }, globalOptionsMap, @@ -340,7 +340,7 @@ describe("Global Options", () => { const globalOptions = resolveGlobalOptions( { - param1: "false", + param1: false, param2: "user", }, globalOptionsMap, @@ -371,7 +371,7 @@ describe("Global Options", () => { const globalOptions = resolveGlobalOptions( { - param1: "false", + param1: false, param2: "user", }, globalOptionsMap, @@ -382,37 +382,6 @@ describe("Global Options", () => { }); }); - it("should throw if the provided option is not valid", () => { - const globalOptionsMap = buildGlobalOptionsMap([ - { - id: "plugin1", - globalOptions: [ - buildGlobalOptionDefinition({ - name: "param1", - description: "param1 description", - parameterType: ParameterType.BOOLEAN, - defaultValue: true, - }), - ], - }, - ]); - - assert.throws( - () => - resolveGlobalOptions( - { - param1: "not a boolean", - }, - globalOptionsMap, - ), - new HardhatError(HardhatError.ERRORS.ARGUMENTS.INVALID_VALUE_FOR_TYPE, { - value: "not a boolean", - name: "param1", - type: ParameterType.BOOLEAN, - }), - ); - }); - it("should throw if the environment variable is not valid", () => { const globalOptionsMap = buildGlobalOptionsMap([ {