UNPKG

hardhat

Version:

Hardhat is an extensible developer tool that helps smart contract developers increase productivity by reliably bringing together the tools they want.

173 lines (148 loc) 5.29 kB
import type { TaskOverrideActionFunction } from "../../../../../types/tasks.js"; import type { Result } from "../../../../../types/utils.js"; import type { SolidityTestRunResult } from "../../../solidity-test/task-action.js"; import type { FunctionGasSnapshotCheckResult } from "../../function-gas-snapshots.js"; import type { SnapshotCheatcodesCheckResult } from "../../snapshot-cheatcodes.js"; import type { SuiteResult } from "@nomicfoundation/edr"; import { HardhatError } from "@nomicfoundation/hardhat-errors"; import chalk from "chalk"; import { errorResult } from "../../../../../utils/result.js"; import { checkFunctionGasSnapshots, extractFunctionGasSnapshots, logFunctionGasSnapshotsSection, writeFunctionGasSnapshots, } from "../../function-gas-snapshots.js"; import { checkSnapshotCheatcodes, extractSnapshotCheatcodes, logSnapshotCheatcodesSection, writeSnapshotCheatcodes, } from "../../snapshot-cheatcodes.js"; interface GasAnalyticsTestActionArguments { snapshot: boolean; snapshotCheck: boolean; } export interface SnapshotResult { functionGasSnapshotsWritten: boolean; } export interface SnapshotCheckResult { functionGasSnapshotsCheck: FunctionGasSnapshotCheckResult; snapshotCheatcodesCheck: SnapshotCheatcodesCheckResult; } const runSolidityTests: TaskOverrideActionFunction< GasAnalyticsTestActionArguments > = async (args, hre, runSuper) => { const superResult: Result<SolidityTestRunResult, SolidityTestRunResult> = await runSuper(args); const testsPassed = superResult.success; const solidityTestRunResult = testsPassed ? superResult.value : superResult.error; const suiteResults = solidityTestRunResult.suiteResults; const rootPath = hre.config.paths.root; if (args.snapshot && args.snapshotCheck) { throw new HardhatError( HardhatError.ERRORS.CORE.SOLIDITY_TESTS.MUTUALLY_EXCLUSIVE_SNAPSHOT_FLAGS, ); } let snapshotCheckPassed = true; if (args.snapshot) { const snapshotResult = await handleSnapshot( rootPath, suiteResults, testsPassed, ); logSnapshotResult(snapshotResult); } else if (testsPassed && args.snapshotCheck) { const snapshotCheckResult = await handleSnapshotCheck( rootPath, suiteResults, ); logSnapshotCheckResult(snapshotCheckResult); snapshotCheckPassed = snapshotCheckResult.functionGasSnapshotsCheck.passed && snapshotCheckResult.snapshotCheatcodesCheck.passed; } if (!snapshotCheckPassed) { return errorResult(solidityTestRunResult); } return superResult; }; export async function handleSnapshot( basePath: string, suiteResults: SuiteResult[], testsPassed: boolean, ): Promise<SnapshotResult> { if (testsPassed) { const functionGasSnapshots = extractFunctionGasSnapshots(suiteResults); await writeFunctionGasSnapshots(basePath, functionGasSnapshots); } const snapshotCheatcodes = extractSnapshotCheatcodes(suiteResults); await writeSnapshotCheatcodes(basePath, snapshotCheatcodes); return { functionGasSnapshotsWritten: testsPassed, }; } export function logSnapshotResult( result: SnapshotResult, logger: typeof console.log = console.log, ): void { if (result.functionGasSnapshotsWritten) { logger(chalk.green("Function gas snapshots written successfully")); logger(); } } export async function handleSnapshotCheck( basePath: string, suiteResults: SuiteResult[], ): Promise<SnapshotCheckResult> { const functionGasSnapshotsCheck = await checkFunctionGasSnapshots( basePath, suiteResults, ); const snapshotCheatcodesCheck = await checkSnapshotCheatcodes( basePath, suiteResults, ); return { functionGasSnapshotsCheck, snapshotCheatcodesCheck, }; } export function logSnapshotCheckResult( { functionGasSnapshotsCheck, snapshotCheatcodesCheck }: SnapshotCheckResult, logger: typeof console.log = console.log, ): void { logger( functionGasSnapshotsCheck.passed && snapshotCheatcodesCheck.passed ? chalk.green("Snapshot check passed") : chalk.red("Snapshot check failed"), ); const functionGasHasOutput = functionGasSnapshotsCheck.written || functionGasSnapshotsCheck.comparison.changed.length > 0 || functionGasSnapshotsCheck.comparison.added.length > 0 || functionGasSnapshotsCheck.comparison.removed.length > 0; const snapshotCheatcodesHasOutput = snapshotCheatcodesCheck.written || snapshotCheatcodesCheck.comparison.changed.length > 0 || snapshotCheatcodesCheck.comparison.added.length > 0 || snapshotCheatcodesCheck.comparison.removed.length > 0; // Add an extra newline if function gas snapshots have output if (functionGasHasOutput) { logger(); } logFunctionGasSnapshotsSection(functionGasSnapshotsCheck, logger); // Add an extra newline if only snapshot cheatcodes have output // (logFunctionGasSnapshotsSection adds one if it has output) if (!functionGasHasOutput && snapshotCheatcodesHasOutput) { logger(); } logSnapshotCheatcodesSection(snapshotCheatcodesCheck, logger); if (!functionGasSnapshotsCheck.passed || !snapshotCheatcodesCheck.passed) { logger(chalk.yellow("To update snapshots, run your tests with --snapshot")); logger(); } } export default runSolidityTests;