From 6446a6414ec768d9eb5c7ae1fc03e61f32f5b65a Mon Sep 17 00:00:00 2001 From: ioedeveloper Date: Tue, 28 Jul 2020 17:08:03 +0100 Subject: [PATCH] Moved more custom commands to typescript --- apps/remix-ide-e2e/src/commands/addFile.ts | 38 +++ .../src/commands/clickFunction.ts | 25 ++ .../src/commands/clickLaunchIcon.ts | 8 +- .../src/commands/goToVMTraceStep.ts | 37 +++ .../src/commands/scrollAndClick.ts | 15 ++ apps/remix-ide-e2e/src/commands/scrollInto.ts | 23 ++ .../src/commands/selectAccount.ts | 16 ++ .../src/commands/setEditorValue.ts | 22 ++ .../src/commands/switchBrowserTab.ts | 8 +- .../src/commands/testContracts.ts | 26 ++ .../src/commands/testFunction.ts | 60 +++++ .../src/commands/verifyContracts.ts | 70 +++++ .../src/examples/example-contracts.ts | 249 ++++++++++++++++++ apps/remix-ide-e2e/src/helpers/init.ts | 19 +- apps/remix-ide-e2e/src/tests/ballot.test.ts | 3 +- apps/remix-ide-e2e/src/types/index.d.ts | 37 ++- 16 files changed, 628 insertions(+), 28 deletions(-) create mode 100644 apps/remix-ide-e2e/src/commands/addFile.ts create mode 100644 apps/remix-ide-e2e/src/commands/clickFunction.ts create mode 100644 apps/remix-ide-e2e/src/commands/goToVMTraceStep.ts create mode 100644 apps/remix-ide-e2e/src/commands/scrollAndClick.ts create mode 100644 apps/remix-ide-e2e/src/commands/scrollInto.ts create mode 100644 apps/remix-ide-e2e/src/commands/selectAccount.ts create mode 100644 apps/remix-ide-e2e/src/commands/setEditorValue.ts create mode 100644 apps/remix-ide-e2e/src/commands/testContracts.ts create mode 100644 apps/remix-ide-e2e/src/commands/testFunction.ts create mode 100644 apps/remix-ide-e2e/src/commands/verifyContracts.ts create mode 100644 apps/remix-ide-e2e/src/examples/example-contracts.ts diff --git a/apps/remix-ide-e2e/src/commands/addFile.ts b/apps/remix-ide-e2e/src/commands/addFile.ts new file mode 100644 index 0000000000..e5b79b16c1 --- /dev/null +++ b/apps/remix-ide-e2e/src/commands/addFile.ts @@ -0,0 +1,38 @@ +import { NightwatchBrowser, NightwatchContractContent } from 'nightwatch' + +const EventEmitter = require('events') + +export class AddFile extends EventEmitter { + command (this: NightwatchBrowser, name: string, content: NightwatchContractContent): NightwatchBrowser { + this.api.perform((done: VoidFunction) => { + addFile(this.api, name, content, () => { + done() + this.emit('complete') + }) + }) + return this + } +} + +function addFile (browser: NightwatchBrowser, name: string, content: NightwatchContractContent, done: VoidFunction) { + browser.clickLaunchIcon('udapp').clickLaunchIcon('fileExplorers').click('.newFile') + .waitForElementVisible('#modal-dialog') + .perform((client, done) => { + browser.execute(function (fileName) { + if (fileName !== 'Untitled.sol') { + document.querySelector('#modal-dialog #prompt_text').setAttribute('value', fileName) + } + const elem = document.querySelector('#modal-footer-ok') as HTMLElement + + elem.click() + }, [name], function (result) { + console.log(result) + done() + }) + }) + .setEditorValue(content.content) + .pause(1000) + .perform(function () { + done() + }) +} diff --git a/apps/remix-ide-e2e/src/commands/clickFunction.ts b/apps/remix-ide-e2e/src/commands/clickFunction.ts new file mode 100644 index 0000000000..648030bb74 --- /dev/null +++ b/apps/remix-ide-e2e/src/commands/clickFunction.ts @@ -0,0 +1,25 @@ +import { NightwatchBrowser, NightwatchClickFunctionExpectedInput } from 'nightwatch' + +const EventEmitter = require('events') + +export class ClickFunction extends EventEmitter { + command (this: NightwatchBrowser, fnFullName: string, expectedInput?: NightwatchClickFunctionExpectedInput): NightwatchBrowser { + this.api.waitForElementPresent('.instance button[title="' + fnFullName + '"]') + .perform(function (client, done) { + client.execute(function () { + document.querySelector('#runTabView').scrollTop = document.querySelector('#runTabView').scrollHeight + }, [], function () { + if (expectedInput) { + client.setValue('#runTabView input[title="' + expectedInput.types + '"]', expectedInput.values, _ => _) + } + done() + }) + }) + .click('.instance button[title="' + fnFullName + '"]') + .pause(2000) + .perform(() => { + this.emit('complete') + }) + return this + } +} diff --git a/apps/remix-ide-e2e/src/commands/clickLaunchIcon.ts b/apps/remix-ide-e2e/src/commands/clickLaunchIcon.ts index 9c8eccadf3..d8d9c8388b 100644 --- a/apps/remix-ide-e2e/src/commands/clickLaunchIcon.ts +++ b/apps/remix-ide-e2e/src/commands/clickLaunchIcon.ts @@ -2,14 +2,12 @@ import { NightwatchBrowser } from "nightwatch" const EventEmitter = require('events') -class ClickLaunchIcon extends EventEmitter { - command (this: NightwatchBrowser, icon: string) { - this.api.waitForElementVisible('#icon-panel div[plugin="' + icon + '"]').click('#icon-panel div[plugin="' + icon + '"]').perform((done: CallableFunction) => { +export class ClickLaunchIcon extends EventEmitter { + command (this: NightwatchBrowser, icon: string): NightwatchBrowser { + this.api.waitForElementVisible('#icon-panel div[plugin="' + icon + '"]').click('#icon-panel div[plugin="' + icon + '"]').perform((done: VoidFunction) => { done() this.emit('complete') }) return this } } - -module.exports = ClickLaunchIcon diff --git a/apps/remix-ide-e2e/src/commands/goToVMTraceStep.ts b/apps/remix-ide-e2e/src/commands/goToVMTraceStep.ts new file mode 100644 index 0000000000..c543155e92 --- /dev/null +++ b/apps/remix-ide-e2e/src/commands/goToVMTraceStep.ts @@ -0,0 +1,37 @@ +import { NightwatchBrowser } from 'nightwatch' + +const EventEmitter = require('events') + +export class GoToVmTraceStep extends EventEmitter { + command (this: NightwatchBrowser, step: number, incr?: number): NightwatchBrowser { + this.api.perform((done: VoidFunction) => { + goToVMtraceStep(this.api, step, incr, () => { + done() + this.emit('complete') + }) + }) + return this + } +} + +function goToVMtraceStep (browser: NightwatchBrowser, step: number, incr: number, done: VoidFunction) { + if (!incr) incr = 0 + browser.execute(function () { + return document.querySelector('#stepdetail').innerHTML + }, [], function (result) { + if (typeof result.value === 'string' && ( result.value.indexOf('vm trace step:') !== -1 && result.value.indexOf(step.toString()) !== -1)) { + done() + } else if (incr > 1000) { + browser.assert.fail('goToVMtraceStep fails', 'info about error', '') + done() + } else { + incr++ + browser.click('#intoforward') + .perform(() => { + setTimeout(() => { + goToVMtraceStep(browser, step, incr, done) + }, 200) + }) + } + }) +} diff --git a/apps/remix-ide-e2e/src/commands/scrollAndClick.ts b/apps/remix-ide-e2e/src/commands/scrollAndClick.ts new file mode 100644 index 0000000000..d360dd4839 --- /dev/null +++ b/apps/remix-ide-e2e/src/commands/scrollAndClick.ts @@ -0,0 +1,15 @@ +import { NightwatchBrowser } from 'nightwatch' + +const EventEmitter = require('events') + +export class scrollAndClick extends EventEmitter { + command (this: NightwatchBrowser, target: string): NightwatchBrowser { + this.api + .scrollInto(target) + .click(target) + .perform(() => { + this.emit('complete') + }) + return this + } +} diff --git a/apps/remix-ide-e2e/src/commands/scrollInto.ts b/apps/remix-ide-e2e/src/commands/scrollInto.ts new file mode 100644 index 0000000000..d10214da96 --- /dev/null +++ b/apps/remix-ide-e2e/src/commands/scrollInto.ts @@ -0,0 +1,23 @@ +import { NightwatchBrowser } from 'nightwatch' + +const EventEmitter = require('events') + +export class ScrollInto extends EventEmitter { + command (this: NightwatchBrowser, target: string): NightwatchBrowser { + this.api.perform((client, done) => { + _scrollInto(this.api, target, () => { + done() + this.emit('complete') + }) + }) + return this + } +} + +function _scrollInto (browser: NightwatchBrowser, target: string, cb: VoidFunction): void { + browser.execute(function (target) { + document.querySelector(target).scrollIntoView(({block: 'center'})) + }, [target], function () { + cb() + }) +} diff --git a/apps/remix-ide-e2e/src/commands/selectAccount.ts b/apps/remix-ide-e2e/src/commands/selectAccount.ts new file mode 100644 index 0000000000..64bbff680d --- /dev/null +++ b/apps/remix-ide-e2e/src/commands/selectAccount.ts @@ -0,0 +1,16 @@ +import { NightwatchBrowser } from 'nightwatch' + +const EventEmitter = require('events') + +export class SelectAccount extends EventEmitter { + command (this: NightwatchBrowser, account?: string): NightwatchBrowser { + if (account) { + this.api + .click(`select[data-id="runTabSelectAccount"] [value="${account}"]`) + .perform(() => { + this.emit('complete') + }) + } else this.emit('complete') + return this + } +} diff --git a/apps/remix-ide-e2e/src/commands/setEditorValue.ts b/apps/remix-ide-e2e/src/commands/setEditorValue.ts new file mode 100644 index 0000000000..d718c1172f --- /dev/null +++ b/apps/remix-ide-e2e/src/commands/setEditorValue.ts @@ -0,0 +1,22 @@ +import { NightwatchBrowser } from 'nightwatch' + +const EventEmitter = require('events') + +export class SetEditorValue extends EventEmitter { + command (this: NightwatchBrowser, value: string, callback?: VoidFunction): NightwatchBrowser { + this.api.perform((client, done) => { + this.api.execute(function (value) { + const elem: any = document.querySelector('#modal-footer-ok') + + elem.editor.session.setValue(value) + }, [value], () => { + done() + if (callback) { + callback.call(this.api) + } + this.emit('complete') + }) + }) + return this + } +} diff --git a/apps/remix-ide-e2e/src/commands/switchBrowserTab.ts b/apps/remix-ide-e2e/src/commands/switchBrowserTab.ts index 7314d5a26d..25c05249c0 100644 --- a/apps/remix-ide-e2e/src/commands/switchBrowserTab.ts +++ b/apps/remix-ide-e2e/src/commands/switchBrowserTab.ts @@ -6,9 +6,9 @@ const EventEmitter = require('events') Switches between browser tabs */ -class SwitchBrowserTab extends EventEmitter { - command (this: NightwatchBrowser, index: number) { - this.api.perform((browser: NightwatchBrowser, done: VoidFunction) => { +export class SwitchBrowserTab extends EventEmitter { + command (this: NightwatchBrowser, index: number): NightwatchBrowser { + this.api.perform((browser: NightwatchBrowser, done) => { browser.windowHandles((result) => { browser.switchWindow(result.value[index]) done() @@ -18,5 +18,3 @@ class SwitchBrowserTab extends EventEmitter { return this } } - -module.exports = SwitchBrowserTab diff --git a/apps/remix-ide-e2e/src/commands/testContracts.ts b/apps/remix-ide-e2e/src/commands/testContracts.ts new file mode 100644 index 0000000000..44bcd17846 --- /dev/null +++ b/apps/remix-ide-e2e/src/commands/testContracts.ts @@ -0,0 +1,26 @@ +import { NightwatchBrowser, NightwatchContractContent } from 'nightwatch' + +const EventEmitter = require('events') + +export class TestContracts extends EventEmitter { + command (this: NightwatchBrowser,fileName: string, contractCode: NightwatchContractContent, compiledContractNames: string[]): NightwatchBrowser { + this.api.perform((done: VoidFunction) => { + testContracts(this.api, fileName, contractCode, compiledContractNames, () => { + done() + this.emit('complete') + }) + }) + return this + } +} + +function testContracts (browser: NightwatchBrowser, fileName: string, contractCode: NightwatchContractContent, compiledContractNames: string[], callback: VoidFunction) { + browser + .clickLaunchIcon('solidity') + .addFile(fileName, contractCode) + .pause(1000) + .verifyContracts(compiledContractNames) + .perform(() => { + callback() + }) +} diff --git a/apps/remix-ide-e2e/src/commands/testFunction.ts b/apps/remix-ide-e2e/src/commands/testFunction.ts new file mode 100644 index 0000000000..11f26eac34 --- /dev/null +++ b/apps/remix-ide-e2e/src/commands/testFunction.ts @@ -0,0 +1,60 @@ +import { NightwatchBrowser, NightwatchTestFunctionExpectedInput } from 'nightwatch' +import deepequal from 'deep-equal' + +const EventEmitter = require('events') + +export class TestFunction extends EventEmitter { + command (this: NightwatchBrowser, txHash: string, expectedValue: NightwatchTestFunctionExpectedInput): NightwatchBrowser { + const browser = this.api + const logs = {} + const setLog = (index: number, value: string) => { logs[Object.keys(logs)[index]] = typeof value === 'string' ? value.trim() : value } + + browser + .waitForElementVisible(`[data-id="block_tx${txHash}"]`) + .click(`[data-id="block_tx${txHash}"]`) + .waitForElementVisible(`*[data-id="txLoggerTable${txHash}"]`) + + // fetch and format transaction logs as key => pair object + .elements('css selector', `*[data-shared="key_${txHash}"]`, (res) => { + Array.isArray(res.value) && res.value.forEach(function (jsonWebElement) { + const jsonWebElementId: string = jsonWebElement.ELEMENT || jsonWebElement[Object.keys(jsonWebElement)[0]] + + browser.elementIdText(jsonWebElementId, (jsonElement) => { + const key = typeof jsonElement.value === 'string' ? jsonElement.value.trim() : null + + logs[key] = null + }) + }) + }) + .elements('css selector', `*[data-shared="pair_${txHash}"]`, (res) => { + Array.isArray(res.value) && res.value.forEach(function (jsonWebElement, index) { + const jsonWebElementId = jsonWebElement.ELEMENT || jsonWebElement[Object.keys(jsonWebElement)[0]] + + browser.elementIdText(jsonWebElementId, (jsonElement) => { + let value = jsonElement.value + + try { + value = JSON.parse(jsonElement.value) + setLog(index, value) + } catch (e) { + setLog(index, value) + } + }) + }) + }) + + browser.perform(() => { + Object.keys(expectedValue).forEach(key => { + const equal: boolean = deepequal(logs[key], expectedValue[key]) + + if (!equal) { + browser.assert.fail(`Expected ${expectedValue[key]} but got ${logs[key]}`) + } else { + browser.assert.ok(true, `Expected value matched returned value ${expectedValue[key]}`) + } + }) + this.emit('complete') + }) + return this + } +} diff --git a/apps/remix-ide-e2e/src/commands/verifyContracts.ts b/apps/remix-ide-e2e/src/commands/verifyContracts.ts new file mode 100644 index 0000000000..82c620a822 --- /dev/null +++ b/apps/remix-ide-e2e/src/commands/verifyContracts.ts @@ -0,0 +1,70 @@ +import { NightwatchBrowser, NightwatchVerifyContractOpts, NightwatchCallbackResult } from 'nightwatch' + +const EventEmitter = require('events') + +export class VerifyContracts extends EventEmitter { + command (this: NightwatchBrowser,compiledContractNames: string[], opts = { wait: 1000, version: null }): NightwatchBrowser { + this.api.perform((done: VoidFunction) => { + verifyContracts(this.api, compiledContractNames, opts, () => { + done() + this.emit('complete') + }) + }) + return this + } +} + +function getCompiledContracts (browser: NightwatchBrowser, opts: NightwatchVerifyContractOpts, callback: CallableFunction) { + browser + .clickLaunchIcon('solidity') + .pause(opts.wait) + .waitForElementPresent('*[data-id="compiledContracts"] option') + .perform((done: VoidFunction) => { + if (opts.version) { + browser + .click('*[data-id="compilation-details"]') + .waitForElementVisible('*[data-id="treeViewDivcompiler"]') + .pause(2000) + .click('*[data-id="treeViewDivcompiler"]') + .waitForElementVisible('*[data-id="treeViewLicompiler/version"]') + .assert.containsText('*[data-id="treeViewLicompiler/version"]', `version:\n ${opts.version}`) + .perform(done) + } else done() + }) + .execute(function () { + const contracts = document.querySelectorAll('*[data-id="compiledContracts"] option') as NodeListOf + + if (!contracts) { + return null + } else { + const ret = [] + + for (let c = 0; c < contracts.length; c++) { + ret.push(contracts[c].value) + } + return ret + } + }, [], function (result) { + callback(result) + }) +} + +function verifyContracts (browser: NightwatchBrowser, compiledContractNames: string[], opts: NightwatchVerifyContractOpts, callback: VoidFunction) { + getCompiledContracts(browser, opts, (result: NightwatchCallbackResult) => { + if (result.value) { + for (const contract in compiledContractNames) { + console.log(' - ' + compiledContractNames[contract], result.value) + if (result.value.indexOf(compiledContractNames[contract]) === -1) { + browser.assert.fail('compiled contract ' + compiledContractNames + ' not found', 'info about error', '') + browser.end() + return + } + } + } else { + browser.assert.fail('compiled contract ' + compiledContractNames + ' not found - none found', 'info about error', '') + browser.end() + } + console.log('contracts all found ' + compiledContractNames) + callback() + }) +} diff --git a/apps/remix-ide-e2e/src/examples/example-contracts.ts b/apps/remix-ide-e2e/src/examples/example-contracts.ts new file mode 100644 index 0000000000..6f1a43d19a --- /dev/null +++ b/apps/remix-ide-e2e/src/examples/example-contracts.ts @@ -0,0 +1,249 @@ +'use strict' + +const storage = `pragma solidity >=0.4.22 <0.7.0; + +/** + * @title Storage + * @dev Store & retreive value in a variable + */ +contract Storage { + + uint256 number; + + /** + * @dev Store value in variable + * @param num value to store + */ + function store(uint256 num) public { + number = num; + } + + /** + * @dev Return value + * @return value of 'number' + */ + function retreive() public view returns (uint256){ + return number; + } +}` + +const owner = `pragma solidity >=0.4.22 <0.7.0; + +/** + * @title Owner + * @dev Set & change owner + */ +contract Owner { + + address private owner; + + // event for EVM logging + event OwnerSet(address indexed oldOwner, address indexed newOwner); + + // modifier to check if caller is owner + modifier isOwner() { + // If the first argument of 'require' evaluates to 'false', execution terminates and all + // changes to the state and to Ether balances are reverted. + // This used to consume all gas in old EVM versions, but not anymore. + // It is often a good idea to use 'require' to check if functions are called correctly. + // As a second argument, you can also provide an explanation about what went wrong. + require(msg.sender == owner, "Caller is not owner"); + _; + } + + /** + * @dev Set contract deployer as owner + */ + constructor() public { + owner = msg.sender; // 'msg.sender' is sender of current call, contract deployer for a constructor + emit OwnerSet(address(0), owner); + } + + /** + * @dev Change owner + * @param newOwner address of new owner + */ + function changeOwner(address newOwner) public isOwner { + emit OwnerSet(owner, newOwner); + owner = newOwner; + } + + /** + * @dev Return owner address + * @return address of owner + */ + function getOwner() external view returns (address) { + return owner; + } +}` + +const ballot = `pragma solidity >=0.4.22 <0.7.0; + +/** + * @title Ballot + * @dev Implements voting process along with vote delegation + */ +contract Ballot { + + struct Voter { + uint weight; // weight is accumulated by delegation + bool voted; // if true, that person already voted + address delegate; // person delegated to + uint vote; // index of the voted proposal + } + + struct Proposal { + // If you can limit the length to a certain number of bytes, + // always use one of bytes1 to bytes32 because they are much cheaper + bytes32 name; // short name (up to 32 bytes) + uint voteCount; // number of accumulated votes + } + + address public chairperson; + + mapping(address => Voter) public voters; + + Proposal[] public proposals; + + /** + * @dev Create a new ballot to choose one of 'proposalNames'. + * @param proposalNames names of proposals + */ + constructor(bytes32[] memory proposalNames) public { + chairperson = msg.sender; + voters[chairperson].weight = 1; + + for (uint i = 0; i < proposalNames.length; i++) { + // 'Proposal({...})' creates a temporary + // Proposal object and 'proposals.push(...)' + // appends it to the end of 'proposals'. + proposals.push(Proposal({ + name: proposalNames[i], + voteCount: 0 + })); + } + } + + /** + * @dev Give 'voter' the right to vote on this ballot. May only be called by 'chairperson'. + * @param voter address of voter + */ + function giveRightToVote(address voter) public { + require( + msg.sender == chairperson, + "Only chairperson can give right to vote." + ); + require( + !voters[voter].voted, + "The voter already voted." + ); + require(voters[voter].weight == 0); + voters[voter].weight = 1; + } + + /** + * @dev Delegate your vote to the voter 'to'. + * @param to address to which vote is delegated + */ + function delegate(address to) public { + Voter storage sender = voters[msg.sender]; + require(!sender.voted, "You already voted."); + require(to != msg.sender, "Self-delegation is disallowed."); + + while (voters[to].delegate != address(0)) { + to = voters[to].delegate; + + // We found a loop in the delegation, not allowed. + require(to != msg.sender, "Found loop in delegation."); + } + sender.voted = true; + sender.delegate = to; + Voter storage delegate_ = voters[to]; + if (delegate_.voted) { + // If the delegate already voted, + // directly add to the number of votes + proposals[delegate_.vote].voteCount += sender.weight; + } else { + // If the delegate did not vote yet, + // add to her weight. + delegate_.weight += sender.weight; + } + } + + /** + * @dev Give your vote (including votes delegated to you) to proposal 'proposals[proposal].name'. + * @param proposal index of proposal in the proposals array + */ + function vote(uint proposal) public { + Voter storage sender = voters[msg.sender]; + require(sender.weight != 0, "Has no right to vote"); + require(!sender.voted, "Already voted."); + sender.voted = true; + sender.vote = proposal; + + // If 'proposal' is out of the range of the array, + // this will throw automatically and revert all + // changes. + proposals[proposal].voteCount += sender.weight; + } + + /** + * @dev Computes the winning proposal taking all previous votes into account. + * @return winningProposal_ index of winning proposal in the proposals array + */ + function winningProposal() public view + returns (uint winningProposal_) + { + uint winningVoteCount = 0; + for (uint p = 0; p < proposals.length; p++) { + if (proposals[p].voteCount > winningVoteCount) { + winningVoteCount = proposals[p].voteCount; + winningProposal_ = p; + } + } + } + + /** + * @dev Calls winningProposal() function to get the index of the winner contained in the proposals array and then + * @return winnerName_ the name of the winner + */ + function winnerName() public view + returns (bytes32 winnerName_) + { + winnerName_ = proposals[winningProposal()].name; + } +} +` + +const ballotTest = `pragma solidity >=0.4.22 <0.7.0; +import "remix_tests.sol"; // this import is automatically injected by Remix. +import "../3_Ballot.sol"; + +contract BallotTest { + + bytes32[] proposalNames; + + Ballot ballotToTest; + function beforeAll () public { + proposalNames.push(bytes32("candidate1")); + ballotToTest = new Ballot(proposalNames); + } + + function checkWinningProposal () public { + ballotToTest.vote(0); + Assert.equal(ballotToTest.winningProposal(), uint(0), "proposal at index 0 should be the winning proposal"); + Assert.equal(ballotToTest.winnerName(), bytes32("candidate1"), "candidate1 should be the winner name"); + } + + function checkWinninProposalWithReturnValue () public view returns (bool) { + return ballotToTest.winningProposal() == 0; + } +} +` + +export default { + storage: { name: '1_Storage.sol', content: storage }, + owner: { name: '2_Owner.sol', content: owner }, + ballot: { name: '3_Ballot.sol', content: ballot }, + ballot_test: { name: 'tests/4_Ballot_test.sol', content: ballotTest } +} diff --git a/apps/remix-ide-e2e/src/helpers/init.ts b/apps/remix-ide-e2e/src/helpers/init.ts index 61a3235417..e4c0bbf6b5 100644 --- a/apps/remix-ide-e2e/src/helpers/init.ts +++ b/apps/remix-ide-e2e/src/helpers/init.ts @@ -7,17 +7,14 @@ export default function (browser: NightwatchBrowser, callback: VoidFunction, url .url(url || 'http://127.0.0.1:8080') .pause(5000) .switchBrowserTab(0) - .injectScript('test-browser/helpers/applytestmode.js', function () { - browser.fullscreenWindow(() => { - if (preloadPlugins) { - console.log('preloadPlugins: ', preloadPlugins) - initModules(browser, () => { - browser.clickLaunchIcon('solidity') - .waitForElementPresent('[for="autoCompile"]') - .click('[for="autoCompile"]') - }) - } - }) + .fullscreenWindow(() => { + if (preloadPlugins) { + initModules(browser, () => { + browser.clickLaunchIcon('solidity') + .waitForElementPresent('[for="autoCompile"]') + .click('[for="autoCompile"]') + }) + } }) .perform(() => { callback() diff --git a/apps/remix-ide-e2e/src/tests/ballot.test.ts b/apps/remix-ide-e2e/src/tests/ballot.test.ts index 79294cf1be..cfc18f2f47 100644 --- a/apps/remix-ide-e2e/src/tests/ballot.test.ts +++ b/apps/remix-ide-e2e/src/tests/ballot.test.ts @@ -3,8 +3,7 @@ import { NightwatchBrowser } from 'nightwatch' import init from '../helpers/init' import sauce from './sauce' - -const examples = require('../../../../../apps/remix-ide/src/app/editor/example-contracts') // reference example-contracts from inside dist directory +import examples from '../examples/example-contracts' const sources = [ {'browser/Untitled.sol': { content: examples.ballot.content }} diff --git a/apps/remix-ide-e2e/src/types/index.d.ts b/apps/remix-ide-e2e/src/types/index.d.ts index d0400a04de..d9bcc5a7c5 100644 --- a/apps/remix-ide-e2e/src/types/index.d.ts +++ b/apps/remix-ide-e2e/src/types/index.d.ts @@ -1,17 +1,44 @@ // Merge custom command types with nightwatch types -import { NightwatchBrowser, NightwatchAPI, NightwatchBrowser, NightwatchBrowser } from "nightwatch"; +import { NightwatchBrowser, NightwatchBrowser, NightwatchBrowser } from "nightwatch"; declare module "nightwatch" { export interface NightwatchCustomCommands { clickLaunchIcon(this: NightwatchBrowser, icon: string): NightwatchBrowser, - switchBrowserTab(this: NightwatchBrowser, index: number): NightwatchBrowser + switchBrowserTab(this: NightwatchBrowser, index: number): NightwatchBrowser, + scrollAndClick(this: NightwatchBrowser, target: string): NightwatchBrowser, + scrollInto(this: NightwatchBrowser, target: string): NightwatchBrowser, + testContracts(this: NightwatchBrowser, fileName: string, contractCode: ContractContent, compiledContractNames: string[]): NightwatchBrowser, + setEditorValue(this: NightwatchBrowser, value: string, callback?: () => void): NightwatchBrowser, + addFile(this: NightwatchBrowser, name: string, content: NightwatchContractContent): NightwatchBrowser, + verifyContracts(this: NightwatchBrowser, compiledContractNames: string[]): NightwatchBrowser, + selectAccount(this: NightwatchBrowser, account?: string): NightwatchBrowser, + clickFunction(this: NightwatchBrowser, fnFullName: string, expectedInput?: NightwatchClickFunctionExpectedInput): NightwatchBrowser, + testFunction(this: NightwatchBrowser, txHash: string, expectedInput: NightwatchTestFunctionExpectedInput): NightwatchBrowser, + goToVMTraceStep(this: NightwatchBrowser, step: number, incr?: number): NightwatchBrowser } export interface NightwatchBrowser { - api: NightwatchAPI, + api: this, emit: (status: string) => void, - fullscreenWindow: (result?: any) => this, - injectScript: (scriptUrl: string, callback?: VoidFunction) => this + fullscreenWindow: (result?: any) => this + } + + export interface NightwatchContractContent { + content: string; + } + + export interface NightwatchVerifyContractOpts { + wait: number, + version?: string + } + + export interface NightwatchClickFunctionExpectedInput { + types: string, + values: string + } + + export interface NightwatchTestFunctionExpectedInput { + [key: string]: any } } \ No newline at end of file