From 59b8f2340c05d9a38302239a97bb51f47d306e0c Mon Sep 17 00:00:00 2001 From: ioedeveloper Date: Mon, 3 Aug 2020 03:32:19 +0100 Subject: [PATCH] Added specialFunctions tests --- .../src/commands/sendLowLevelTx.ts | 21 ++ .../src/tests/specialFunctions.test.ts | 284 ++++++++++++++++++ apps/remix-ide-e2e/src/types/index.d.ts | 3 +- 3 files changed, 307 insertions(+), 1 deletion(-) create mode 100644 apps/remix-ide-e2e/src/commands/sendLowLevelTx.ts create mode 100644 apps/remix-ide-e2e/src/tests/specialFunctions.test.ts diff --git a/apps/remix-ide-e2e/src/commands/sendLowLevelTx.ts b/apps/remix-ide-e2e/src/commands/sendLowLevelTx.ts new file mode 100644 index 0000000000..f818a34862 --- /dev/null +++ b/apps/remix-ide-e2e/src/commands/sendLowLevelTx.ts @@ -0,0 +1,21 @@ +import { NightwatchBrowser } from 'nightwatch' +import EventEmitter from "events" + +class sendLowLevelTx extends EventEmitter { + command (this: NightwatchBrowser, address: string, value: string, callData: string): NightwatchBrowser { + console.log('low level transact to ', address, value, callData) + this.api.waitForElementVisible(`#instance${address} #deployAndRunLLTxSendTransaction`, 1000) + .clearValue(`#instance${address} #deployAndRunLLTxCalldata`) + .setValue(`#instance${address} #deployAndRunLLTxCalldata`, callData) + .waitForElementVisible('#value') + .clearValue('#value') + .setValue('#value', value) + .scrollAndClick(`#instance${address} #deployAndRunLLTxSendTransaction`) + .perform(() => { + this.emit('complete') + }) + return this + } +} + +module.exports = sendLowLevelTx diff --git a/apps/remix-ide-e2e/src/tests/specialFunctions.test.ts b/apps/remix-ide-e2e/src/tests/specialFunctions.test.ts new file mode 100644 index 0000000000..2b6e1a2ecd --- /dev/null +++ b/apps/remix-ide-e2e/src/tests/specialFunctions.test.ts @@ -0,0 +1,284 @@ +'use strict' +import { NightwatchBrowser } from "nightwatch" +import init from '../helpers/init' +import sauce from './sauce' + +module.exports = { + before: function (browser: NightwatchBrowser, done: VoidFunction) { + // this test suite also contribute testing https://github.com/ethereum/remix/pull/1497 and https://github.com/ethereum/remix-ide/pull/2898 + // quick explanation: + // the goal of https://github.com/ethereum/remix-ide/pull/2898 is to keep track of all the compiled contracts an not only the last one. + // this introduce an issue: if 2 compiled contracts have the same name, the second one override the first which is not wanted. + // fix's delivered by https://github.com/ethereum/remix/pull/1497: instead of getting contract by name, + // which result in name clashing we process the whole contract object (which contain bytecode, deployedbytecode, ...) + init(browser, done) + }, + + '@sources': function () { + return sources + }, + + 'Use special functions receive/fallback - both are declared, sending data': function (browser: NightwatchBrowser) { + browser.waitForElementVisible('#icon-panel', 10000) + .testContracts('receiveAndFallback.sol', sources[0]['browser/receiveAndFallback.sol'], ['CheckSpecials']) // compile + .clickLaunchIcon('udapp') + .selectAccount('0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c') // this account will be used for this test suite + .selectContract('CheckSpecials') + .createContract('') // deploy + .clickInstance(0) + .perform((done) => { + browser.getAddressAtPosition(0, (address) => { + browser.sendLowLevelTx(address, '0', '0xaa') + .pause(1000) + .journalLastChildIncludes('to: CheckSpecials.(fallback)') + .journalLastChildIncludes('value: 0 wei') + .journalLastChildIncludes('data: 0xaa') + .perform(done) + }) + }) + }, + + 'Use special functions receive/fallback - both are declared, failing sending data < 1 byte': function (browser: NightwatchBrowser) { + // don't need to redeploy it, same contract + browser.perform((done) => { + browser.getAddressAtPosition(0, (address) => { + browser.sendLowLevelTx(address, '0', '0xa') + .pause(1000) + .waitForElementVisible(`#instance${address} label[id="deployAndRunLLTxError"]`) + .assert.containsText(`#instance${address} label[id="deployAndRunLLTxError"]`, `The calldata should be a valid hexadecimal value with size of at least one byte.`) + .perform(done) + }) + }) + }, + 'Use special functions receive/fallback - both are declared, failing sending data with odd number of digits': function (browser: NightwatchBrowser) { + // don't need to redeploy it, same contract + browser.perform((done) => { + browser.getAddressAtPosition(0, (address) => { + browser.sendLowLevelTx(address, '0', '0x1aa') + .pause(1000) + .waitForElementVisible(`#instance${address} label[id="deployAndRunLLTxError"]`) + .assert.containsText(`#instance${address} label[id="deployAndRunLLTxError"]`, `The calldata should be a valid hexadecimal value.`) + .perform(done) + }) + }) + }, + 'Use special functions receive/fallback - both are declared - receive called, sending wei': function (browser: NightwatchBrowser) { + // don't need to redeploy it, same contract + browser.perform((done) => { + browser.getAddressAtPosition(0, (address) => { + browser.sendLowLevelTx(address, '1', '') + .pause(1000) + .journalLastChildIncludes('to: CheckSpecials.(receive)') + .journalLastChildIncludes('value: 1 wei') + .journalLastChildIncludes('data: 0x') + .perform(done) + }) + }) + }, + 'Use special functions receive/fallback - both are declared - fallback should fail cause not payable, sending data and wei': function (browser: NightwatchBrowser) { + // don't need to redeploy it, same contract + browser.perform((done) => { + browser.getAddressAtPosition(0, (address) => { + browser.sendLowLevelTx(address, '10', '0xaa') + .pause(1000) + .journalLastChildIncludes('to CheckSpecials.(fallback) errored:') + .journalLastChildIncludes('The called function should be payable if you send value') + .perform(done) + }) + }) + }, + 'Use special functions receive/fallback - only receive is declared, sending wei': function (browser: NightwatchBrowser) { + browser.waitForElementVisible('#icon-panel', 10000) + .testContracts('receiveOnly.sol', sources[1]['browser/receiveOnly.sol'], ['CheckSpecials']) + .clickLaunchIcon('udapp') + .selectContract('CheckSpecials') + .createContract('') + .clickInstance(1) + .perform((done) => { + browser.getAddressAtPosition(1, (address) => { + browser.sendLowLevelTx(address, '1', '') + .pause(1000) + .journalLastChildIncludes('to: CheckSpecials.(receive)') + .journalLastChildIncludes('value: 1 wei') + .journalLastChildIncludes('data: 0x') + .perform(done) + }) + }) + }, + 'Use special functions receive/fallback - only receive is declared, failing, fallback is not declared, sending data': function (browser: NightwatchBrowser) { + // don't need to redeploy it, same contract + browser.perform((done) => { + browser.getAddressAtPosition(1, (address) => { + browser.sendLowLevelTx(address, '0', '0xaa') + .pause(1000) + .waitForElementVisible(`#instance${address} label[id="deployAndRunLLTxError"]`) + .assert.containsText(`#instance${address} label[id="deployAndRunLLTxError"]`, `'Fallback' function is not defined`) + .perform(done) + }) + }) + }, + 'Use special functions receive/fallback - only fallback declared and is payable, sending wei': function (browser: NightwatchBrowser) { + browser.waitForElementVisible('#icon-panel', 10000) + .testContracts('fallbackOnlyPayable.sol', sources[2]['browser/fallbackOnlyPayable.sol'], ['CheckSpecials']) + .clickLaunchIcon('udapp') + .selectContract('CheckSpecials') + .createContract('') + .clickInstance(2) + .perform((done) => { + browser.getAddressAtPosition(2, (address) => { + browser.sendLowLevelTx(address, '1', '') + .pause(1000) + .journalLastChildIncludes('to: CheckSpecials.(fallback)') + .journalLastChildIncludes('value: 1 wei') + .journalLastChildIncludes('data: 0x') + .perform(done) + }) + }) + }, + 'Use special functions receive/fallback - only fallback is diclared and is payable, sending data and wei': function (browser: NightwatchBrowser) { + // don't need to redeploy it, same contract + browser.perform((done) => { + browser.getAddressAtPosition(2, (address) => { + browser.sendLowLevelTx(address, '1', '0xaa') + .pause(1000) + .journalLastChildIncludes('to: CheckSpecials.(fallback)') + .journalLastChildIncludes('value: 1 wei') + .journalLastChildIncludes('data: 0xaa') + .perform(done) + }) + }) + }, + 'Use special functions receive/fallback - only fallback is declared, fallback should fail cause not payable, sending wei': function (browser: NightwatchBrowser) { + browser.waitForElementVisible('#icon-panel', 10000) + .testContracts('fallbackOnlyNotPayable.sol', sources[3]['browser/fallbackOnlyNotPayable.sol'], ['CheckSpecials']) + .clickLaunchIcon('udapp') + .selectContract('CheckSpecials') + .createContract('') + .clickInstance(3) + .perform((done) => { + browser.getAddressAtPosition(3, (address) => { + browser.sendLowLevelTx(address, '1', '') + .pause(1000) + .waitForElementVisible(`#instance${address} label[id="deployAndRunLLTxError"]`) + .assert.containsText(`#instance${address} label[id="deployAndRunLLTxError"]`, `should have either 'receive' or payable 'fallback'`) + .perform(done) + }) + }) + }, + 'Use special functions receive/fallback - receive and fallback are declared, sending data and wei': function (browser: NightwatchBrowser) { + browser.waitForElementVisible('#icon-panel', 10000) + .testContracts('receiveAndFallbackBothPayable.sol', sources[4]['browser/receiveAndFallbackBothPayable.sol'], ['CheckSpecials']) + .clickLaunchIcon('udapp') + .selectContract('CheckSpecials') + .waitForElementVisible('#value') + .clearValue('#value') + .setValue('#value', '0') + .createContract('') + .clickInstance(4) + .pause(1000) + .perform((done) => { + browser.getAddressAtPosition(4, (address) => { + browser.sendLowLevelTx(address, '1', '0xaa') + .pause(1000) + .journalLastChildIncludes('to: CheckSpecials.(fallback)') + .journalLastChildIncludes('value: 1 wei') + .journalLastChildIncludes('data: 0xaa') + .perform(done) + }) + }) + }, + 'Use special functions receive/fallback - receive and fallback are declared and payable, sending wei': function (browser: NightwatchBrowser) { + browser.perform((done) => { + browser.getAddressAtPosition(4, (address) => { + browser.sendLowLevelTx(address, '1', '') + .pause(1000) + .journalLastChildIncludes('to: CheckSpecials.(receive)') + .journalLastChildIncludes('value: 1 wei') + .journalLastChildIncludes('data: 0x') + .perform(done) + }) + }) + }, + 'Use special functions receive/fallback - receive and fallback are not declared, sending nothing': function (browser: NightwatchBrowser) { + browser.waitForElementVisible('#icon-panel', 10000) + .testContracts('notSpecial.sol', sources[5]['browser/notSpecial.sol'], ['CheckSpecials']) + .clickLaunchIcon('udapp') + .selectContract('CheckSpecials') + .waitForElementVisible('#value') + .clearValue('#value') + .setValue('#value', '0') + .createContract('') + .clickInstance(5) + .pause(1000) + .perform((done) => { + browser.getAddressAtPosition(5, (address) => { + browser.sendLowLevelTx(address, '0', '') + .pause(1000) + .waitForElementVisible(`#instance${address} label[id="deployAndRunLLTxError"]`) + .assert.containsText(`#instance${address} label[id="deployAndRunLLTxError"]`, `Both 'receive' and 'fallback' functions are not defined`) + .perform(done) + }) + }) + .end() + }, + tearDown: sauce +} + +const sources = [ + { + 'browser/receiveAndFallback.sol': { + content: ` + contract CheckSpecials { + receive() payable external{} + fallback() external {} + } + ` + } + }, + { + 'browser/receiveOnly.sol': { + content: ` + contract CheckSpecials { + receive() payable external {} + } + ` + } + }, + { + 'browser/fallbackOnlyPayable.sol': { + content: ` + contract CheckSpecials { + fallback() payable external {} + } + ` + } + }, + { + 'browser/fallbackOnlyNotPayable.sol': { + content: ` + contract CheckSpecials { + fallback() external {} + } + ` + } + }, + { + 'browser/receiveAndFallbackBothPayable.sol': { + content: ` + contract CheckSpecials { + receive() payable external {} + fallback() payable external {} + } + ` + } + }, + { + 'browser/notSpecial.sol': { + content: ` + contract CheckSpecials { + function otherFallback() payable external {} + } + ` + } + } +] diff --git a/apps/remix-ide-e2e/src/types/index.d.ts b/apps/remix-ide-e2e/src/types/index.d.ts index 8fffb227d1..f156b57a93 100644 --- a/apps/remix-ide-e2e/src/types/index.d.ts +++ b/apps/remix-ide-e2e/src/types/index.d.ts @@ -47,7 +47,8 @@ declare module "nightwatch" { signMessage(msg: string, callback: (hash: { value: string }, signature: { value: string }) => void): NightwatchBrowser, setSolidityCompilerVersion(version: string): NightwatchBrowser, clickElementAtPosition(cssSelector: string, index: number): NightwatchBrowser, - notContainsText(cssSelector: string, text: string): NightwatchBrowser + notContainsText(cssSelector: string, text: string): NightwatchBrowser, + sendLowLevelTx(address: string, value: string, callData: string): NightwatchBrowser } export interface NightwatchBrowser {