diff --git a/tools/webide/packages/client/src/components/output-tab.tsx b/tools/webide/packages/client/src/components/output-tab.tsx index 0f6cad87e..22e0a397c 100644 --- a/tools/webide/packages/client/src/components/output-tab.tsx +++ b/tools/webide/packages/client/src/components/output-tab.tsx @@ -132,7 +132,7 @@ export const OutputTabComponent = (props: { return ( - {output.length !== 0 && ( + {!(loading.loading || output.length === 0) && ( copyOutput(preRef.current)} onDownload={() => downloadOutput(preRef.current)} diff --git a/tools/webide/packages/client/src/redux/actions/deploy.ts b/tools/webide/packages/client/src/redux/actions/deploy.ts index e8b8c2d9e..ffc62c966 100644 --- a/tools/webide/packages/client/src/redux/actions/deploy.ts +++ b/tools/webide/packages/client/src/redux/actions/deploy.ts @@ -2,7 +2,7 @@ import { Tezos } from '@taquito/taquito'; import { TezBridgeSigner } from '@taquito/tezbridge-signer'; import { Dispatch } from 'redux'; -import { compileContract, compileExpression, deploy, getErrorMessage } from '../../services/api'; +import { compileContract, compileStorage, deploy, getErrorMessage } from '../../services/api'; import { AppState } from '../app'; import { MichelsonFormat } from '../compile'; import { DoneLoadingAction, UpdateLoadingAction } from '../loading'; @@ -32,8 +32,10 @@ export class DeployAction extends CancellableAction { } dispatch({ ...new UpdateLoadingAction('Compiling storage...') }); - const michelsonStorage = await compileExpression( + const michelsonStorage = await compileStorage( editorState.language, + editorState.code, + deployState.entrypoint, deployState.storage, MichelsonFormat.Json ); diff --git a/tools/webide/packages/client/src/services/api.ts b/tools/webide/packages/client/src/services/api.ts index 14d89b391..39defca87 100644 --- a/tools/webide/packages/client/src/services/api.ts +++ b/tools/webide/packages/client/src/services/api.ts @@ -36,6 +36,23 @@ export async function compileExpression( return response.data; } +export async function compileStorage( + syntax: Language, + code: string, + entrypoint: string, + storage: string, + format?: string +) { + const response = await axios.post('/api/compile-storage', { + syntax, + code, + entrypoint, + storage, + format + }); + return response.data; +} + export async function dryRun( syntax: Language, code: string, diff --git a/tools/webide/packages/e2e/test/common-utils.js b/tools/webide/packages/e2e/test/common-utils.js index 4b6c53cc1..68cddbadc 100644 --- a/tools/webide/packages/e2e/test/common-utils.js +++ b/tools/webide/packages/e2e/test/common-utils.js @@ -79,6 +79,19 @@ exports.verifyAllExamples = async (action, done) => { done(); }; +exports.verifyWithParameter = async (command, parameter, value, action, done) => { + await page.click('#command-select'); + await page.click(`#${command}`); + + await page.click(`#${parameter}`); + await exports.clearText(page.keyboard); + await page.keyboard.type(value); + + expect(await action()).toEqual(`Error: "${parameter}" is not allowed to be empty`); + + done(); +} + exports.verifyWithBlankParameter = async (command, parameter, action, done) => { await page.click('#command-select'); await page.click(`#${command}`); diff --git a/tools/webide/packages/e2e/test/deploy.spec.js b/tools/webide/packages/e2e/test/deploy.spec.js new file mode 100644 index 000000000..ba0424565 --- /dev/null +++ b/tools/webide/packages/e2e/test/deploy.spec.js @@ -0,0 +1,38 @@ +const commonUtils = require('./common-utils'); + +const API_HOST = commonUtils.API_HOST; + +const runCommandAndGetOutputFor = commonUtils.runCommandAndGetOutputFor; +const clearText = commonUtils.clearText; + +const COMMAND = 'deploy'; +const COMMAND_ENDPOINT = 'deploy'; + +async function deploy() { + return await runCommandAndGetOutputFor(COMMAND, COMMAND_ENDPOINT); +} + +describe('Deploy contract', () => { + beforeAll(() => jest.setTimeout(60000)); + + beforeEach(async () => await page.goto(API_HOST)); + + it('should deploy', async done => { + expect(await deploy()).toContain('The contract was successfully deployed to the babylonnet test network.'); + + done(); + }); + + it('should fail to deploy contract with invalid storage', async done => { + await page.click('#command-select'); + await page.click(`#deploy`); + + await page.click(`#storage`); + await clearText(page.keyboard); + await page.keyboard.type('asdf'); + + expect(await deploy()).toContain('Error: '); + + done(); + }); +}); diff --git a/tools/webide/packages/server/src/ligo-compiler.ts b/tools/webide/packages/server/src/ligo-compiler.ts index b239cab73..53b575b3c 100644 --- a/tools/webide/packages/server/src/ligo-compiler.ts +++ b/tools/webide/packages/server/src/ligo-compiler.ts @@ -120,6 +120,7 @@ export class LigoCompiler { format: string ) { const { name, remove } = await this.createTemporaryFile(code); + try { const result = await this.execPromise(this.ligoCmd, [ 'compile-contract', @@ -148,6 +149,33 @@ export class LigoCompiler { return result; } + async compileStorage( + syntax: string, + code: string, + entrypoint: string, + format: string, + storage: string + ) { + const { name, remove } = await this.createTemporaryFile(code); + + try { + const result = await this.execPromise(this.ligoCmd, [ + 'compile-storage', + '--michelson-format', + format, + '-s', + syntax, + name, + entrypoint, + storage + ]); + + return result; + } finally { + remove(); + } + } + async dryRun( syntax: string, code: string, diff --git a/tools/webide/packages/server/test/ligo-compiler.spec.ts b/tools/webide/packages/server/test/ligo-compiler.spec.ts new file mode 100644 index 000000000..f5dbd0109 --- /dev/null +++ b/tools/webide/packages/server/test/ligo-compiler.spec.ts @@ -0,0 +1,37 @@ +import { LigoCompiler } from '../src/ligo-compiler'; + +const PASCALIGO_CODE = ` +type action is +| Increment of int +| Decrement of int + +function add (const a : int ; const b : int) : int is + block { skip } with a + b + +function subtract (const a : int ; const b : int) : int is + block { skip } with a - b + +function main (const p : action ; const s : int) : + (list(operation) * int) is + block { skip } with ((nil : list(operation)), + case p of + | Increment(n) -> add(s, n) + | Decrement(n) -> subtract(s, n) + end) +`; + +describe('Ligo compiler', () => { + it('should compile storage', async done => { + const michelsonCode = await new LigoCompiler().compileStorage( + 'pascaligo', + PASCALIGO_CODE, + 'main', + 'json', + '0' + ); + + expect(michelsonCode.trim()).toEqual('{ "int": "0" }'); + + done(); + }); +});