diff --git a/v-next/hardhat/test/internal/example-mock-artifacts-plugin-using-test.ts b/v-next/hardhat/test/internal/example-mock-artifacts-plugin-using-test.ts new file mode 100644 index 00000000000..05d1a4275a1 --- /dev/null +++ b/v-next/hardhat/test/internal/example-mock-artifacts-plugin-using-test.ts @@ -0,0 +1,54 @@ +import type { Artifact } from "../../src/types/artifacts.js"; +import type { HardhatRuntimeEnvironment } from "../../src/types/hre.js"; +import type { HardhatPlugin } from "../../src/types/plugins.js"; + +import assert from "node:assert/strict"; +import { describe, it } from "node:test"; + +import { task } from "../../src/config.js"; +import { createMockHardhatRuntimeEnvironment } from "../test-helpers/create-mock-hardhat-runtime-environment.js"; + +// TODO: This test is an example and should be removed with the completion of +// the build system and the artifacts plugin. +describe("createMockHardhatRuntimeEnvironment", () => { + it("should allow plugins that leverage the artifact hre object", async () => { + // arrange + const exampleArtifact: Artifact = { + _format: "hh-sol-artifact-1", + contractName: "MyContract", + sourceName: "source.sol", + abi: [], + bytecode: "0x", + linkReferences: {}, + deployedBytecode: "0x", + deployedLinkReferences: {}, + }; + + const myPlugin: HardhatPlugin = { + id: "my-plugin", + tasks: [ + task("hello-artifact-using-world", "Tests artifact loading") + .setAction(async ({}, hre: HardhatRuntimeEnvironment) => { + return hre.artifacts.readArtifact("MyContract"); + }) + .build(), + ], + }; + + const mockHre = await createMockHardhatRuntimeEnvironment({ + plugins: [myPlugin], + }); + + await mockHre.artifacts.saveArtifact(exampleArtifact); + + // act + const helloArtifactUsingWorld = mockHre.tasks.getTask( + "hello-artifact-using-world", + ); + + const result = await helloArtifactUsingWorld.run({}); + + // Assert + assert.equal(result, exampleArtifact); + }); +}); diff --git a/v-next/hardhat/test/test-helpers/create-mock-hardhat-runtime-environment.ts b/v-next/hardhat/test/test-helpers/create-mock-hardhat-runtime-environment.ts new file mode 100644 index 00000000000..7013ad9c587 --- /dev/null +++ b/v-next/hardhat/test/test-helpers/create-mock-hardhat-runtime-environment.ts @@ -0,0 +1,51 @@ +import type { HardhatUserConfig } from "../../src/config.js"; +import type { UnsafeHardhatRuntimeEnvironmentOptions } from "../../src/internal/core/types.js"; +import type { GlobalOptions } from "../../src/types/global-options.js"; +import type { HardhatRuntimeEnvironment } from "../../src/types/hre.js"; +import type { HardhatPlugin } from "../../src/types/plugins.js"; + +import "../../src/internal/builtin-plugins/artifacts/type-extensions.js"; + +import { createHardhatRuntimeEnvironment } from "../../src/hre.js"; +import artifacts from "../../src/internal/builtin-plugins/artifacts/index.js"; +import { resolveProjectRoot } from "../../src/internal/core/hre.js"; + +import { MockArtifactsManager } from "./mock-artifacts-manager.js"; + +export async function createMockHardhatRuntimeEnvironment( + config: HardhatUserConfig, + userProvidedGlobalOptions: Partial = {}, + projectRoot?: string, + unsafeOptions: UnsafeHardhatRuntimeEnvironmentOptions = {}, +): Promise { + const resolvedProjectRoot = await resolveProjectRoot(projectRoot); + + return createHardhatRuntimeEnvironment( + { ...config, plugins: [mockArtifactsPlugin, ...(config.plugins ?? [])] }, + userProvidedGlobalOptions, + resolvedProjectRoot, + unsafeOptions, + ); +} + +const mockArtifactsPlugin: HardhatPlugin = { + id: "mock-artifacts", + dependencies: [async () => artifacts], + hookHandlers: { + hre: async () => { + return { + created: async ( + context, + hre, + next, + ): Promise => { + const updatedHre = await next(context, hre); + + updatedHre.artifacts = new MockArtifactsManager(); + + return updatedHre; + }, + }; + }, + }, +}; diff --git a/v-next/hardhat/test/test-helpers/mock-artifacts-manager.ts b/v-next/hardhat/test/test-helpers/mock-artifacts-manager.ts new file mode 100644 index 00000000000..46f406416c3 --- /dev/null +++ b/v-next/hardhat/test/test-helpers/mock-artifacts-manager.ts @@ -0,0 +1,104 @@ +import type { + ArtifactsManager, + Artifact, + BuildInfo, + CompilerInput, + CompilerOutput, +} from "../../src/types/artifacts.js"; + +import { HardhatError } from "@ignored/hardhat-vnext-errors"; + +export class MockArtifactsManager implements ArtifactsManager { + readonly #artifacts: Map; + + constructor() { + this.#artifacts = new Map(); + } + + public async readArtifact( + contractNameOrFullyQualifiedName: string, + ): Promise { + const artifact = this.#artifacts.get(contractNameOrFullyQualifiedName); + + if (artifact === undefined) { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: + "Unable to find the artifact during mock readArtifact " + + contractNameOrFullyQualifiedName, + }); + } + + return artifact; + } + + public artifactExists( + _contractNameOrFullyQualifiedName: string, + ): Promise { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: "Not implemented in MockArtifactsManager", + }); + } + + public getAllFullyQualifiedNames(): Promise { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: "Not implemented in MockArtifactsManager", + }); + } + + public getBuildInfo( + _fullyQualifiedName: string, + ): Promise { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: "Not implemented in MockArtifactsManager", + }); + } + + public getArtifactPaths(): Promise { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: "Not implemented in MockArtifactsManager", + }); + } + + public getDebugFilePaths(): Promise { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: "Not implemented in MockArtifactsManager", + }); + } + + public getBuildInfoPaths(): Promise { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: "Not implemented in MockArtifactsManager", + }); + } + + public async saveArtifact(artifact: Artifact): Promise { + this.#artifacts.set(artifact.contractName, artifact); + } + + public saveBuildInfo( + _solcVersion: string, + _solcLongVersion: string, + _input: CompilerInput, + _output: CompilerOutput, + ): Promise { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: "Not implemented in MockArtifactsManager", + }); + } + + public formArtifactPathFromFullyQualifiedName( + _fullyQualifiedName: string, + ): string { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: "Not implemented in MockArtifactsManager", + }); + } + + public getArtifactPath( + _contractNameOrFullyQualifiedName: string, + ): Promise { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: "Not implemented in MockArtifactsManager", + }); + } +}