From 1ad307ccaa09844fd7b2d0fecbadb03fcc7adde5 Mon Sep 17 00:00:00 2001 From: Michael Weichert Date: Fri, 6 Oct 2023 13:24:30 -0400 Subject: [PATCH] Fixes #1909, added test suite for new LIGO plugin, based on LIGO v1. --- lerna.json | 2 +- package-lock.json | 98 +-- package.json | 2 +- taqueria-analytics/package.json | 4 +- taqueria-lib-ligo/common.ts | 8 + taqueria-lib-ligo/compile.ts | 3 +- taqueria-lib-ligo/package.json | 4 +- taqueria-plugin-archetype/package.json | 4 +- taqueria-plugin-contract-types/package.json | 4 +- taqueria-plugin-core/package.json | 4 +- taqueria-plugin-flextesa/package.json | 6 +- taqueria-plugin-ipfs-pinata/package.json | 4 +- taqueria-plugin-jest/package.json | 6 +- taqueria-plugin-ligo-legacy/package.json | 6 +- taqueria-plugin-ligo/package.json | 6 +- taqueria-plugin-metadata/package.json | 6 +- taqueria-plugin-mock/package.json | 4 +- taqueria-plugin-octez-client/package.json | 4 +- taqueria-plugin-smartpy-legacy/package.json | 4 +- taqueria-plugin-smartpy/package.json | 4 +- taqueria-plugin-taquito/package.json | 4 +- taqueria-protocol/package.json | 2 +- taqueria-sdk/package.json | 4 +- taqueria-toolkit/package.json | 4 +- taqueria-vscode-extension-web-ui/package.json | 2 +- taqueria-vscode-extension/package.json | 6 +- tests/e2e/data/ligo-data/IncDec.jsligo | 17 +- tests/e2e/data/ligo-data/IncDec.tz | 6 - tests/e2e/data/ligo-data/entry.jsligo | 2 +- .../expected-IncDec.parameterList.jsligo | 6 + .../expected-entry.parameterList.jsligo | 6 + .../ligo-data/hello-tacos-invalid-tests.mligo | 13 + .../data/ligo-data/hello-tacos-tests.mligo | 12 + tests/e2e/data/ligo-data/hello-tacos.mligo | 9 + .../ligo-data/hello-tacos.parameters.mligo | 1 + tests/e2e/data/ligo-data/pokeGame.jsligo | 8 + ...okeGame.parameterList-with-comments.jsligo | 4 + .../ligo-data/pokeGame.parameterList.jsligo | 3 + .../pokeGame.storageList-with-comments.jsligo | 5 + .../ligo-data/pokeGame.storageList.jsligo | 3 + .../e2e/ligo-legacy-plugin-e2e-tests.spec.ts | 2 +- tests/e2e/ligo-plugin-e2e-tests.spec.ts | 747 ++++++++++++++++++ tests/package.json | 2 +- 43 files changed, 934 insertions(+), 117 deletions(-) delete mode 100644 tests/e2e/data/ligo-data/IncDec.tz create mode 100644 tests/e2e/data/ligo-data/expected-IncDec.parameterList.jsligo create mode 100644 tests/e2e/data/ligo-data/expected-entry.parameterList.jsligo create mode 100644 tests/e2e/data/ligo-data/hello-tacos-invalid-tests.mligo create mode 100644 tests/e2e/data/ligo-data/hello-tacos-tests.mligo create mode 100644 tests/e2e/data/ligo-data/hello-tacos.mligo create mode 100644 tests/e2e/data/ligo-data/hello-tacos.parameters.mligo create mode 100644 tests/e2e/data/ligo-data/pokeGame.jsligo create mode 100644 tests/e2e/data/ligo-data/pokeGame.parameterList-with-comments.jsligo create mode 100644 tests/e2e/data/ligo-data/pokeGame.parameterList.jsligo create mode 100644 tests/e2e/data/ligo-data/pokeGame.storageList-with-comments.jsligo create mode 100644 tests/e2e/data/ligo-data/pokeGame.storageList.jsligo create mode 100644 tests/e2e/ligo-plugin-e2e-tests.spec.ts diff --git a/lerna.json b/lerna.json index cfe026d98..089777aff 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", - "version": "0.40.22", + "version": "0.40.23", "packages": [ "taqueria-protocol", "taqueria-lib*", diff --git a/package-lock.json b/package-lock.json index 913d45e54..b0b4e2e54 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@taqueria/root", - "version": "0.40.22", + "version": "0.40.23", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@taqueria/root", - "version": "0.40.22", + "version": "0.40.23", "license": "Apache-2.0", "workspaces": [ "./taqueria-protocol", @@ -23122,10 +23122,10 @@ }, "taqueria-analytics": { "name": "@taqueria/analytics", - "version": "0.40.22", + "version": "0.40.23", "license": "Apache-2.0", "dependencies": { - "@taqueria/protocol": "^0.40.22", + "@taqueria/protocol": "^0.40.23", "node-machine-id-xz": "^1.0.2" }, "devDependencies": { @@ -23135,10 +23135,10 @@ }, "taqueria-lib-ligo": { "name": "@taqueria/lib-ligo", - "version": "0.40.22", + "version": "0.40.23", "license": "Apache-2.0", "dependencies": { - "@taqueria/node-sdk": "^0.40.22", + "@taqueria/node-sdk": "^0.40.23", "fast-glob": "^3.3.1" }, "devDependencies": { @@ -23148,10 +23148,10 @@ }, "taqueria-plugin-archetype": { "name": "@taqueria/plugin-archetype", - "version": "0.40.22", + "version": "0.40.23", "license": "Apache-2.0", "dependencies": { - "@taqueria/node-sdk": "^0.40.22", + "@taqueria/node-sdk": "^0.40.23", "fast-glob": "^3.3.1", "ts-pattern": "^5.0.5" }, @@ -23162,10 +23162,10 @@ }, "taqueria-plugin-contract-types": { "name": "@taqueria/plugin-contract-types", - "version": "0.40.22", + "version": "0.40.23", "license": "ISC", "dependencies": { - "@taqueria/node-sdk": "^0.40.22", + "@taqueria/node-sdk": "^0.40.23", "@taquito/michel-codec": "^17.3.1", "@taquito/signer": "^17.3.1", "@taquito/taquito": "^17.3.1", @@ -23266,10 +23266,10 @@ }, "taqueria-plugin-core": { "name": "@taqueria/plugin-core", - "version": "0.40.22", + "version": "0.40.23", "license": "Apache-2.0", "dependencies": { - "@taqueria/node-sdk": "^0.40.22" + "@taqueria/node-sdk": "^0.40.23" }, "devDependencies": { "tsup": "^7.2.0", @@ -23281,11 +23281,11 @@ }, "taqueria-plugin-flextesa": { "name": "@taqueria/plugin-flextesa", - "version": "0.40.22", + "version": "0.40.23", "license": "Apache-2.0", "dependencies": { - "@taqueria/node-sdk": "^0.40.22", - "@taqueria/protocol": "^0.40.22", + "@taqueria/node-sdk": "^0.40.23", + "@taqueria/protocol": "^0.40.23", "async-retry": "^1.3.3", "fast-glob": "^3.2.12", "portfinder": "^1.0.32", @@ -23299,11 +23299,11 @@ }, "taqueria-plugin-ipfs-pinata": { "name": "@taqueria/plugin-ipfs-pinata", - "version": "0.40.22", + "version": "0.40.23", "license": "Apache-2.0", "dependencies": { "@helia/unixfs": "^1.4.2", - "@taqueria/node-sdk": "^0.40.22", + "@taqueria/node-sdk": "^0.40.23", "dotenv": "^16.3.1", "form-data": "^4.0.0", "helia": "^2.0.3", @@ -23317,11 +23317,11 @@ }, "taqueria-plugin-jest": { "name": "@taqueria/plugin-jest", - "version": "0.40.22", + "version": "0.40.23", "license": "Apache-2.0", "dependencies": { - "@taqueria/node-sdk": "^0.40.22", - "@taqueria/plugin-contract-types": "^0.40.22", + "@taqueria/node-sdk": "^0.40.23", + "@taqueria/plugin-contract-types": "^0.40.23", "@taquito/signer": "^17.3.1", "@taquito/taquito": "^17.3.1", "@taquito/utils": "^17.3.1", @@ -23422,11 +23422,11 @@ }, "taqueria-plugin-ligo": { "name": "@taqueria/plugin-ligo", - "version": "0.40.22", + "version": "0.40.23", "license": "Apache-2.0", "dependencies": { - "@taqueria/lib-ligo": "^0.40.22", - "@taqueria/node-sdk": "^0.40.22", + "@taqueria/lib-ligo": "^0.40.23", + "@taqueria/node-sdk": "^0.40.23", "fast-glob": "^3.3.1" }, "devDependencies": { @@ -23436,11 +23436,11 @@ }, "taqueria-plugin-ligo-legacy": { "name": "@taqueria/plugin-ligo-legacy", - "version": "0.40.22", + "version": "0.40.23", "license": "Apache-2.0", "dependencies": { - "@taqueria/lib-ligo": "^0.40.22", - "@taqueria/node-sdk": "^0.40.22", + "@taqueria/lib-ligo": "^0.40.23", + "@taqueria/node-sdk": "^0.40.23", "fast-glob": "^3.3.1" }, "devDependencies": { @@ -23450,11 +23450,11 @@ }, "taqueria-plugin-metadata": { "name": "@taqueria/plugin-metadata", - "version": "0.40.22", + "version": "0.40.23", "license": "Apache-2.0", "dependencies": { - "@taqueria/node-sdk": "^0.40.22", - "@taqueria/protocol": "^0.40.22", + "@taqueria/node-sdk": "^0.40.23", + "@taqueria/protocol": "^0.40.23", "prompts": "^2.4.2" }, "devDependencies": { @@ -23465,18 +23465,18 @@ }, "taqueria-plugin-mock": { "name": "@taqueria/plugin-mock", - "version": "0.40.22", + "version": "0.40.23", "license": "Apache-2.0", "dependencies": { - "@taqueria/node-sdk": "^0.40.22" + "@taqueria/node-sdk": "^0.40.23" } }, "taqueria-plugin-octez-client": { "name": "@taqueria/plugin-octez-client", - "version": "0.40.22", + "version": "0.40.23", "license": "Apache-2.0", "dependencies": { - "@taqueria/node-sdk": "^0.40.22", + "@taqueria/node-sdk": "^0.40.23", "fast-glob": "^3.3.1" }, "devDependencies": { @@ -23489,10 +23489,10 @@ }, "taqueria-plugin-smartpy": { "name": "@taqueria/plugin-smartpy", - "version": "0.40.22", + "version": "0.40.23", "license": "Apache-2.0", "dependencies": { - "@taqueria/node-sdk": "^0.40.22", + "@taqueria/node-sdk": "^0.40.23", "fast-glob": "^3.3.1" }, "devDependencies": { @@ -23505,10 +23505,10 @@ }, "taqueria-plugin-smartpy-legacy": { "name": "@taqueria/plugin-smartpy-legacy", - "version": "0.40.22", + "version": "0.40.23", "license": "Apache-2.0", "dependencies": { - "@taqueria/node-sdk": "^0.40.22", + "@taqueria/node-sdk": "^0.40.23", "fast-glob": "^3.3.1" }, "devDependencies": { @@ -23521,10 +23521,10 @@ }, "taqueria-plugin-taquito": { "name": "@taqueria/plugin-taquito", - "version": "0.40.22", + "version": "0.40.23", "license": "Apache-2.0", "dependencies": { - "@taqueria/node-sdk": "^0.40.22", + "@taqueria/node-sdk": "^0.40.23", "@taquito/michel-codec": "^17.3.1", "@taquito/signer": "^17.3.1", "@taquito/taquito": "^17.3.1", @@ -23622,7 +23622,7 @@ }, "taqueria-protocol": { "name": "@taqueria/protocol", - "version": "0.40.22", + "version": "0.40.23", "license": "Apache-2.0", "dependencies": { "@peculiar/webcrypto": "^1.4.3", @@ -23647,10 +23647,10 @@ }, "taqueria-sdk": { "name": "@taqueria/node-sdk", - "version": "0.40.22", + "version": "0.40.23", "license": "Apache-2.0", "dependencies": { - "@taqueria/protocol": "^0.40.22", + "@taqueria/protocol": "^0.40.23", "@taquito/signer": "^17.3.1", "@taquito/taquito": "^17.3.1", "@taquito/utils": "^17.3.1", @@ -23762,10 +23762,10 @@ }, "taqueria-toolkit": { "name": "@taqueria/toolkit", - "version": "0.40.22", + "version": "0.40.23", "license": "Apache-2.0", "dependencies": { - "@taqueria/protocol": "^0.40.22", + "@taqueria/protocol": "^0.40.23", "cross-spawn": "^7.0.3", "yargs": "^17.7.2" }, @@ -23782,12 +23782,12 @@ }, "taqueria-vscode-extension": { "name": "taqueria", - "version": "0.40.22", + "version": "0.40.23", "license": "Apache-2.0", "dependencies": { "@microsoft/signalr": "^6.0.18", - "@taqueria/analytics": "^0.40.22", - "@taqueria/protocol": "^0.40.22", + "@taqueria/analytics": "^0.40.23", + "@taqueria/protocol": "^0.40.23", "cli-table3": "^0.6.3", "comment-json": "^4.2.3", "eventsource": "^2.0.2", @@ -23819,7 +23819,7 @@ } }, "taqueria-vscode-extension-web-ui": { - "version": "0.40.22", + "version": "0.40.23", "dependencies": { "@taquito/michel-codec": "^17.3.1", "@taquito/michelson-encoder": "^17.3.1", @@ -23906,7 +23906,7 @@ }, "tests": { "name": "@taqueria/tests", - "version": "0.40.22", + "version": "0.40.23", "license": "MIT", "devDependencies": { "@gmrchk/cli-testing-library": "^0.1.2", diff --git a/package.json b/package.json index 48bc85338..3d38b47f7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@taqueria/root", - "version": "0.40.22", + "version": "0.40.23", "description": "An easy to use opinionated tool for building, testing, and deploying Tezos software", "main": "index.ts", "directories": { diff --git a/taqueria-analytics/package.json b/taqueria-analytics/package.json index c7925229a..6999697f4 100644 --- a/taqueria-analytics/package.json +++ b/taqueria-analytics/package.json @@ -1,6 +1,6 @@ { "name": "@taqueria/analytics", - "version": "0.40.22", + "version": "0.40.23", "description": "A TypeScript SDK submitting events for Taqueria activity", "main": "./index.js", "source": "./index.ts", @@ -35,7 +35,7 @@ }, "homepage": "https://github.com/pinnacle-labs/taqueria#readme", "dependencies": { - "@taqueria/protocol": "^0.40.22", + "@taqueria/protocol": "^0.40.23", "node-machine-id-xz": "^1.0.2" }, "devDependencies": { diff --git a/taqueria-lib-ligo/common.ts b/taqueria-lib-ligo/common.ts index 2cc57dd9c..d506c3fa0 100644 --- a/taqueria-lib-ligo/common.ts +++ b/taqueria-lib-ligo/common.ts @@ -39,6 +39,14 @@ export const formatLigoError = (err: Error): Error => { ) { result = `By convention, Taqueria expects you to import your contract with Contract as the module name.\nFor instance, if you have a contract in a file called "increment.mligo", in your parameter/storage list file you must include #import "Increment.mligo" "Contract" for compilation to be successful.`; + } else { + const regex = /contracts\/(.+): No such file or directory/; + const match = regex.exec(result); + if (match) { + const filename = match[1]; + result = + `The file ${filename} was not found. Please ensure that the file exists and that it is in the contracts directory.`; + } } err.message = result diff --git a/taqueria-lib-ligo/compile.ts b/taqueria-lib-ligo/compile.ts index badc4b72b..5eac0be66 100644 --- a/taqueria-lib-ligo/compile.ts +++ b/taqueria-lib-ligo/compile.ts @@ -222,6 +222,7 @@ export const inject = (commonObj: Common) => { [], ); } catch (err) { + const formattedErr = err instanceof Error ? formatLigoError(err) : err; emitExternalError(err, sourceFile); return []; } @@ -455,7 +456,7 @@ export const compile = async (commonObj: Common, parsedArgs: Opts): Promise, storage]; @@ -11,7 +11,7 @@ namespace IncDec { const decrement = (delta: int, store: storage): ret => [list([]), store - delta]; @entry - const reset = (_: unit, _: storage): ret => [list([]), 0] + const reset = (_: unit, _s: storage): ret => [list([]), 0] }; /* Tests for main access point */ @@ -20,9 +20,8 @@ const test_initial_storage = ( () => { let initial_storage = 42; - let [taddr, _, _] = - Test.originate_module(contract_of (IncDec), initial_storage, 0 as tez); - return assert(Test.get_storage(taddr) == initial_storage) + let contract = Test.originate(contract_of (IncDec), initial_storage, 0 as tez); + return assert(Test.get_storage(contract.addr) == initial_storage) } )(); @@ -30,10 +29,8 @@ const test_increment = ( () => { let initial_storage = 42; - let [taddr, _, _] = - Test.originate_module(contract_of (IncDec), initial_storage, 0 as tez); - let contr = Test.to_contract(taddr); - let _ = Test.transfer_to_contract_exn(contr, (Increment(1)), 1 as mutez); - return assert(Test.get_storage(taddr) == initial_storage + 1) + let contract = Test.originate(contract_of (IncDec), initial_storage, 0 as tez); + Test.transfer_exn(contract.addr, (Increment (1)), 1mutez); + return assert(Test.get_storage(contract.addr) == initial_storage + 1) } )(); \ No newline at end of file diff --git a/tests/e2e/data/ligo-data/IncDec.tz b/tests/e2e/data/ligo-data/IncDec.tz deleted file mode 100644 index 6f175d473..000000000 --- a/tests/e2e/data/ligo-data/IncDec.tz +++ /dev/null @@ -1,6 +0,0 @@ -{ parameter (or (or (int %decrement) (int %increment)) (unit %reset)) ; - storage int ; - code { UNPAIR ; - IF_LEFT { IF_LEFT { SWAP ; SUB } { ADD } } { DROP 2 ; PUSH int 0 } ; - NIL operation ; - PAIR } } \ No newline at end of file diff --git a/tests/e2e/data/ligo-data/entry.jsligo b/tests/e2e/data/ligo-data/entry.jsligo index 4a3732da4..9e3669641 100644 --- a/tests/e2e/data/ligo-data/entry.jsligo +++ b/tests/e2e/data/ligo-data/entry.jsligo @@ -12,5 +12,5 @@ [list([]), store - delta]; @entry - const reset = (_ : unit, _ : storage) : ret => + const reset = (_ : unit, _s : storage) : ret => [list([]), 0]; \ No newline at end of file diff --git a/tests/e2e/data/ligo-data/expected-IncDec.parameterList.jsligo b/tests/e2e/data/ligo-data/expected-IncDec.parameterList.jsligo new file mode 100644 index 000000000..5b19b7586 --- /dev/null +++ b/tests/e2e/data/ligo-data/expected-IncDec.parameterList.jsligo @@ -0,0 +1,6 @@ +#import "IncDec.jsligo" "Contract" + +// When this file was created, the smart contract was defined with an entrypoint using `@entry` that was within a namespace. As such, the examples below are written with that assumption in mind. + +// IMPORTANT: We suggest always explicitly typing your parameter values: +// E.g.: `const parameter: int = 10` or `const parameter: Contract.parameter = 10` \ No newline at end of file diff --git a/tests/e2e/data/ligo-data/expected-entry.parameterList.jsligo b/tests/e2e/data/ligo-data/expected-entry.parameterList.jsligo new file mode 100644 index 000000000..acf7b5505 --- /dev/null +++ b/tests/e2e/data/ligo-data/expected-entry.parameterList.jsligo @@ -0,0 +1,6 @@ +#import "entry.jsligo" "Contract" + +// When this file was created, the smart contract was defined with an entrypoint using `@entry` that was not within a namespace. As such, the examples below are written with that assumption in mind. + +// IMPORTANT: We suggest always explicitly typing your parameter values: +// E.g.: `const parameter: int = 10` or `const parameter: Contract.parameter = 10` \ No newline at end of file diff --git a/tests/e2e/data/ligo-data/hello-tacos-invalid-tests.mligo b/tests/e2e/data/ligo-data/hello-tacos-invalid-tests.mligo new file mode 100644 index 000000000..c9c9d99cb --- /dev/null +++ b/tests/e2e/data/ligo-data/hello-tacos-invalid-tests.mligo @@ -0,0 +1,13 @@ +#include "hello-tacos.mligo" + +let available_tacos = 100 + +let test_available_tacos = + let (taddr, _, _) = Test.originate main initial_storage 100tez in + assert (Test.get_storage taddr = available_tacos) + +let test_buy_tacos = + let (taddr, _, _) = Test.originate main initial_storage 100tez in + let contr = Test.to_contract taddr in + let _ = Test.transfer_to_contract_exn contr 1mutez in + assert (Test.get_storage taddr = test_available_tacos - 1) \ No newline at end of file diff --git a/tests/e2e/data/ligo-data/hello-tacos-tests.mligo b/tests/e2e/data/ligo-data/hello-tacos-tests.mligo new file mode 100644 index 000000000..13e5f28fa --- /dev/null +++ b/tests/e2e/data/ligo-data/hello-tacos-tests.mligo @@ -0,0 +1,12 @@ +#import "hello-tacos.mligo" "HelloTacos" + +let available_tacos = 100n + +let test_available_tacos = + let contract = Test.originate (contract_of HelloTacos) available_tacos 100tez in + assert (Test.get_storage contract.addr = available_tacos) + +let test_buy_tacos = + let res = HelloTacos.main(1n) (available_tacos) in (* The nature of the contract we don't have entrypoints + // The only way to test it is to call function itself *) + assert (res.1 = 99n) \ No newline at end of file diff --git a/tests/e2e/data/ligo-data/hello-tacos.mligo b/tests/e2e/data/ligo-data/hello-tacos.mligo new file mode 100644 index 000000000..9b56dd506 --- /dev/null +++ b/tests/e2e/data/ligo-data/hello-tacos.mligo @@ -0,0 +1,9 @@ +type available_tacos = nat + +type tacos_to_buy = nat + +[@entry] +let main (tacos_to_buy: tacos_to_buy) (available_tacos: available_tacos): operation list * available_tacos = + if tacos_to_buy > available_tacos + then (failwith "NOT_ENOUGH_TACOS": operation list * available_tacos) + else ([]: operation list), abs(available_tacos - tacos_to_buy) \ No newline at end of file diff --git a/tests/e2e/data/ligo-data/hello-tacos.parameters.mligo b/tests/e2e/data/ligo-data/hello-tacos.parameters.mligo new file mode 100644 index 000000000..06c556470 --- /dev/null +++ b/tests/e2e/data/ligo-data/hello-tacos.parameters.mligo @@ -0,0 +1 @@ +let decrement_by_1: tacos_to_buy = 1n \ No newline at end of file diff --git a/tests/e2e/data/ligo-data/pokeGame.jsligo b/tests/e2e/data/ligo-data/pokeGame.jsligo new file mode 100644 index 000000000..e3e2cb072 --- /dev/null +++ b/tests/e2e/data/ligo-data/pokeGame.jsligo @@ -0,0 +1,8 @@ +export type storage = set
; + +type return_ = [list, storage]; + +@entry +const poke = (_: unit, store: storage): return_ => { + return [list([]) as list, Set.add(Tezos.get_source(), store)] +}; \ No newline at end of file diff --git a/tests/e2e/data/ligo-data/pokeGame.parameterList-with-comments.jsligo b/tests/e2e/data/ligo-data/pokeGame.parameterList-with-comments.jsligo new file mode 100644 index 000000000..fb6ad8ac5 --- /dev/null +++ b/tests/e2e/data/ligo-data/pokeGame.parameterList-with-comments.jsligo @@ -0,0 +1,4 @@ +#import "pokeGame.jsligo" "Contract" + +// const commented_parameter: Contract.parameter = Poke(); +const parameter: parameter_of Contract = Poke(); \ No newline at end of file diff --git a/tests/e2e/data/ligo-data/pokeGame.parameterList.jsligo b/tests/e2e/data/ligo-data/pokeGame.parameterList.jsligo new file mode 100644 index 000000000..f4fd30b45 --- /dev/null +++ b/tests/e2e/data/ligo-data/pokeGame.parameterList.jsligo @@ -0,0 +1,3 @@ +#import "pokeGame.jsligo" "Contract" + +const default_parameter: parameter_of Contract = Poke(); \ No newline at end of file diff --git a/tests/e2e/data/ligo-data/pokeGame.storageList-with-comments.jsligo b/tests/e2e/data/ligo-data/pokeGame.storageList-with-comments.jsligo new file mode 100644 index 000000000..9497a3eeb --- /dev/null +++ b/tests/e2e/data/ligo-data/pokeGame.storageList-with-comments.jsligo @@ -0,0 +1,5 @@ +#import "pokeGame.jsligo" "Contract" + +// const commented_storage = Set.empty as set
; + +const default_storage = Set.empty as set
; \ No newline at end of file diff --git a/tests/e2e/data/ligo-data/pokeGame.storageList.jsligo b/tests/e2e/data/ligo-data/pokeGame.storageList.jsligo new file mode 100644 index 000000000..b8da90bf0 --- /dev/null +++ b/tests/e2e/data/ligo-data/pokeGame.storageList.jsligo @@ -0,0 +1,3 @@ +#import "pokeGame.jsligo" "Contract" + +const default_storage = Set.empty as set
; \ No newline at end of file diff --git a/tests/e2e/ligo-legacy-plugin-e2e-tests.spec.ts b/tests/e2e/ligo-legacy-plugin-e2e-tests.spec.ts index a7cbdb887..1413928a4 100644 --- a/tests/e2e/ligo-legacy-plugin-e2e-tests.spec.ts +++ b/tests/e2e/ligo-legacy-plugin-e2e-tests.spec.ts @@ -956,7 +956,7 @@ describe('Ligo Plugin E2E Testing for Taqueria CLI', () => { }); // https://github.com/pinnacle-labs/taqueria/issues/1907 - test('regression against #1907, compile task will compile storage/parameter expressions for variables which were commented out', async () => { + test('regression against #1907, compile task will NOT compile storage/parameter expressions for variables which were commented out', async () => { const { execute, cleanup, spawn, writeFile, ls, path: projectDir } = await prepareEnvironment(); // console.log(projectDir); diff --git a/tests/e2e/ligo-plugin-e2e-tests.spec.ts b/tests/e2e/ligo-plugin-e2e-tests.spec.ts new file mode 100644 index 000000000..013b925b8 --- /dev/null +++ b/tests/e2e/ligo-plugin-e2e-tests.spec.ts @@ -0,0 +1,747 @@ +import { exec as exec1 } from 'child_process'; +import { createHash } from 'crypto'; +import path from 'path'; +import util from 'util'; +const exec = util.promisify(exec1); +import { prepareEnvironment } from '@gmrchk/cli-testing-library'; +import { compile } from 'eta'; + +describe('Ligo Plugin E2E Testing for Taqueria CLI', () => { + describe('tasks that rarely change', () => { + test('ligo plugin help will show help', async () => { + const { execute, cleanup, spawn } = await prepareEnvironment(); + const { waitForText } = await spawn('taq', 'init test-project --debug'); + await waitForText("Project taq'ified!"); + + const { stdout } = await execute('taq', 'install ../taqueria-plugin-ligo', './test-project'); + expect(stdout).toContain('Plugin installed successfully'); + + const { stdout: stdout2 } = await execute('taq', '--help', './test-project'); + expect(stdout2).toEqual(expect.arrayContaining(['taq '])); + + await cleanup(); + }); + + test('compile will show contextual help', async () => { + const { execute, cleanup, spawn } = await prepareEnvironment(); + const { waitForText } = await spawn('taq', 'init test-project --debug'); + await waitForText("Project taq'ified!"); + const { stdout } = await execute('taq', 'install ../taqueria-plugin-ligo', './test-project'); + expect(stdout).toContain('Plugin installed successfully'); + + const { stdout: stdout2 } = await execute('taq', 'compile --help', './test-project'); + expect(stdout2).toEqual( + expect.arrayContaining(['Compile a smart contract written in a LIGO syntax to Michelson code, along with']), + ); + + await cleanup(); + }); + + test('compile will error if missing parameter', async () => { + const { execute, cleanup, spawn } = await prepareEnvironment(); + const { waitForText } = await spawn('taq', 'init test-project --debug'); + await waitForText("Project taq'ified!"); + + const { stdout } = await execute('taq', 'install ../taqueria-plugin-ligo', './test-project'); + expect(stdout).toContain('Plugin installed successfully'); + + const { stderr: compileErr } = await execute('taq', 'compile', './test-project'); + expect(compileErr).toEqual(expect.arrayContaining(['Not enough non-option arguments: got 0, need at least 1'])); + + await cleanup(); + }); + + test('ligo postInstall script runs after installation', async () => { + const { execute, cleanup, writeFile, ls, spawn, readFile, exists } = await prepareEnvironment(); + + const { waitForText } = await spawn('taq', 'init test-project'); + await waitForText("Project taq'ified!"); + + const { stdout, stderr } = await execute('taq', 'install ../taqueria-plugin-ligo', './test-project'); + expect(stdout).toContain('Plugin installed successfully'); + expect(stdout.join('\n')).toContain('LIGO collects anonymous usage data'); + + const postInstallRan = await exists('./test-project/.ligo/term_acceptance'); + expect(postInstallRan).toEqual(true); + }); + + test('get-image returns the docker image for ligo', async () => { + const { execute, cleanup, spawn } = await prepareEnvironment(); + const { waitForText } = await spawn('taq', 'init test-project'); + await waitForText("Project taq'ified!"); + + const { stdout } = await execute('taq', 'install ../taqueria-plugin-ligo', './test-project'); + expect(stdout).toContain('Plugin installed successfully'); + + const { stdout: imageOutput } = await execute('taq', 'get-image --plugin ligo', './test-project'); + expect(imageOutput).toEqual(expect.arrayContaining([expect.stringContaining('ligolang/ligo:')])); + + await cleanup(); + }); + }); + + describe('support for smart contracts which use @entry without a namespace/module', () => { + test('compile should compile a contract that uses @entry and is not within a namespace/module', async () => { + const { execute, cleanup, spawn, writeFile, ls, path: projectDir } = await prepareEnvironment(); + // console.log(projectDir); + + // Create the project + const { waitForText } = await spawn('taq', 'init test-project'); + await waitForText("Project taq'ified!"); + + // Install the plugin + const { stdout } = await execute('taq', 'install ../taqueria-plugin-ligo', './test-project'); + expect(stdout).toContain('Plugin installed successfully'); + + // Write the contract to the test project + const contract = await (await exec(`cat e2e/data/ligo-data/entry.jsligo`)).stdout; + await writeFile('./test-project/contracts/entry.jsligo', contract); + + // Write the parameter file for the contract + const parameterFile = await (await exec(`cat e2e/data/ligo-data/entry.parameterList.jsligo`)).stdout; + await writeFile('./test-project/contracts/entry.parameterList.jsligo', parameterFile); + + // Write the storage file for the contract + const storageFile = await (await exec(`cat e2e/data/ligo-data/entry.storageList.jsligo`)).stdout; + await writeFile('./test-project/contracts/entry.storageList.jsligo', storageFile); + + // Compile using the `compile` task + const compileResult = await execute('taq', 'compile entry.jsligo', './test-project'); + // console.log(compileResult); + expect(compileResult.stderr).toHaveLength(0); + + // Expect the output to be correct + expect(compileResult.stdout).toEqual([ + '┌──────────────┬────────────────────────────────────────────────┐', + '│ Source │ Artifact │', + '├──────────────┼────────────────────────────────────────────────┤', + '│ entry.jsligo │ artifacts/entry.tz │', + '│ │ artifacts/entry.default_storage.tz │', + '│ │ artifacts/entry.parameter.default_parameter.tz │', + '└──────────────┴────────────────────────────────────────────────┘', + 'Compiled 1 contract(s) in "entry.jsligo"', + ]); + + // Expect the artifacts to be created + const artifacts_list = await ls('./test-project/artifacts'); + const expectedContracts = [ + 'entry.tz', + 'entry.default_storage.tz', + 'entry.parameter.default_parameter.tz', + ]; + expect(artifacts_list).toHaveLength(expectedContracts.length); + expectedContracts.map(contract => expect(artifacts_list).toContain(contract)); + + // Cleanup + await cleanup(); + }); + + test('compile should create a missing parameterList file for a contract that uses @entry without a namespace/module', async () => { + const { execute, cleanup, spawn, writeFile, ls, readFile, path: projectDir } = await prepareEnvironment(); + // console.log(projectDir); + + // Create the project + const { waitForText } = await spawn('taq', 'init test-project'); + await waitForText("Project taq'ified!"); + + // Install the plugin + const { stdout } = await execute('taq', 'install ../taqueria-plugin-ligo', './test-project'); + expect(stdout).toContain('Plugin installed successfully'); + + // Write the contract to the test project + const contract = await (await exec(`cat e2e/data/ligo-data/entry.jsligo`)).stdout; + await writeFile('./test-project/contracts/entry.jsligo', contract); + + // Write the storage file for the contract + const storageFile = await (await exec(`cat e2e/data/ligo-data/entry.storageList.jsligo`)).stdout; + await writeFile('./test-project/contracts/entry.storageList.jsligo', storageFile); + + // Compile using the `compile` task + const compileResult = await execute('taq', 'compile entry.jsligo', './test-project'); + // console.log(compileResult); + + // Expect stderr to contain a warning about the missing parameter file + expect(compileResult.stderr).toHaveLength(1); + expect(compileResult.stderr[0]).toEqual( + `Note: parameter file associated with "entry" can't be found, so "entry.parameterList.jsligo" has been created for you. Use this file to define all parameter values for this contract`, + ); + + // Expect the output to be correct + expect(compileResult.stdout).toEqual([ + '┌──────────────┬────────────────────────────────────┐', + '│ Source │ Artifact │', + '├──────────────┼────────────────────────────────────┤', + '│ entry.jsligo │ artifacts/entry.tz │', + '│ │ artifacts/entry.default_storage.tz │', + '└──────────────┴────────────────────────────────────┘', + 'Compiled 1 contract(s) in "entry.jsligo"', + ]); + + // Expect the parameter file to be created + const contractsList = await ls('./test-project/contracts'); + expect(contractsList).toContain('entry.parameterList.jsligo'); + + // Expect the parameterList file to have the correct contents + const parameterFile = await readFile('./test-project/contracts/entry.parameterList.jsligo'); + // console.log(parameterFile) + const expectedParameterFile = await (await exec(`cat e2e/data/ligo-data/expected-entry.parameterList.jsligo`)) + .stdout; + expect(parameterFile).toEqual(expectedParameterFile); + + // Cleanup + await cleanup(); + }); + }); + + describe('support for smart contracts which use @entry within a namespace/module', () => { + test('compile should compile a contract that uses @entry and is within a namespace/module', async () => { + const { execute, cleanup, spawn, writeFile, ls, path: projectDir } = await prepareEnvironment(); + // console.log(projectDir); + + // Create the project + const { waitForText } = await spawn('taq', 'init test-project'); + await waitForText("Project taq'ified!"); + + // Install the plugin + const { stdout } = await execute('taq', 'install ../taqueria-plugin-ligo', './test-project'); + expect(stdout).toContain('Plugin installed successfully'); + + // Write the contract to the test project + const contract = await (await exec(`cat e2e/data/ligo-data/IncDec.jsligo`)).stdout; + await writeFile('./test-project/contracts/IncDec.jsligo', contract); + + // Write the parameter file for the contract + const parameterFile = await (await exec(`cat e2e/data/ligo-data/IncDec.parameterList.jsligo`)).stdout; + await writeFile('./test-project/contracts/IncDec.parameterList.jsligo', parameterFile); + + // Write the storage file for the contract + const storageFile = await (await exec(`cat e2e/data/ligo-data/IncDec.storageList.jsligo`)).stdout; + await writeFile('./test-project/contracts/IncDec.storageList.jsligo', storageFile); + + // Compile using the `compile` task + const compileResult = await execute('taq', 'compile IncDec.jsligo', './test-project'); + // console.log(compileResult); + expect(compileResult.stderr).toHaveLength(0); + + // Expect the output to be correct + expect(compileResult.stdout).toEqual([ + '┌──────────────────────┬─────────────────────────────────────────┐', + '│ Source │ Artifact │', + '├──────────────────────┼─────────────────────────────────────────┤', + '│ IncDec.jsligo/IncDec │ artifacts/IncDec.tz │', + '│ │ artifacts/IncDec.default_storage.tz │', + '│ │ artifacts/IncDec.parameter.increment.tz │', + '│ │ artifacts/IncDec.parameter.decrement.tz │', + '└──────────────────────┴─────────────────────────────────────────┘', + 'Compiled 1 contract(s) in "IncDec.jsligo"', + ]); + + // Expect the artifacts to be created + const artifacts_list = await ls('./test-project/artifacts'); + const expectedContracts = [ + 'IncDec.tz', + 'IncDec.default_storage.tz', + 'IncDec.parameter.increment.tz', + 'IncDec.parameter.decrement.tz', + ]; + expect(artifacts_list).toHaveLength(expectedContracts.length); + expectedContracts.map(contract => expect(artifacts_list).toContain(contract)); + + // Cleanup + await cleanup(); + }); + + test('compile should create a missing parameterList file for a contract that uses @entry within a namespace/module', async () => { + const { execute, cleanup, spawn, writeFile, ls, readFile, path: projectDir } = await prepareEnvironment(); + // console.log(projectDir); + + // Create the project + const { waitForText } = await spawn('taq', 'init test-project'); + await waitForText("Project taq'ified!"); + + // Install the plugin + const { stdout } = await execute('taq', 'install ../taqueria-plugin-ligo', './test-project'); + expect(stdout).toContain('Plugin installed successfully'); + + // Write the contract to the test project + const contract = await (await exec(`cat e2e/data/ligo-data/IncDec.jsligo`)).stdout; + await writeFile('./test-project/contracts/IncDec.jsligo', contract); + + // Write the storage file for the contract + const storageFile = await (await exec(`cat e2e/data/ligo-data/IncDec.storageList.jsligo`)).stdout; + await writeFile('./test-project/contracts/IncDec.storageList.jsligo', storageFile); + + // Compile using the `compile` task + const compileResult = await execute('taq', 'compile IncDec.jsligo', './test-project'); + // console.log(compileResult); + + // Expect stderr to contain a warning about the missing parameter file + expect(compileResult.stderr).toHaveLength(1); + expect(compileResult.stderr[0]).toEqual( + `Note: parameter file associated with "IncDec" can't be found, so "IncDec.parameterList.jsligo" has been created for you. Use this file to define all parameter values for this contract`, + ); + + // Expect the output to be correct + expect(compileResult.stdout).toEqual([ + '┌──────────────────────┬─────────────────────────────────────┐', + '│ Source │ Artifact │', + '├──────────────────────┼─────────────────────────────────────┤', + '│ IncDec.jsligo/IncDec │ artifacts/IncDec.tz │', + '│ │ artifacts/IncDec.default_storage.tz │', + '└──────────────────────┴─────────────────────────────────────┘', + 'Compiled 1 contract(s) in "IncDec.jsligo"', + ]); + + // Expect the parameter file to be created + const contractsList = await ls('./test-project/contracts'); + expect(contractsList).toContain('IncDec.parameterList.jsligo'); + + // Expect the parameterList file to have the correct contents + const parameterFile = await readFile('./test-project/contracts/IncDec.parameterList.jsligo'); + const expectedParameterFile = await exec('cat e2e/data/ligo-data/expected-IncDec.parameterList.jsligo'); + expect(parameterFile).toEqual(expectedParameterFile.stdout); + + // Cleanup + await cleanup(); + }); + }); + + describe('other compilation tasks', () => { + test('compile will compile only the specified module in the given source file when multiple modules exist', async () => { + const { execute, cleanup, spawn, writeFile, ls, path: projectDir } = await prepareEnvironment(); + // console.log(projectDir); + + const { waitForText } = await spawn('taq', 'init test-project'); + await waitForText("Project taq'ified!"); + + const { stdout } = await execute('taq', 'install ../taqueria-plugin-ligo', './test-project'); + expect(stdout).toContain('Plugin installed successfully'); + + // Write the contract to the test project + const contract = await (await exec(`cat e2e/data/ligo-data/MultipleContracts.mligo`)).stdout; + await writeFile('./test-project/contracts/MultipleContracts.mligo', contract); + + // Compile using the `compile` task + const compileResult = await execute('taq', 'compile MultipleContracts.mligo -m HelloWorld', './test-project'); + // console.log(compileResult); + + // Expect the output to be correct + expect(compileResult.stdout).toEqual([ + '┌────────────────────────────────────┬─────────────────────────┐', + '│ Source │ Artifact │', + '├────────────────────────────────────┼─────────────────────────┤', + '│ MultipleContracts.mligo/HelloWorld │ artifacts/HelloWorld.tz │', + '└────────────────────────────────────┴─────────────────────────┘', + 'Compiled 1 contract(s) in "MultipleContracts.mligo"', + ]); + + // Expect no errors + expect(compileResult.stderr).toEqual([ + `Note: storage file associated with "HelloWorld" can't be found, so "HelloWorld.storageList.mligo" has been created for you. Use this file to define all initial storage values for this contract`, + `Note: parameter file associated with "HelloWorld" can't be found, so "HelloWorld.parameterList.mligo" has been created for you. Use this file to define all parameter values for this contract`, + ]); + + // Cleanup + await cleanup(); + }); + + test('compile to json-encoded michelson', async () => { + const { execute, cleanup, writeFile, readFile, ls, spawn } = await prepareEnvironment(); + const { waitForText } = await spawn('taq', 'init test-project --debug'); + await waitForText("Project taq'ified!"); + + const { stdout } = await execute('taq', 'install ../taqueria-plugin-ligo', './test-project'); + expect(stdout).toContain('Plugin installed successfully'); + + const jsligo_file = await (await exec(`cat e2e/data/ligo-data/IncDec.jsligo`)).stdout; + await writeFile('./test-project/contracts/IncDec.jsligo', jsligo_file); + + await execute('taq', 'compile IncDec.jsligo --json', './test-project'); + const artifacts_list = await ls('./test-project/artifacts'); + expect(artifacts_list).toContain('IncDec.json'); + const json_file = await readFile('./test-project/artifacts/IncDec.json'); + expect(json_file).toContain( + '[{"prim":"parameter","args":[{"prim":"or","args":[{"prim":"unit","annots":["%reset"]},{"prim":"or","args":[{"prim":"int","annots":["%decrement"]},{"prim":"int","annots":["%increment"]}]}]}]},{"prim":"storage","args":[{"prim":"int"}]},{"prim":"code","args":[[{"prim":"UNPAIR"},{"prim":"IF_LEFT","args":[[{"prim":"DROP","args":[{"int":"2"}]},{"prim":"PUSH","args":[{"prim":"int"},{"int":"0"}]}],[{"prim":"IF_LEFT","args":[[{"prim":"SWAP"},{"prim":"SUB"}],[{"prim":"ADD"}]]}]]},{"prim":"NIL","args":[{"prim":"operation"}]},{"prim":"PAIR"}]]}]', + ); + + await cleanup(); + }); + + test('compile will only compile one contract using compile command when multiple contracts exist', async () => { + const { execute, cleanup, spawn, writeFile, ls } = await prepareEnvironment(); + const { waitForText } = await spawn('taq', 'init test-project --debug'); + await waitForText("Project taq'ified!"); + + const { stdout } = await execute('taq', 'install ../taqueria-plugin-ligo', './test-project'); + expect(stdout).toContain('Plugin installed successfully'); + + const artifacts_list_before = await ls('./test-project/artifacts'); + expect(artifacts_list_before).toEqual([]); + + const mligo_file = await (await exec(`cat e2e/data/ligo-data/IncDec.jsligo`)).stdout; + await writeFile('./test-project/contracts/IncDec.jsligo', mligo_file); + + const jsligo_file = await (await exec(`cat e2e/data/ligo-data/entry.jsligo`)).stdout; + await writeFile('./test-project/contracts/entry.jsligo', jsligo_file); + + await execute('taq', 'compile IncDec.jsligo', './test-project'); + const artifacts_list = await ls('./test-project/artifacts'); + expect(artifacts_list).toContain('IncDec.tz'); + + await cleanup(); + }); + + test('compile will error if the named contract does not exist', async () => { + const { execute, cleanup, spawn, writeFile, ls } = await prepareEnvironment(); + const { waitForText } = await spawn('taq', 'init test-project --debug'); + await waitForText("Project taq'ified!"); + + const { stdout } = await execute('taq', 'install ../taqueria-plugin-ligo', './test-project'); + expect(stdout).toContain('Plugin installed successfully'); + + const compileResult = await execute( + 'taq', + 'compile does_not_exist.mligo', + './test-project', + ); + // console.log(compileResult) + expect(compileResult.stdout.join('\n')).toContain( + '│ does_not_exist.mligo │ No contract modules found in "does_not_exist.mligo"', + ); + expect(compileResult.stderr.join()).toContain( + 'The file does_not_exist.mligo was not found. Please ensure that the file exists and that it is in the contracts directory.', + ); + + await cleanup(); + }); + }); + + describe('ligo test framework', () => { + test('test will run ligo test', async () => { + const { execute, cleanup, spawn, writeFile, path: projectDir } = await prepareEnvironment(); + // console.log(projectDir) + + const { waitForText } = await spawn('taq', 'init test-project'); + await waitForText("Project taq'ified!"); + + const { stdout } = await execute('taq', 'install ../taqueria-plugin-ligo', './test-project'); + expect(stdout).toContain('Plugin installed successfully'); + + const mligo_file = await (await exec('cat e2e/data/ligo-data/hello-tacos.mligo')).stdout; + await writeFile('./test-project/contracts/hello-tacos.mligo', mligo_file); + const test_file = await (await exec('cat e2e/data/ligo-data/hello-tacos-tests.mligo')).stdout; + await writeFile('./test-project/contracts/hello-tacos-tests.mligo', test_file); + + const testResult = await execute( + 'taq', + 'test hello-tacos-tests.mligo', + './test-project', + ); + + // console.log(testResult) + + expect(testResult.stdout).toEqual([ + '┌─────────────────────────┬──────────────────────────────────────────────┐', + '│ Contract │ Test Results │', + '├─────────────────────────┼──────────────────────────────────────────────┤', + '│ hello-tacos-tests.mligo │ Everything at the top-level was executed. │', + '│ │ - test_available_tacos exited with value (). │', + '│ │ - test_buy_tacos exited with value (). │', + '│ │ │', + '│ │ 🎉 All tests passed 🎉 │', + '└─────────────────────────┴──────────────────────────────────────────────┘', + ]); + + expect(testResult.stderr).toEqual([]); + + await cleanup(); + }); + + test('test will error if test file is invalid', async () => { + const { execute, cleanup, spawn, writeFile } = await prepareEnvironment(); + const { waitForText } = await spawn('taq', 'init test-project --debug'); + await waitForText("Project taq'ified!"); + + const { stdout } = await execute('taq', 'install ../taqueria-plugin-ligo', './test-project'); + expect(stdout).toContain('Plugin installed successfully'); + + const mligo_file = await (await exec('cat e2e/data/ligo-data/hello-tacos.mligo')).stdout; + await writeFile('./test-project/contracts/hello-tacos.mligo', mligo_file); + const invalid_test_file = await (await exec('cat e2e/data/ligo-data/hello-tacos-invalid-tests.mligo')) + .stdout; + await writeFile('./test-project/contracts/hello-tacos-invalid-tests.mligo', invalid_test_file); + + const { stdout: testOutput, stderr: testErr } = await execute( + 'taq', + 'test hello-tacos-invalid-tests.mligo', + './test-project', + ); + expect(testOutput).toEqual( + expect.arrayContaining(['│ hello-tacos-invalid-tests.mligo │ Some tests failed :( │']), + ); + expect(testErr.join()).toContain('Error messages for hello-tacos-invalid-tests.mligo'); + + await cleanup(); + }); + + test('test will error if named file does not exist', async () => { + const { execute, cleanup, spawn } = await prepareEnvironment(); + const { waitForText } = await spawn('taq', 'init test-project --debug'); + await waitForText("Project taq'ified!"); + + const { stdout } = await execute('taq', 'install ../taqueria-plugin-ligo', './test-project'); + expect(stdout).toContain('Plugin installed successfully'); + + const { stderr: testErr } = await execute('taq', 'test hello-tacos-test.mligo', './test-project'); + expect(testErr.toString()).toContain('contracts/hello-tacos-test.mligo: No such file or directory.'); + + await cleanup(); + }); + }); + + test('LIGO contract template will be instantiated with the right content', async () => { + const { execute, cleanup, spawn, readFile, ls } = await prepareEnvironment(); + const { waitForText } = await spawn('taq', 'init test-project'); + await waitForText("Project taq'ified!"); + + const { stdout } = await execute('taq', 'install ../taqueria-plugin-ligo', './test-project'); + expect(stdout).toContain('Plugin installed successfully'); + + await execute('taq', 'create contract counter.mligo', './test-project'); + expect(await ls('./test-project/contracts')).toContain('counter.mligo'); + + const bytes = await readFile(path.join('./test-project', 'contracts', 'counter.mligo')); + const digest = createHash('sha256'); + digest.update(bytes); + const hash = digest.digest('hex'); + expect(hash).toEqual('e1ceba3bc28cb7a86f07eef36ea9baa835af4b58901b5b0d3e07730054400f55'); + await cleanup(); + }); + + test('ligo compile will error with missing storage file', async () => { + const { execute, cleanup, writeFile, exists, ls, path: projectDir } = await prepareEnvironment(); + // console.log(projectDir) + + await execute('taq', 'init test-project'); + await exists('./test-project/.taq/config.json'); + + await execute('taq', 'install ../taqueria-plugin-ligo', './test-project'); + await exists('./test-project/node_modules/@taqueria/plugin-ligo/index.js'); + + const mligo_file = await (await exec(`cat e2e/data/ligo-data/hello-tacos.mligo`)).stdout; + await writeFile('./test-project/contracts/hello-tacos.mligo', mligo_file); + const parameters_file = await (await exec(`cat e2e/data/ligo-data/hello-tacos.parameters.mligo`)).stdout; + await writeFile('./test-project/contracts/hello-tacos.parameters.mligo', parameters_file); + + expect(await ls('./test-project/contracts')).toEqual( + expect.arrayContaining(['hello-tacos.mligo', 'hello-tacos.parameters.mligo']), + ); + + const { stderr, stdout } = await execute('taq', 'compile counter.mligo', './test-project'); + + expect(stderr).toEqual( + expect.arrayContaining([expect.stringContaining('=== Error messages for counter.mligo ===')]), + ); + + await cleanup(); + }); + + describe('ligo package registry', () => { + test('ligo can create template (contract from the package registry) and the user owns the file', async () => { + const { execute, cleanup, exists } = await prepareEnvironment(); + await execute('taq', 'init test-project'); + await execute('taq', 'install ../taqueria-plugin-ligo', './test-project'); + const result = await execute( + 'taq', + "ligo --command 'init contract --template shifumi-jsligo shifumiTemplate'", + './test-project', + ); + await exists('./test-project/shifumiTemplate'); + const { stdout } = await execute('ls', '-l', './test-project'); + const output = stdout.join('\n'); + expect(output).toContain(process.env.USER); + expect(output).not.toContain('root'); + await cleanup(); + }); + + // See https://github.com/pinnacle-labs/taqueria/issues/1870 + test('ligo task with install command does not result in an error', async () => { + const { execute, cleanup, exists } = await prepareEnvironment(); + await execute('taq', 'init test-project'); + await execute('taq', 'install ../taqueria-plugin-ligo', './test-project'); + const result = await execute('taq', 'ligo --command "install"', './test-project'); + expect(result.stderr.join('').trim()).not.toContain('error'); + await cleanup(); + }); + }); + + describe('long running tests', () => { + jest.setTimeout(100000); + + test('compile-all will find and compile all contracts', async () => { + const { execute, cleanup, spawn, writeFile, ls, path: projectDir } = await prepareEnvironment(); + + const { waitForText } = await spawn('taq', 'init test-project'); + await waitForText("Project taq'ified!"); + + const { stdout } = await execute('taq', 'install ../taqueria-plugin-ligo', './test-project'); + expect(stdout).toContain('Plugin installed successfully'); + + // List of test files to copy to test project + const testFiles = await exec('ls e2e/data/ligo-data').then(res => + res.stdout + .split('\n') + .filter(file => file !== 'hello-tacos-invalid-tests.mligo' && file.length > 0) + ); + + // Copy the test files to the test project + await Promise.all(testFiles.map(async file => { + const fileContents = (await exec(`cat e2e/data/ligo-data/${file}`)).stdout; + return await writeFile(`./test-project/contracts/${file}`, fileContents); + })); + + // Expect files to exist in test project + const contractsList = await ls('./test-project/contracts'); + testFiles.map(file => expect(contractsList).toContain(file)); + + // Compile the contracts using the `compile-all` task + const compileResult = await execute('taq', 'compile-all', './test-project'); + // console.log(compileResult); + + // Check that the output contains the expected files + expect(compileResult.stdout).toEqual( + [ + '┌────────────────────────────────────┬───────────────────────────────────────────────────┐', + '│ Source │ Artifact │', + '├────────────────────────────────────┼───────────────────────────────────────────────────┤', + '│ IncDec.jsligo/IncDec │ artifacts/IncDec.tz │', + '│ │ artifacts/IncDec.default_storage.tz │', + '│ │ artifacts/IncDec.parameter.increment.tz │', + '│ │ artifacts/IncDec.parameter.decrement.tz │', + '├────────────────────────────────────┼───────────────────────────────────────────────────┤', + '│ MultipleContracts.mligo/HelloWorld │ artifacts/HelloWorld.tz │', + '├────────────────────────────────────┼───────────────────────────────────────────────────┤', + '│ MultipleContracts.mligo/Increment │ artifacts/Increment.tz │', + '├────────────────────────────────────┼───────────────────────────────────────────────────┤', + '│ entry-module.mligo/C │ artifacts/C.tz │', + '├────────────────────────────────────┼───────────────────────────────────────────────────┤', + '│ entry.jsligo │ artifacts/entry.tz │', + '│ │ artifacts/entry.default_storage.tz │', + '│ │ artifacts/entry.parameter.default_parameter.tz │', + '├────────────────────────────────────┼───────────────────────────────────────────────────┤', + '│ hello-tacos.mligo │ artifacts/hello-tacos.tz │', + '├────────────────────────────────────┼───────────────────────────────────────────────────┤', + '│ hello-tacos.mligo │ artifacts/hello-tacos.tz │', + '├────────────────────────────────────┼───────────────────────────────────────────────────┤', + '│ pokeGame.jsligo │ artifacts/pokeGame.tz │', + '│ │ artifacts/pokeGame.default_storage.tz │', + '│ │ artifacts/pokeGame.parameter.default_parameter.tz │', + '└────────────────────────────────────┴───────────────────────────────────────────────────┘', + ], + ); + + const expectedStdErr = [ + `Note: storage file associated with "HelloWorld" can't be found, so "HelloWorld.storageList.mligo" has been created for you. Use this file to define all initial storage values for this contract`, + `Note: storage file associated with "Increment" can't be found, so "Increment.storageList.mligo" has been created for you. Use this file to define all initial storage values for this contract`, + `Note: parameter file associated with "HelloWorld" can't be found, so "HelloWorld.parameterList.mligo" has been created for you. Use this file to define all parameter values for this contract`, + `Note: parameter file associated with "Increment" can't be found, so "Increment.parameterList.mligo" has been created for you. Use this file to define all parameter values for this contract`, + `Note: storage file associated with "C" can't be found, so "C.storageList.mligo" has been created for you. Use this file to define all initial storage values for this contract`, + `Note: parameter file associated with "C" can't be found, so "C.parameterList.mligo" has been created for you. Use this file to define all parameter values for this contract`, + `Note: storage file associated with "hello-tacos" can't be found, so "hello-tacos.storageList.mligo" has been created for you. Use this file to define all initial storage values for this contract`, + `Note: parameter file associated with "hello-tacos" can't be found, so "hello-tacos.parameterList.mligo" has been created for you. Use this file to define all parameter values for this contract`, + ]; + + expectedStdErr.map(err => expect(compileResult.stderr).toContain(err)); + expect(compileResult.stderr).toHaveLength(expectedStdErr.length); + + await cleanup(); + }); + }); + + describe('regression tests', () => { + // See https://github.com/pinnacle-labs/taqueria/issues/1859 + // See https://github.com/pinnacle-labs/taqueria/issues/1867 + test('regression against #1859, ligo compile-all will not create infinite storage files', async () => { + const { execute, cleanup, writeFile, path: projectDir } = await prepareEnvironment(); + + // console.log(projectDir) + + // set up the project + await execute('taq', 'init test-project'); + await execute('taq', 'install ../taqueria-plugin-ligo', './test-project'); + + // copy jsligo files to contracts folder + const jligo_file = await (await exec(`cat e2e/data/ligo-data/pokeGame.jsligo`)).stdout; + await writeFile('./test-project/contracts/pokeGame.jsligo', jligo_file); + const storage_file = await (await exec(`cat e2e/data/ligo-data/pokeGame.storageList.jsligo`)).stdout; + await writeFile('./test-project/contracts/pokeGame.storageList.jsligo', storage_file); + const parameters_file = await (await exec(`cat e2e/data/ligo-data/pokeGame.parameterList.jsligo`)).stdout; + await writeFile('./test-project/contracts/pokeGame.parameterList.jsligo', parameters_file); + + // compile the contract using compile-all task + const { stdout } = await execute('taq', 'compile-all', './test-project'); + expect(stdout).toEqual([ + '┌─────────────────┬───────────────────────────────────────────────────┐', + '│ Source │ Artifact │', + '├─────────────────┼───────────────────────────────────────────────────┤', + '│ pokeGame.jsligo │ artifacts/pokeGame.tz │', + '│ │ artifacts/pokeGame.default_storage.tz │', + '│ │ artifacts/pokeGame.parameter.default_parameter.tz │', + '└─────────────────┴───────────────────────────────────────────────────┘', + ]); + + // Cleanup + await cleanup(); + }); + + // https://github.com/pinnacle-labs/taqueria/issues/1907 + test('regression against #1907, compile task will NOT compile storage/parameter expressions for variables which were commented out', async () => { + const { execute, cleanup, spawn, writeFile, ls, path: projectDir } = await prepareEnvironment(); + + // console.log(projectDir); + + // set up the project + const { waitForText } = await spawn('taq', 'init test-project'); + await waitForText("Project taq'ified!"); + + // Install the plugin + const { stdout } = await execute('taq', 'install ../taqueria-plugin-ligo', './test-project'); + + // copy jsligo files to contracts folder + const jligo_file = await (await exec(`cat e2e/data/ligo-data/pokeGame.jsligo`)).stdout; + await writeFile('./test-project/contracts/pokeGame.jsligo', jligo_file); + const storage_file = await (await exec(`cat e2e/data/ligo-data/pokeGame.storageList-with-comments.jsligo`)) + .stdout; + await writeFile('./test-project/contracts/pokeGame.storageList.jsligo', storage_file); + const parameters_file = await (await exec(`cat e2e/data/ligo-data/pokeGame.parameterList-with-comments.jsligo`)) + .stdout; + await writeFile('./test-project/contracts/pokeGame.parameterList.jsligo', parameters_file); + + // compile the contract using compile task + const results = await execute('taq', 'compile pokeGame.jsligo', './test-project'); + expect(results.stdout).toEqual([ + '┌─────────────────┬───────────────────────────────────────────┐', + '│ Source │ Artifact │', + '├─────────────────┼───────────────────────────────────────────┤', + '│ pokeGame.jsligo │ artifacts/pokeGame.tz │', + '│ │ artifacts/pokeGame.default_storage.tz │', + '│ │ artifacts/pokeGame.parameter.parameter.tz │', + '└─────────────────┴───────────────────────────────────────────┘', + 'Compiled 1 contract(s) in "pokeGame.jsligo"', + ]); + + // assure that no storage/parameter files were created + const artifacts_list = await ls('./test-project/artifacts'); + expect(artifacts_list).toEqual( + [ + 'pokeGame.default_storage.tz', + 'pokeGame.parameter.parameter.tz', + 'pokeGame.tz', + ], + ); + + // Cleanup + await cleanup(); + }); + }); +}); diff --git a/tests/package.json b/tests/package.json index 6858ffe2c..992574ef8 100644 --- a/tests/package.json +++ b/tests/package.json @@ -1,6 +1,6 @@ { "name": "@taqueria/tests", - "version": "0.40.22", + "version": "0.40.23", "type": "module", "private": true, "description": "This is Taqueria testing project includes unit, integration and e2e tests",