From 5e89608b4ade49a7b7075d3bc481a86b8b7eacdf Mon Sep 17 00:00:00 2001 From: prxgr4mm3r Date: Mon, 19 Feb 2024 19:57:52 +0200 Subject: [PATCH] fixes --- src/commands/contract/generate/tests.ts | 97 +++++++++++++++++++ .../{test/generate.ts => generate/types.ts} | 4 +- src/commands/contract/new.ts | 1 - .../contract/{test/index.ts => test.ts} | 18 ++-- src/commands/init/index.ts | 34 ++++--- src/lib/tasks.ts | 26 +++-- 6 files changed, 144 insertions(+), 36 deletions(-) create mode 100644 src/commands/contract/generate/tests.ts rename src/commands/contract/{test/generate.ts => generate/types.ts} (90%) rename src/commands/contract/{test/index.ts => test.ts} (93%) diff --git a/src/commands/contract/generate/tests.ts b/src/commands/contract/generate/tests.ts new file mode 100644 index 00000000..d97f8b8a --- /dev/null +++ b/src/commands/contract/generate/tests.ts @@ -0,0 +1,97 @@ +import { Args, Flags } from "@oclif/core"; +import { getTemplates, prepareTestFiles, processTemplates } from "../../../lib/index.js"; +import { Contract } from "../../../lib/contract.js"; +import { SwankyCommand } from "../../../lib/swankyCommand.js"; +import { ConfigError, FileError } from "../../../lib/errors.js"; +import path from "node:path"; +import { existsSync } from "node:fs"; +import inquirer from "inquirer"; +import { pascalCase } from "change-case"; + +export class GenerateTests extends SwankyCommand { + static description = "Generate types from compiled contract metadata"; + + static args = { + contractName: Args.string({ + name: "contractName", + required: true, + description: "Name of the contract", + }), + }; + + static flags = { + mocha: Flags.boolean({ + default: false, + description: "Generate tests with mocha", + }), + }; + + async run(): Promise { + const { args, flags } = await this.parse(GenerateTests); + + const contractRecord = this.swankyConfig.contracts[args.contractName]; + if (!contractRecord) { + throw new ConfigError( + `Cannot find a contract named ${args.contractName} in swanky.config.json` + ); + } + + const contract = new Contract(contractRecord); + + if (!(await contract.pathExists())) { + throw new FileError( + `Path to contract ${args.contractName} does not exist: ${contract.contractPath}` + ); + } + + const artifactsCheck = await contract.artifactsExist(); + + if (!artifactsCheck.result) { + throw new FileError( + `No artifact file found at path: ${artifactsCheck.missingPaths.toString()}` + ); + } + + const templates = getTemplates(); + + const testsPath = path.resolve(process.cwd(), "tests"); + + let owerwrite = true; + if (!flags.mocha) + { + if (existsSync(path.resolve(testsPath, "test_helpers"))) { + owerwrite = (await inquirer.prompt({ + type: "confirm", + name: "overwrite", + message: "Test helpers already exist. Overwrite?", + default: false, + })).overwrite; + } + if (owerwrite) { + await this.spinner.runCommand(async () => { + await prepareTestFiles("e2e", templates.templatesPath, process.cwd(), args.contractName); + }, "Generating test helpers"); + } + } else { + if (existsSync(path.resolve(testsPath, args.contractName, "index.test.ts"))) { + owerwrite = (await inquirer.prompt({ + type: "confirm", + name: "overwrite", + message: `Mocha tests for ${args.contractName} are already exist. Overwrite?`, + default: false, + })).overwrite; + } + if (owerwrite) { + await this.spinner.runCommand(async () => { + await prepareTestFiles("mocha", templates.templatesPath, process.cwd(), args.contractName); + }, `Generating tests for ${args.contractName} with mocha`); + await this.spinner.runCommand(async () => { + await processTemplates(process.cwd(), { + contract_name: args.contractName, + contract_name_pascal: pascalCase(args.contractName), + }) + }, 'Processing templates') + } + } + } +} diff --git a/src/commands/contract/test/generate.ts b/src/commands/contract/generate/types.ts similarity index 90% rename from src/commands/contract/test/generate.ts rename to src/commands/contract/generate/types.ts index e498b9fb..506f0c9c 100644 --- a/src/commands/contract/test/generate.ts +++ b/src/commands/contract/generate/types.ts @@ -4,7 +4,7 @@ import { Contract } from "../../../lib/contract.js"; import { SwankyCommand } from "../../../lib/swankyCommand.js"; import { ConfigError, FileError } from "../../../lib/errors.js"; -export class ContractTestTypegen extends SwankyCommand { +export class GenerateTypes extends SwankyCommand { static description = "Generate types from compiled contract metadata"; static args = { @@ -16,7 +16,7 @@ export class ContractTestTypegen extends SwankyCommand { - const { args } = await this.parse(ContractTestTypegen); + const { args } = await this.parse(GenerateTypes); const contractRecord = this.swankyConfig.contracts[args.contractName]; if (!contractRecord) { diff --git a/src/commands/contract/new.ts b/src/commands/contract/new.ts index 0936663f..c455a801 100644 --- a/src/commands/contract/new.ts +++ b/src/commands/contract/new.ts @@ -93,7 +93,6 @@ export class NewContract extends SwankyCommand { ); await ensureDir(path.resolve(projectPath, "artifacts", args.contractName)); - await ensureDir(path.resolve(projectPath, "tests", args.contractName)); await this.spinner.runCommand(async () => { this.swankyConfig.contracts[args.contractName] = { diff --git a/src/commands/contract/test/index.ts b/src/commands/contract/test.ts similarity index 93% rename from src/commands/contract/test/index.ts rename to src/commands/contract/test.ts index 10479a2d..774f564e 100644 --- a/src/commands/contract/test/index.ts +++ b/src/commands/contract/test.ts @@ -3,13 +3,13 @@ import { Flags, Args } from "@oclif/core"; import path from "node:path"; import { globby } from "globby"; import Mocha from "mocha"; -import { emptyDir } from "fs-extra/esm"; +import { emptyDir, pathExists } from "fs-extra/esm"; import shell from "shelljs"; -import { Contract } from "../../../lib/contract.js"; -import { SwankyCommand } from "../../../lib/swankyCommand.js"; -import { ConfigError, FileError, InputError, ProcessError, TestError } from "../../../lib/errors.js"; +import { Contract } from "../../lib/contract.js"; +import { SwankyCommand } from "../../lib/swankyCommand.js"; +import { ConfigError, FileError, InputError, ProcessError, TestError } from "../../lib/errors.js"; import { spawn } from "node:child_process"; -import { Spinner } from "../../../lib/index.js"; +import { Spinner } from "../../lib/index.js"; declare global { var contractTypesPath: string; // eslint-disable-line no-var @@ -53,8 +53,6 @@ export class TestContract extends SwankyCommand { ? Object.keys(this.swankyConfig.contracts) : [args.contractName]; - const testDir = path.resolve("tests"); - const spinner = new Spinner(); for (const contractName of contractNames) { @@ -130,6 +128,12 @@ export class TestContract extends SwankyCommand { ); } else { + const testDir = path.resolve("tests"); + + if (!pathExists(testDir)) { + throw new FileError(`Tests folder does not exist: ${testDir}`); + } + const artifactsCheck = await contract.artifactsExist(); if (!artifactsCheck.result) { diff --git a/src/commands/init/index.ts b/src/commands/init/index.ts index 01050221..aefde1bb 100644 --- a/src/commands/init/index.ts +++ b/src/commands/init/index.ts @@ -1,22 +1,23 @@ import { Args, Flags } from "@oclif/core"; import path from "node:path"; -import { ensureDir, writeJSON, pathExists, copy, outputFile, readJSON, remove } from "fs-extra/esm"; -import { stat, readdir, readFile } from "fs/promises"; +import { copy, ensureDir, outputFile, pathExists, readJSON, remove, writeJSON } from "fs-extra/esm"; +import { readdir, readFile, stat } from "fs/promises"; import { execaCommand, execaCommandSync } from "execa"; import { paramCase, pascalCase, snakeCase } from "change-case"; import inquirer from "inquirer"; import TOML from "@iarna/toml"; import { choice, email, name, pickTemplate } from "../../lib/prompts.js"; import { + ChainAccount, checkCliDependencies, copyCommonTemplateFiles, copyContractTemplateFiles, downloadNode, + getTemplates, installDeps, - ChainAccount, + prepareTestFiles, processTemplates, swankyNode, - getTemplates, copyTestHelpers, } from "../../lib/index.js"; import { DEFAULT_ASTAR_NETWORK_URL, @@ -26,7 +27,7 @@ import { } from "../../lib/consts.js"; import { SwankyCommand } from "../../lib/swankyCommand.js"; import { InputError, UnknownError } from "../../lib/errors.js"; -import { GlobEntry, globby } from "globby"; +import { globby, GlobEntry } from "globby"; import { merge } from "lodash-es"; import inquirerFuzzyPath from "inquirer-fuzzy-path"; import { SwankyConfig } from "../../types/index.js"; @@ -91,6 +92,7 @@ export class Init extends SwankyCommand { super(argv, config); (this.constructor as typeof SwankyCommand).ENSURE_SWANKY_CONFIG = false; } + projectPath = ""; configBuilder: Partial = { @@ -188,7 +190,6 @@ export class Init extends SwankyCommand { Object.keys(this.configBuilder.contracts!).forEach(async (contractName) => { await ensureDir(path.resolve(this.projectPath, "artifacts", contractName)); - await ensureDir(path.resolve(this.projectPath, "tests", contractName)); }); this.taskQueue.push({ @@ -214,7 +215,7 @@ export class Init extends SwankyCommand { runningMessage, successMessage, failMessage, - shouldExitOnError + shouldExitOnError, ); if (result && callback) { callback(result as string); @@ -271,8 +272,9 @@ export class Init extends SwankyCommand { if (contractTemplate === "psp22") { this.taskQueue.push({ - task: copyTestHelpers, + task: prepareTestFiles, args: [ + "e2e", path.resolve(templates.templatesPath), this.projectPath, ], @@ -317,7 +319,7 @@ export class Init extends SwankyCommand { } catch (cause) { throw new InputError( `Error reading target directory [${chalk.yellowBright(pathToExistingProject)}]`, - { cause } + { cause }, ); } @@ -337,7 +339,7 @@ export class Init extends SwankyCommand { const candidatesList: CopyCandidates = await getCopyCandidatesList( pathToExistingProject, - copyGlobsList + copyGlobsList, ); const testDir = await detectTests(pathToExistingProject); @@ -505,10 +507,10 @@ async function confirmCopyList(candidatesList: CopyCandidates) { ( item: PathEntry & { group: "contracts" | "crates" | "tests"; - } + }, ) => { resultingList[item.group]?.push(item); - } + }, ); return resultingList; } @@ -535,7 +537,7 @@ async function detectTests(pathToExistingProject: string): Promise { const { selectedDirectory } = await inquirer.prompt([ { @@ -606,7 +608,7 @@ async function getCopyCandidatesList( pathsToCopy: { contractsDirectories: string[]; cratesDirectories: string[]; - } + }, ) { const detectedPaths = { contracts: await getDirsAndFiles(projectPath, pathsToCopy.contractsDirectories), @@ -627,7 +629,7 @@ async function getGlobPaths(projectPath: string, globList: string[], isDirOnly: onlyDirectories: isDirOnly, deep: 1, objectMode: true, - } + }, ); } diff --git a/src/lib/tasks.ts b/src/lib/tasks.ts index b43e7c2b..31c5c6dd 100644 --- a/src/lib/tasks.ts +++ b/src/lib/tasks.ts @@ -53,20 +53,26 @@ export async function copyContractTemplateFiles( path.resolve(contractTemplatePath, "contract"), path.resolve(projectPath, "contracts", contractName) ); - await copy( - path.resolve(contractTemplatePath, "test"), - path.resolve(projectPath, "tests", contractName) - ); } -export async function copyTestHelpers( +export async function prepareTestFiles( + testType: "e2e" | "mocha", templatePath: string, - projectPath: string + projectPath: string, + contractName: string ) { - await copy( - path.resolve(templatePath, "test_helpers"), - path.resolve(projectPath, "tests", "test_helpers") - ); + if (testType === "e2e") { + await copy( + path.resolve(templatePath, "test_helpers"), + path.resolve(projectPath, "tests", "test_helpers") + ); + } + else { + await copy( + path.resolve(templatePath, "contracts", contractName, "test"), + path.resolve(projectPath, "tests", contractName) + ); + } } export async function processTemplates(projectPath: string, templateData: Record) {