diff --git a/taqueria-plugin-ligo/compile.ts b/taqueria-plugin-ligo/compile.ts index 10dc71c29..a130f2089 100644 --- a/taqueria-plugin-ligo/compile.ts +++ b/taqueria-plugin-ligo/compile.ts @@ -161,7 +161,7 @@ const compileExprs = (parsedArgs: Opts, sourceFile: string, exprKind: ExprKind): }) .then(mergeArtifactsOutput(sourceFile)); -const compileContractWithStorageAndParameter = async (parsedArgs: Opts, sourceFile: string) => { +const compileContractWithStorageAndParameter = async (parsedArgs: Opts, sourceFile: string): Promise => { const contractCompileResult = await compileContract(parsedArgs, sourceFile); if (contractCompileResult.artifact === COMPILE_ERR_MSG) return [contractCompileResult]; @@ -226,7 +226,6 @@ const mergeArtifactsOutput = (sourceFile: string) => export const compile = (parsedArgs: Opts): Promise => { const sourceFile = parsedArgs.sourceFile; - if (!sourceFile) return sendAsyncErr('No source file specified.'); let p: Promise; if (isStoragesFile(sourceFile)) p = compileExprs(parsedArgs, sourceFile, 'storage'); else if (isParametersFile(sourceFile)) p = compileExprs(parsedArgs, sourceFile, 'parameter'); diff --git a/taqueria-plugin-ligo/index.ts b/taqueria-plugin-ligo/index.ts index 7958041d9..7ff3886d0 100644 --- a/taqueria-plugin-ligo/index.ts +++ b/taqueria-plugin-ligo/index.ts @@ -16,6 +16,13 @@ Plugin.create(i18n => ({ handler: 'proxy', encoding: 'json', }), + Task.create({ + task: 'test', + command: 'test ', + description: 'Test a smart contract written in LIGO', + handler: 'proxy', + encoding: 'json', + }), ], templates: [ Template.create({ diff --git a/taqueria-plugin-ligo/ligo.ts b/taqueria-plugin-ligo/ligo.ts index 347570e4c..61109724a 100644 --- a/taqueria-plugin-ligo/ligo.ts +++ b/taqueria-plugin-ligo/ligo.ts @@ -1,6 +1,7 @@ import { sendAsyncErr } from '@taqueria/node-sdk'; import { RequestArgs } from '@taqueria/node-sdk/types'; import compile from './compile'; +import { test } from './test'; interface Opts extends RequestArgs.ProxyRequestArgs { sourceFile: string; @@ -10,8 +11,8 @@ export const ligo = (parsedArgs: Opts): Promise => { switch (parsedArgs.task) { case 'compile': return compile(parsedArgs); - // case 'test': - // return test(parsedArgs); // TODO: to be implemented in the future + case 'test': + return test(parsedArgs); default: return sendAsyncErr(`${parsedArgs.task} is not an understood task by the LIGO plugin`); } diff --git a/taqueria-plugin-ligo/test.ts b/taqueria-plugin-ligo/test.ts new file mode 100644 index 000000000..a02fdaa72 --- /dev/null +++ b/taqueria-plugin-ligo/test.ts @@ -0,0 +1,53 @@ +import { execCmd, getArch, sendAsyncErr, sendErr, sendJsonRes, sendWarn } from '@taqueria/node-sdk'; +import { RequestArgs } from '@taqueria/node-sdk/types'; +import { access, readFile, writeFile } from 'fs/promises'; +import { basename, extname, join } from 'path'; + +interface Opts extends RequestArgs.t { + sourceFile: string; +} + +type TableRow = { contract: string; testResults: string }; + +const getInputFilename = (parsedArgs: Opts, sourceFile: string): string => + join(parsedArgs.config.contractsDir, sourceFile); + +const getTestContractCmd = (parsedArgs: Opts, sourceFile: string): string => { + const projectDir = process.env.PROJECT_DIR ?? parsedArgs.projectDir; + if (!projectDir) throw `No project directory provided`; + const baseCmd = + `DOCKER_DEFAULT_PLATFORM=linux/amd64 docker run --rm -v \"${projectDir}\":/project -w /project -u $(id -u):$(id -g) ligolang/ligo:next run test`; + const inputFile = getInputFilename(parsedArgs, sourceFile); + const cmd = `${baseCmd} ${inputFile}`; + return cmd; +}; + +const testContract = (parsedArgs: Opts, sourceFile: string): Promise => + getArch() + .then(() => getTestContractCmd(parsedArgs, sourceFile)) + .then(execCmd) + .then(({ stdout, stderr }) => { + if (stderr.length > 0) sendWarn(stderr); + const result = '🎉 All tests passed 🎉'; + return { + contract: sourceFile, + testResults: stdout.length > 0 ? `${stdout}\n${result}` : result, + }; + }) + .catch(err => { + sendErr(`\n=== For ${sourceFile} ===`); + sendErr(err.message.replace(/Command failed.+?\n/, '')); + return { + contract: sourceFile, + testResults: 'Some tests failed :(', + }; + }); + +export const test = (parsedArgs: Opts): Promise => { + const sourceFile = parsedArgs.sourceFile; + return testContract(parsedArgs, sourceFile).then(results => [results]).then(sendJsonRes).catch(err => + sendAsyncErr(err, false) + ); +}; + +export default test;