Unverified Commit 64b2ec99 authored by yann300's avatar yann300 Committed by GitHub

Merge pull request #1219 from ethereum/runTab

Run tab
parents 517eeb30 41790513
...@@ -42,7 +42,7 @@ done ...@@ -42,7 +42,7 @@ done
npm run nightwatch_remote_chrome || TEST_EXITCODE=1 npm run nightwatch_remote_chrome || TEST_EXITCODE=1
npm run nightwatch_remote_firefox || TEST_EXITCODE=1 npm run nightwatch_remote_firefox || TEST_EXITCODE=1
npm run nightwatch_remote_safari || TEST_EXITCODE=1 # npm run nightwatch_remote_safari || TEST_EXITCODE=1
# npm run nightwatch_remote_ie || TEST_EXITCODE=1 # npm run nightwatch_remote_ie || TEST_EXITCODE=1
# npm run nightwatch_remote_parallel || TEST_EXITCODE=1 # npm run nightwatch_remote_parallel || TEST_EXITCODE=1
......
...@@ -53,8 +53,8 @@ module.exports = { ...@@ -53,8 +53,8 @@ module.exports = {
'desiredCapabilities': { 'desiredCapabilities': {
'browserName': 'safari', 'browserName': 'safari',
'javascriptEnabled': true, 'javascriptEnabled': true,
'platform': 'OS X 10.11', 'platform': 'macOS 10.13',
'version': '10.0', 'version': '11.0',
'acceptSslCerts': true, 'acceptSslCerts': true,
'build': 'build-' + buildId, 'build': 'build-' + buildId,
'tunnel-identifier': 'browsersolidity_tests_' + buildId 'tunnel-identifier': 'browsersolidity_tests_' + buildId
......
...@@ -523,7 +523,8 @@ Please make a backup of your contracts and start using http://remix.ethereum.org ...@@ -523,7 +523,8 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
editor: self._components.editor, editor: self._components.editor,
config: self._api.config, config: self._api.config,
txListener: txlistener, txListener: txlistener,
contextview: self._components.contextView contextview: self._components.contextView,
udapp: () => { return udapp }
} }
}) })
this._components.editorpanel.event.register('resize', direction => self._adjustLayout(direction)) this._components.editorpanel.event.register('resize', direction => self._adjustLayout(direction))
......
...@@ -28,6 +28,7 @@ class EditorPanel { ...@@ -28,6 +28,7 @@ class EditorPanel {
terminal: new Terminal({ terminal: new Terminal({
api: { api: {
cmdInterpreter: self._api.cmdInterpreter, cmdInterpreter: self._api.cmdInterpreter,
udapp: self._api.udapp,
getPosition (event) { getPosition (event) {
var limitUp = 36 var limitUp = 36
var limitDown = 20 var limitDown = 20
......
...@@ -27,20 +27,20 @@ var css = csjs` ...@@ -27,20 +27,20 @@ var css = csjs`
display : flex; display : flex;
align-items : center; align-items : center;
width : 100%; width : 100%;
padding : 5px;
} }
.clear { .clear {
margin-left : 10px; margin-right : 20px;
margin-right : 10px;
width : 10px; width : 10px;
cursor : pointer; cursor : pointer;
color : ${styles.terminal.icon_Color_TogglePanel}; color : ${styles.terminal.icon_Color_TogglePanel};
display : flex;
} }
.clear:hover { .clear:hover {
color : ${styles.terminal.icon_HoverColor_Menu}; color : ${styles.terminal.icon_HoverColor_Menu};
} }
.toggleTerminal { .toggleTerminal {
margin-right : 10px; margin-right : 20px;
margin-left : 20px;
font-size : 14px; font-size : 14px;
font-weight : bold; font-weight : bold;
cursor : pointer; cursor : pointer;
...@@ -56,6 +56,7 @@ var css = csjs` ...@@ -56,6 +56,7 @@ var css = csjs`
height : 100%; height : 100%;
overflow-y : auto; overflow-y : auto;
font-family : monospace; font-family : monospace;
margin : 0px;
} }
.terminal_bg { .terminal_bg {
display : flex; display : flex;
...@@ -137,9 +138,21 @@ var css = csjs` ...@@ -137,9 +138,21 @@ var css = csjs`
align-items : center; align-items : center;
justify-content : center; justify-content : center;
} }
.listen { .listen {}
min-width : 120px; .verticalLine {
display : flex; border-left : 1px solid ${styles.colors.veryLightGrey};
height : 65%;
margin-right : 30px; }
.pendingTx {
border : 1px solid ${styles.terminal.icon_HoverColor_Menu};
border-radius: 50%;
margin-right: 30px;
min-width: 13px;
height: 13px;
display: flex;
justify-content: center;
align-items: center;
font-size: 10px;
} }
.dragbarHorizontal { .dragbarHorizontal {
position : absolute; position : absolute;
......
...@@ -105,23 +105,40 @@ class Terminal { ...@@ -105,23 +105,40 @@ class Terminal {
${self._view.input} ${self._view.input}
</div> </div>
` `
self._view.icon = yo`<i onmouseenter=${hover} onmouseleave=${hover} onmousedown=${minimize} class="${css.toggleTerminal} fa fa-angle-double-down"></i>` self._view.icon = yo`
self._view.dragbar = yo`<div onmousedown=${mousedown} class=${css.dragbarHorizontal}></div>` <i onmouseenter=${hover} onmouseleave=${hover} onmousedown=${minimize}
class="${css.toggleTerminal} fa fa-angle-double-down"></i>`
self._view.dragbar = yo`
<div onmousedown=${mousedown} class=${css.dragbarHorizontal}></div>`
self._view.dropdown = self._components.dropdown.render() self._view.dropdown = self._components.dropdown.render()
self._view.pendingTxCount = yo`<div class=${css.pendingTx} title='Pending Transactions'>${self._view.pendingTxCount}</div>`
self._view.bar = yo` self._view.bar = yo`
<div class=${css.bar}> <div class=${css.bar}>
${self._view.dragbar} ${self._view.dragbar}
<div class=${css.menu}> <div class=${css.menu}>
${self._view.icon} ${self._view.icon}
<div class=${css.clear} onclick=${clear}> <div class=${css.clear} onclick=${clear}>
<i class="fa fa-ban" aria-hidden="true" onmouseenter=${hover} onmouseleave=${hover}></i> <i class="fa fa-ban" aria-hidden="true" title="Clear console"
onmouseenter=${hover} onmouseleave=${hover}></i>
</div>
${self._view.pendingTxCount}
<div class=${css.verticalLine}></div>
<div class=${css.listen}>
<input onchange=${listenOnNetwork} type="checkbox"
title="If checked Remix will listen on all transactions mined in the current environment and not only transactions created by you">
</div> </div>
${self._view.dropdown} ${self._view.dropdown}
<div class=${css.search}><i class="fa fa-search ${css.searchIcon}" aria-hidden="true"></i><input type="text" class=${css.filter} onkeydown=${filter} placeholder="Search transactions"></div> <div class=${css.search}>
<div class=${css.listen}><input onchange=${listenOnNetwork} type="checkbox"><label title="If checked Remix will listen on all transactions mined in the current environment and not only transactions created from the GUI">Listen on network</label></div> <i class="fa fa-search ${css.searchIcon}" aria-hidden="true"></i>
<input type="text" class=${css.filter} onkeydown=${filter} placeholder="Search transactions">
</div>
</div> </div>
</div> </div>
` `
setInterval(() => {
updatePendingTxs(self._api, self._view.pendingTxCount)
}, 5000)
function listenOnNetwork (ev) { function listenOnNetwork (ev) {
self.event.trigger('listenOnNetWork', [ev.currentTarget.checked]) self.event.trigger('listenOnNetWork', [ev.currentTarget.checked])
} }
...@@ -563,5 +580,10 @@ function domTerminalFeatures (self, scopedCommands) { ...@@ -563,5 +580,10 @@ function domTerminalFeatures (self, scopedCommands) {
} }
function blockify (el) { return yo`<div class=${css.block}>${el}</div>` } function blockify (el) { return yo`<div class=${css.block}>${el}</div>` }
// PENDING TX
function updatePendingTxs (api, el) {
var count = Object.keys(api.udapp().pendingTransactions()).length
el.innerText = count
}
module.exports = Terminal module.exports = Terminal
'use strict' 'use strict'
var $ = require('jquery') var $ = require('jquery')
var yo = require('yo-yo') var yo = require('yo-yo')
var helper = require('../../lib/helper.js')
var remixLib = require('remix-lib') var remixLib = require('remix-lib')
var ethJSUtil = require('ethereumjs-util')
var csjs = require('csjs-inject')
var txExecution = remixLib.execution.txExecution var txExecution = remixLib.execution.txExecution
var txFormat = remixLib.execution.txFormat var txFormat = remixLib.execution.txFormat
var txHelper = remixLib.execution.txHelper var txHelper = remixLib.execution.txHelper
var EventManager = remixLib.EventManager
var helper = require('../../lib/helper.js')
var executionContext = require('../../execution-context') var executionContext = require('../../execution-context')
var modalDialogCustom = require('../ui/modal-dialog-custom') var modalDialogCustom = require('../ui/modal-dialog-custom')
var copyToClipboard = require('../ui/copy-to-clipboard') var copyToClipboard = require('../ui/copy-to-clipboard')
var Card = require('../ui/card')
var Recorder = require('../../recorder') var Recorder = require('../../recorder')
var EventManager = remixLib.EventManager
var addTooltip = require('../ui/tooltip') var addTooltip = require('../ui/tooltip')
var ethJSUtil = require('ethereumjs-util')
var MultiParamManager = require('../../multiParamManager')
var csjs = require('csjs-inject')
var css = require('./styles/run-tab-styles') var css = require('./styles/run-tab-styles')
var MultiParamManager = require('../../multiParamManager')
var instanceContainer = yo`<div class="${css.instanceContainer}"></div>` function runTab (appAPI = {}, appEvents = {}, opts = {}) {
var noInstancesText = yo`<div class="${css.noInstancesText}">0 contract Instances</div>` /* -------------------------
VARIABLES
--------------------------- */
var self = this
var event = new EventManager()
appEvents.eventManager = event
self._view = {}
self.data = {
count: 0,
text: `All transactions (deployed contracts and function executions)
in this environment can be saved and replayed in
another environment. i.e. Transactions created in
Javascript VM can be replayed in the Injected Web3.`
}
var pendingTxsText = yo`<span>0 pending transactions</span>` self._view.recorderCount = yo`<span>0</span>`
self._view.instanceContainer = yo`<div class="${css.instanceContainer}"></div>`
self._view.clearInstanceElement = yo`
<i class="${css.clearinstance} ${css.icon} fa fa-trash" onclick=${() => clearInstanceList(self)}
title="Clear instances list and reset recorder" aria-hidden="true">
</i>`
self._view.instanceContainerTitle = yo`
<div class=${css.instanceContainerTitle}
title="Autogenerated generic user interfaces for interaction with deployed contracts">
UI for Deployed Contracts
${self._view.clearInstanceElement}
</div>`
self._view.noInstancesText = yo`
<div class="${css.noInstancesText}">
Currently you have no contract instances to interact with.
</div>`
function runTab (appAPI = {}, appEvents = {}, opts = {}) {
var container = yo`<div class="${css.runTabView}" id="runTabView" ></div>` var container = yo`<div class="${css.runTabView}" id="runTabView" ></div>`
var event = new EventManager() var recorderInterface = makeRecorder(appAPI, appEvents, opts, self)
var clearInstanceElement = yo`<i class="${css.clearinstance} ${css.icon} fa fa-trash" title="Clear Instances List" aria-hidden="true"></i>` self._view.collapsedView = yo`
clearInstanceElement.addEventListener('click', () => { <div class=${css.recorderCollapsedView}>
event.trigger('clearInstance', []) <div class=${css.recorderCount}>${self._view.recorderCount}</div>
}) </div>`
var recorderInterface = makeRecorder(event, appAPI, appEvents, opts)
var pendingTxsContainer = yo` self._view.expandedView = yo`
<div class="${css.pendingTxsContainer}"> <div class=${css.recorderExpandedView}>
<div class="${css.pendingTxsText}"> <div class=${css.recorderDescription}>
${pendingTxsText} ${self.data.text}
<span class="${css.transactionActions}"> </div>
<div class="${css.transactionActions}">
${recorderInterface.recordButton} ${recorderInterface.recordButton}
${recorderInterface.runButton} ${recorderInterface.runButton}
${clearInstanceElement} </div>
</span> </div>
</div> </div>`
</div>`
self.recorderOpts = {
title: 'Events recorded:',
collapsedView: self._view.collapsedView
}
var recorderCard = new Card({}, {}, self.recorderOpts)
recorderCard.event.register('expandCollapseCard', (arrow, body, status) => {
body.innerHTML = ''
status.innerHTML = ''
if (arrow === 'up') {
status.appendChild(self._view.collapsedView)
body.appendChild(self._view.expandedView)
} else if (arrow === 'down') {
status.appendChild(self._view.collapsedView)
}
})
/* -------------------------
MAIN HTML ELEMENT
--------------------------- */
var el = yo` var el = yo`
<div> <div>
${settings(container, appAPI, appEvents, opts)} ${settings(container, appAPI, appEvents, opts)}
${contractDropdown(event, appAPI, appEvents, opts, instanceContainer)} ${contractDropdown(event, appAPI, appEvents, opts, self)}
${pendingTxsContainer} ${recorderCard.render()}
${instanceContainer} ${self._view.instanceContainer}
</div> </div>
` `
container.appendChild(el) container.appendChild(el)
// PENDING transactions /* -------------------------
function updatePendingTxs (container, appAPI) { HELPER FUNCTIONS
var pendingCount = Object.keys(opts.udapp.pendingTransactions()).length --------------------------- */
pendingTxsText.innerText = pendingCount + ' pending transactions'
}
// DROPDOWN // DROPDOWN
var selectExEnv = el.querySelector('#selectExEnvOptions') var selectExEnv = el.querySelector('#selectExEnvOptions')
function clearInstanceList (self) {
event.trigger('clearInstance', [])
}
function setFinalContext () { function setFinalContext () {
// set the final context. Cause it is possible that this is not the one we've originaly selected // set the final context. Cause it is possible that this is not the one we've originaly selected
selectExEnv.value = executionContext.getProvider() selectExEnv.value = executionContext.getProvider()
...@@ -87,20 +135,23 @@ function runTab (appAPI = {}, appEvents = {}, opts = {}) { ...@@ -87,20 +135,23 @@ function runTab (appAPI = {}, appEvents = {}, opts = {}) {
modalDialogCustom.alert(alertMsg) modalDialogCustom.alert(alertMsg)
}, setFinalContext) }, setFinalContext)
}) })
selectExEnv.value = executionContext.getProvider() selectExEnv.value = executionContext.getProvider()
executionContext.event.register('contextChanged', (context, silent) => { executionContext.event.register('contextChanged', (context, silent) => {
setFinalContext() setFinalContext()
}) })
fillAccountsList(appAPI, opts, el) fillAccountsList(appAPI, opts, el)
setInterval(() => { setInterval(() => {
updateAccountBalances(container, appAPI) updateAccountBalances(container, appAPI)
updatePendingTxs(container, appAPI)
}, 10000) }, 10000)
event.register('clearInstance', () => { event.register('clearInstance', () => {
var instanceContainer = self._view.instanceContainer
var instanceContainerTitle = self._view.instanceContainerTitle
instanceContainer.innerHTML = '' // clear the instances list instanceContainer.innerHTML = '' // clear the instances list
noInstancesText.style.display = 'block' instanceContainer.appendChild(instanceContainerTitle)
instanceContainer.appendChild(noInstancesText) instanceContainer.appendChild(self._view.noInstancesText)
}) })
return { render () { return container } } return { render () { return container } }
} }
...@@ -133,31 +184,41 @@ function updateAccountBalances (container, appAPI) { ...@@ -133,31 +184,41 @@ function updateAccountBalances (container, appAPI) {
} }
/* ------------------------------------------------ /* ------------------------------------------------
RECORDER RECORDER
------------------------------------------------ */ ------------------------------------------------ */
function makeRecorder (events, appAPI, appEvents, opts) { function makeRecorder (appAPI, appEvents, opts, self) {
var recorder = new Recorder(opts.compiler, { var recorder = new Recorder(opts.compiler, {
events: { events: {
udapp: appEvents.udapp, udapp: appEvents.udapp,
executioncontext: executionContext.event, executioncontext: executionContext.event,
runtab: events runtab: appEvents.eventManager
}, },
api: appAPI api: appAPI
}) })
recorder.event.register('newTxRecorded', (count) => {
self.data.count = count
self._view.recorderCount.innerText = count
})
recorder.event.register('cleared', () => {
self.data.count = 0
self._view.recorderCount.innerText = 0
})
var css2 = csjs` var css2 = csjs`
.container, .container {}
.runTxs, .runTxs {}
.recorder { .recorder {}
}
` `
var recordButton = yo`<i class="fa fa-floppy-o savetransaction ${css2.recorder} ${css.icon}" title="Save Transactions" aria-hidden="true"></i>`
var runButton = yo`<i class="fa fa-play runtransaction ${css2.runTxs} ${css.icon}" title="Run Transactions" aria-hidden="true"></i>` var runButton = yo`<i class="fa fa-play runtransaction ${css2.runTxs} ${css.icon}" title="Run Transactions" aria-hidden="true"></i>`
var recordButton = yo`
<i class="fa fa-floppy-o savetransaction ${css2.recorder} ${css.icon}"
onclick=${triggerRecordButton} title="Save Transactions" aria-hidden="true">
</i>`
recordButton.onclick = () => { function triggerRecordButton () {
var txJSON = JSON.stringify(recorder.getAll(), null, 2) var txJSON = JSON.stringify(recorder.getAll(), null, 2)
var path = appAPI.currentPath() var path = appAPI.currentPath()
modalDialogCustom.prompt(null, 'save ran transactions to file (e.g. `scenario.json`). The file is going to be saved under ' + path, 'scenario.json', input => { modalDialogCustom.prompt(null, 'Transactions will be saved in a file under ' + path, 'scenario.json', input => {
var fileProvider = appAPI.fileProviderOf(path) var fileProvider = appAPI.fileProviderOf(path)
if (fileProvider) { if (fileProvider) {
var newFile = path + input var newFile = path + input
...@@ -172,7 +233,13 @@ function makeRecorder (events, appAPI, appEvents, opts) { ...@@ -172,7 +233,13 @@ function makeRecorder (events, appAPI, appEvents, opts) {
} }
}) })
} }
runButton.onclick = () => { runButton.onclick = () => {
/*
@TODO
update account address in scenario.json
popup if scenario.json not open - "Open a file with transactions you want to replay and click play again"
*/
var currentFile = appAPI.config.get('currentFile') var currentFile = appAPI.config.get('currentFile')
appAPI.fileProviderOf(currentFile).get(currentFile, (error, json) => { appAPI.fileProviderOf(currentFile).get(currentFile, (error, json) => {
if (error) { if (error) {
...@@ -183,16 +250,17 @@ function makeRecorder (events, appAPI, appEvents, opts) { ...@@ -183,16 +250,17 @@ function makeRecorder (events, appAPI, appEvents, opts) {
var obj = JSON.parse(json) var obj = JSON.parse(json)
var txArray = obj.transactions || [] var txArray = obj.transactions || []
var accounts = obj.accounts || [] var accounts = obj.accounts || []
var options = obj.options var options = obj.options || {}
var abis = obj.abis var abis = obj.abis || {}
var linkReferences = obj.linkReferences || {} var linkReferences = obj.linkReferences || {}
} catch (e) { } catch (e) {
return modalDialogCustom.alert('Invalid Scenario File, please try again') return modalDialogCustom.alert('Invalid Scenario File, please try again')
} }
if (txArray.length) { if (txArray.length) {
noInstancesText.style.display = 'none' var noInstancesText = self._view.noInstancesText
if (noInstancesText.parentNode) { noInstancesText.parentNode.removeChild(noInstancesText) }
recorder.run(txArray, accounts, options, abis, linkReferences, opts.udapp, (abi, address, contractName) => { recorder.run(txArray, accounts, options, abis, linkReferences, opts.udapp, (abi, address, contractName) => {
instanceContainer.appendChild(opts.udappUI.renderInstanceFromABI(abi, address, contractName)) self._view.instanceContainer.appendChild(opts.udappUI.renderInstanceFromABI(abi, address, contractName))
}) })
} }
} else { } else {
...@@ -201,14 +269,18 @@ function makeRecorder (events, appAPI, appEvents, opts) { ...@@ -201,14 +269,18 @@ function makeRecorder (events, appAPI, appEvents, opts) {
} }
}) })
} }
return { recordButton, runButton } return { recordButton, runButton }
} }
/* ------------------------------------------------ /* ------------------------------------------------
section CONTRACT DROPDOWN and BUTTONS CONTRACT (deploy or access deployed)
------------------------------------------------ */ ------------------------------------------------ */
function contractDropdown (events, appAPI, appEvents, opts, instanceContainer) { function contractDropdown (events, appAPI, appEvents, opts, self) {
instanceContainer.appendChild(noInstancesText) var instanceContainer = self._view.instanceContainer
var instanceContainerTitle = self._view.instanceContainerTitle
instanceContainer.appendChild(instanceContainerTitle)
instanceContainer.appendChild(self._view.noInstancesText)
var compFails = yo`<i title="Contract compilation failed. Please check the compile tab for more information." class="fa fa-times-circle ${css.errorIcon}" ></i>` var compFails = yo`<i title="Contract compilation failed. Please check the compile tab for more information." class="fa fa-times-circle ${css.errorIcon}" ></i>`
appEvents.compiler.register('compilationFinished', function (success, data, source) { appEvents.compiler.register('compilationFinished', function (success, data, source) {
getContractNames(success, data) getContractNames(success, data)
...@@ -222,7 +294,6 @@ function contractDropdown (events, appAPI, appEvents, opts, instanceContainer) { ...@@ -222,7 +294,6 @@ function contractDropdown (events, appAPI, appEvents, opts, instanceContainer) {
}) })
var atAddressButtonInput = yo`<input class="${css.input} ataddressinput" placeholder="Load contract from Address" title="atAddress" />` var atAddressButtonInput = yo`<input class="${css.input} ataddressinput" placeholder="Load contract from Address" title="atAddress" />`
var selectContractNames = yo`<select class="${css.contractNames}" disabled></select>` var selectContractNames = yo`<select class="${css.contractNames}" disabled></select>`
function getSelectedContract () { function getSelectedContract () {
...@@ -236,6 +307,7 @@ function contractDropdown (events, appAPI, appEvents, opts, instanceContainer) { ...@@ -236,6 +307,7 @@ function contractDropdown (events, appAPI, appEvents, opts, instanceContainer) {
return null return null
} }
appAPI.getSelectedContract = getSelectedContract appAPI.getSelectedContract = getSelectedContract
var createPanel = yo`<div class="${css.button}"></div>` var createPanel = yo`<div class="${css.button}"></div>`
var el = yo` var el = yo`
...@@ -247,7 +319,7 @@ function contractDropdown (events, appAPI, appEvents, opts, instanceContainer) { ...@@ -247,7 +319,7 @@ function contractDropdown (events, appAPI, appEvents, opts, instanceContainer) {
${createPanel} ${createPanel}
<div class="${css.button}"> <div class="${css.button}">
${atAddressButtonInput} ${atAddressButtonInput}
<div class="${css.atAddress}" onclick=${function () { loadFromAddress(appAPI) }}>At Address</div> <div class="${css.atAddress}" onclick=${function () { loadFromAddress(appAPI) }}>Access</div>
</div> </div>
</div> </div>
</div> </div>
...@@ -269,7 +341,7 @@ function contractDropdown (events, appAPI, appEvents, opts, instanceContainer) { ...@@ -269,7 +341,7 @@ function contractDropdown (events, appAPI, appEvents, opts, instanceContainer) {
selectContractNames.addEventListener('change', setInputParamsPlaceHolder) selectContractNames.addEventListener('change', setInputParamsPlaceHolder)
// ADD BUTTONS AT ADDRESS AND CREATE // DEPLOY INSTANCE
function createInstance (args) { function createInstance (args) {
var selectedContract = getSelectedContract() var selectedContract = getSelectedContract()
...@@ -292,7 +364,8 @@ function contractDropdown (events, appAPI, appEvents, opts, instanceContainer) { ...@@ -292,7 +364,8 @@ function contractDropdown (events, appAPI, appEvents, opts, instanceContainer) {
return return
} }
} }
noInstancesText.style.display = 'none' var noInstancesText = self._view.noInstancesText
if (noInstancesText.parentNode) { noInstancesText.parentNode.removeChild(noInstancesText) }
var address = isVM ? txResult.result.createdAddress : txResult.result.contractAddress var address = isVM ? txResult.result.createdAddress : txResult.result.contractAddress
instanceContainer.appendChild(opts.udappUI.renderInstance(selectedContract.contract.object, address, selectContractNames.value)) instanceContainer.appendChild(opts.udappUI.renderInstance(selectedContract.contract.object, address, selectContractNames.value))
} else { } else {
...@@ -310,8 +383,10 @@ function contractDropdown (events, appAPI, appEvents, opts, instanceContainer) { ...@@ -310,8 +383,10 @@ function contractDropdown (events, appAPI, appEvents, opts, instanceContainer) {
}) })
} }
// ACCESS DEPLOYED INSTANCE
function loadFromAddress (appAPI) { function loadFromAddress (appAPI) {
noInstancesText.style.display = 'none' var noInstancesText = self._view.noInstancesText
if (noInstancesText.parentNode) { noInstancesText.parentNode.removeChild(noInstancesText) }
var contractNames = document.querySelector(`.${css.contractNames.classNames[0]}`) var contractNames = document.querySelector(`.${css.contractNames.classNames[0]}`)
var address = atAddressButtonInput.value var address = atAddressButtonInput.value
if (!ethJSUtil.isValidAddress(address)) { if (!ethJSUtil.isValidAddress(address)) {
...@@ -353,12 +428,11 @@ function contractDropdown (events, appAPI, appEvents, opts, instanceContainer) { ...@@ -353,12 +428,11 @@ function contractDropdown (events, appAPI, appEvents, opts, instanceContainer) {
return el return el
} }
/* ------------------------------------------------ /* ------------------------------------------------
section SETTINGS: Environment, Account, Gas, Value section SETTINGS: Environment, Account, Gas, Value
------------------------------------------------ */ ------------------------------------------------ */
function settings (container, appAPI, appEvents, opts) { function settings (container, appAPI, appEvents, opts) {
// SETTINGS HTML // VARIABLES
var net = yo`<span class=${css.network}></span>` var net = yo`<span class=${css.network}></span>`
const updateNetwork = () => { const updateNetwork = () => {
executionContext.detectNetwork((err, { id, name } = {}) => { executionContext.detectNetwork((err, { id, name } = {}) => {
...@@ -370,82 +444,86 @@ function settings (container, appAPI, appEvents, opts) { ...@@ -370,82 +444,86 @@ function settings (container, appAPI, appEvents, opts) {
} }
}) })
} }
setInterval(updateNetwork, 5000) var environmentEl = yo`
function newAccount () { <div class="${css.crow}">
opts.udapp.newAccount('', (error, address) => { <div id="selectExEnv" class="${css.col1_1}">
if (!error) { Environment
container.querySelector('#txorigin').appendChild(yo`<option value=${address}>${address}</option>`)
addTooltip(`account ${address} created`)
} else {
addTooltip('Cannot create an account: ' + error)
}
})
}
var el = yo`
<div class="${css.settings}">
<div class="${css.crow}">
<div id="selectExEnv" class="${css.col1_1}">
Environment
</div>
<div class=${css.environment}>
${net}
<select id="selectExEnvOptions" onchange=${updateNetwork} class="${css.select}">
<option id="vm-mode"
title="Execution environment does not connect to any node, everything is local and in memory only."
value="vm"
checked name="executionContext">
JavaScript VM
</option>
<option id="injected-mode"
title="Execution environment has been provided by Mist or similar provider."
value="injected"
checked name="executionContext">
Injected Web3
</option>
<option id="web3-mode"
title="Execution environment connects to node at localhost (or via IPC if available), transactions will be sent to the network and can cause loss of money or worse!
If this page is served via https and you access your node via http, it might not work. In this case, try cloning the repository and serving it via http."
value="web3"
name="executionContext">
Web3 Provider
</option>
</select>
<a href="https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md" target="_blank"><i class="${css.icon} fa fa-info"></i></a>
</div>
</div>
<div class="${css.crow}">
<div class="${css.col1_1}">Account</div>
<select name="txorigin" class="${css.select}" id="txorigin"></select>
${copyToClipboard(() => document.querySelector('#runTabView #txorigin').value)}
<i class="fa fa-plus-square-o ${css.createAccount} ${css.icon}" aria-hidden="true" onclick=${newAccount} title="Create a new account"></i>
</div> </div>
<div class="${css.crow}"> <div class=${css.environment}>
<div class="${css.col1_1}">Gas limit</div> ${net}
<input type="number" class="${css.col2}" id="gasLimit" value="3000000"> <select id="selectExEnvOptions" onchange=${updateNetwork} class="${css.select}">
</div> <option id="vm-mode"
<div class="${css.crow}" style="display: none"> title="Execution environment does not connect to any node, everything is local and in memory only."
<div class="${css.col1_1}">Gas Price</div> value="vm" checked name="executionContext"> JavaScript VM
<input type="number" class="${css.col2}" id="gasPrice" value="0"> </option>
</div> <option id="injected-mode"
<div class="${css.crow}"> title="Execution environment has been provided by Metamask or similar provider."
<div class="${css.col1_1}">Value</div> value="injected" checked name="executionContext"> Injected Web3
<input type="text" class="${css.col2_1}" id="value" value="0" title="Enter the value and choose the unit"> </option>
<select name="unit" class="${css.col2_2}" id="unit"> <option id="web3-mode"
<option data-unit="wei">wei</option> title="Execution environment connects to node at localhost (or via IPC if available), transactions will be sent to the network and can cause loss of money or worse!
<option data-unit="gwei">gwei</option> If this page is served via https and you access your node via http, it might not work. In this case, try cloning the repository and serving it via http."
<option data-unit="finney">finney</option> value="web3" name="executionContext"> Web3 Provider
<option data-unit="ether">ether</option> </option>
</select> </select>
<a href="https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md" target="_blank"><i class="${css.icon} fa fa-info"></i></a>
</div> </div>
</div> </div>
` `
// EVENTS var accountEl = yo`
<div class="${css.crow}">
<div class="${css.col1_1}">Account</div>
<select name="txorigin" class="${css.select}" id="txorigin"></select>
${copyToClipboard(() => document.querySelector('#runTabView #txorigin').value)}
<i class="fa fa-plus-circle ${css.icon}" aria-hidden="true" onclick=${newAccount} title="Create a new account"></i>
</div>
`
var gasPriceEl = yo`
<div class="${css.crow}">
<div class="${css.col1_1}">Gas limit</div>
<input type="number" class="${css.col2}" id="gasLimit" value="3000000">
</div>
`
var valueEl = yo`
<div class="${css.crow}">
<div class="${css.col1_1}">Value</div>
<input type="text" class="${css.col2_1}" id="value" value="0" title="Enter the value and choose the unit">
<select name="unit" class="${css.col2_2}" id="unit">
<option data-unit="wei">wei</option>
<option data-unit="gwei">gwei</option>
<option data-unit="finney">finney</option>
<option data-unit="ether">ether</option>
</select>
</div>
`
// DOM ELEMENT
var el = yo`
<div class="${css.settings}">
${environmentEl}
${accountEl}
${gasPriceEl}
${valueEl}
</div>
`
// HELPER FUNCTIONS AND EVENTS
appEvents.udapp.register('transactionExecuted', (error, from, to, data, lookupOnly, txResult) => { appEvents.udapp.register('transactionExecuted', (error, from, to, data, lookupOnly, txResult) => {
if (error) return if (error) return
if (!lookupOnly) el.querySelector('#value').value = '0' if (!lookupOnly) el.querySelector('#value').value = '0'
updateAccountBalances(container, appAPI) updateAccountBalances(container, appAPI)
}) })
setInterval(updateNetwork, 5000)
function newAccount () {
appAPI.newAccount('', (error, address) => {
if (!error) {
container.querySelector('#txorigin').appendChild(yo`<option value=${address}>${address}</option>`)
addTooltip(`account ${address} created`)
} else {
addTooltip('Cannot create an account: ' + error)
}
})
}
return el return el
} }
......
...@@ -8,11 +8,29 @@ var css = csjs` ...@@ -8,11 +8,29 @@ var css = csjs`
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.instanceContainerTitle {
font-weight: bold;
margin-bottom: 5%;
font-size: 12px;
display: flex;
justify-content: space-between;
}
.settings { .settings {
${styles.rightPanel.runTab.box_RunTab} ${styles.rightPanel.runTab.box_RunTab}
margin-bottom: 2%; margin-bottom: 2%;
padding: 10px 15px 15px 15px; padding: 10px 15px 15px 15px;
} }
.recorderCount {
border: 1px solid ${styles.rightPanel.runTab.icon_HoverColor};
border-radius: 50%;
margin-right: 30px;
min-width: 13px;
height: 13px;
display: flex;
justify-content: center;
align-items: center;
font-size: 10px;
}
.crow { .crow {
margin-top: .5em; margin-top: .5em;
display: flex; display: flex;
...@@ -54,11 +72,13 @@ var css = csjs` ...@@ -54,11 +72,13 @@ var css = csjs`
width: 250px; width: 250px;
} }
.instanceContainer { .instanceContainer {
${styles.rightPanel.runTab.box_Instance}
display: flex; display: flex;
flex-direction: column; flex-direction: column;
margin-top: 2%; margin-bottom: 2%;
border: none; border: none;
text-align: center; text-align: center;
padding: 10px 0px 15px 15px;
} }
.pendingTxsContainer { .pendingTxsContainer {
${styles.rightPanel.runTab.box_Instance} ${styles.rightPanel.runTab.box_Instance}
...@@ -70,8 +90,16 @@ var css = csjs` ...@@ -70,8 +90,16 @@ var css = csjs`
} }
.container { .container {
${styles.rightPanel.runTab.box_RunTab} ${styles.rightPanel.runTab.box_RunTab}
margin-top: 2%; margin-bottom: 2%;
}
.recorderCollapsedView,
.recorderExpandedView {
display: flex;
flex-direction: column;
} }
.recorderDescription {
margin: 0 15px 15px 0;
}
.contractNames { .contractNames {
${styles.rightPanel.runTab.dropdown_RunTab} ${styles.rightPanel.runTab.dropdown_RunTab}
width: 100%; width: 100%;
...@@ -105,6 +133,7 @@ var css = csjs` ...@@ -105,6 +133,7 @@ var css = csjs`
.noInstancesText { .noInstancesText {
${styles.rightPanel.runTab.box_Instance} ${styles.rightPanel.runTab.box_Instance}
font-style: italic; font-style: italic;
text-align: left;
} }
.pendingTxsText { .pendingTxsText {
${styles.rightPanel.runTab.borderBox_Instance} ${styles.rightPanel.runTab.borderBox_Instance}
...@@ -176,14 +205,14 @@ var css = csjs` ...@@ -176,14 +205,14 @@ var css = csjs`
.networkItem { .networkItem {
margin-right: 5px; margin-right: 5px;
} }
.clearinstance {} .clearinstance {
margin-right: 15px;
}
.transactionActions { .transactionActions {
display: flex; display: flex;
width: 70px; justify-content: space-evenly;
justify-content: space-between; ${styles.rightPanel.runTab.box_Info_RunTab};
border: 1px solid ${styles.rightPanel.runTab.additionalText_Color}; width: 145px;
padding: 5px;
border-radius: 3px;
} }
` `
......
var yo = require('yo-yo')
var csjs = require('csjs-inject')
var styleGuide = require('./styles-guide/theme-chooser')
var styles = styleGuide.chooser()
var remixLib = require('remix-lib')
var EventManager = remixLib.EventManager
module.exports = class Card {
constructor (api, events, opts) {
const self = this
self._api = api
self._events = events
self._opts = opts
self._view = {}
self.event = new EventManager()
}
render () {
const self = this
if (self._view.el) return self._view.el
self._view.cardBody = yo`<div class=${css.cardBody}></div>`
self._view.arrow = yo`<i class="${css.arrow} fa fa-angle-up"
onclick=${(ev) => trigger(ev.target)}></i>`
self._view.expandCollapseButton = yo`
<div class=${css.expandCollapseButton}>${self._view.arrow}</div>`
self._view.statusBar = yo`<div class=${css.statusBar}>${self._opts.collapsedView}</div>`
self._view.cardHeader = yo`
<div class=${css.cardHeader}>
<div class=${css.cardTitles}>
<div class=${css.cardTitle}>${self._opts.title}</div>
${self._view.statusBar}
</div>
<div class=${css.expandCollapseButton}>${self._view.expandCollapseButton}</div>
</div>`
function trigger (el) {
var body = self._view.cardBody
var status = self._view.statusBar
el.classList.toggle('fa-angle-down')
var arrow = el.classList.toggle('fa-angle-up') ? 'down' : 'up'
self.event.trigger('expandCollapseCard', [arrow, body, status])
}
// HTML
self._view.el = yo`
<div class=${css.cardContainer}>
${self._view.cardHeader}
${self._view.cardBody}
</div>`
return self._view.el
}
}
const css = csjs`
.cardContainer {
${styles.remix.solidBox};
margin-bottom : 2%;
}
.cardHeader {
display : flex;
justify-content : space-between;
}
.statusBar {}
.cardBody {}
.cardTitles {
display : flex;
flex-direction : row;
align-items : center;
}
.cardTitle {
font-size : 13px;
font-weight : bold;
color : ${styles.appProperties.mainText_Color};
margin-right : 5px;
}
.expandCollapseButton {}
.arrow {
margin-right : 15px;
color : ${styles.appProperties.icon_Color};
font-weight : bold;
cursor : pointer;
font-size : 14px;
}
.arrow:hover {
color : ${styles.appProperties.icon_HoverColor};
}
`
...@@ -390,7 +390,12 @@ function styleGuide () { ...@@ -390,7 +390,12 @@ function styleGuide () {
tooltip_CopyToClipboard_Color: appProperties.tooltip_Color, tooltip_CopyToClipboard_Color: appProperties.tooltip_Color,
icon_Color_CopyToClipboard: appProperties.icon_Color, icon_Color_CopyToClipboard: appProperties.icon_Color,
icon_HoverColor_CopyToClipboard: appProperties.icon_HoverColor icon_HoverColor_CopyToClipboard: appProperties.icon_HoverColor,
solidBox: appProperties.uiElements.solidBorderBox({
BackgroundColor: appProperties.solidBox_BackgroundColor,
Color: appProperties.solidBox_TextColor
})
}, },
/* ------------------------------------------------------ /* ------------------------------------------------------
...@@ -569,6 +574,12 @@ function styleGuide () { ...@@ -569,6 +574,12 @@ function styleGuide () {
Color: appProperties.solidBox_TextColor Color: appProperties.solidBox_TextColor
}), }),
box_Info_RunTab: appProperties.uiElements.dottedBorderBox({
BackgroundColor: appProperties.solidBorderBox_BackgroundColor,
BorderColor: appProperties.solidBorderBox_BorderColor,
Color: appProperties.solidBorderBox_TextColor
}),
dropdown_RunTab: appProperties.uiElements.dropdown({ dropdown_RunTab: appProperties.uiElements.dropdown({
BackgroundColor: appProperties.dropdown_BackgroundColor, BackgroundColor: appProperties.dropdown_BackgroundColor,
BorderColor: appProperties.dropdown_BorderColor, BorderColor: appProperties.dropdown_BorderColor,
......
...@@ -10,6 +10,7 @@ var css = csjs` ...@@ -10,6 +10,7 @@ var css = csjs`
display : flex; display : flex;
flex-direction : column; flex-direction : column;
margin-right : 10px; margin-right : 10px;
width : auto;
} }
.selectbox { .selectbox {
display : flex; display : flex;
......
...@@ -131,6 +131,7 @@ class Recorder { ...@@ -131,6 +131,7 @@ class Recorder {
append (timestamp, record) { append (timestamp, record) {
var self = this var self = this
self.data.journal.push({ timestamp, record }) self.data.journal.push({ timestamp, record })
self.event.trigger('newTxRecorded', [self.data.journal.length])
} }
/** /**
...@@ -167,6 +168,7 @@ class Recorder { ...@@ -167,6 +168,7 @@ class Recorder {
self.data._abis = {} self.data._abis = {}
self.data._contractABIReferences = {} self.data._contractABIReferences = {}
self.data._linkReferences = {} self.data._linkReferences = {}
self.event.trigger('cleared', [])
} }
/** /**
......
...@@ -10,7 +10,7 @@ var css = csjs` ...@@ -10,7 +10,7 @@ var css = csjs`
.title { .title {
${styles.rightPanel.runTab.titlebox_RunTab} ${styles.rightPanel.runTab.titlebox_RunTab}
display: flex; display: flex;
justify-content: end; justify-content: space-between;
align-items: center; align-items: center;
font-size: 11px; font-size: 11px;
height: 30px; height: 30px;
...@@ -21,6 +21,9 @@ var css = csjs` ...@@ -21,6 +21,9 @@ var css = csjs`
overflow: visible; overflow: visible;
margin-bottom: 10px; margin-bottom: 10px;
} }
.noInstancesText {
}
.titleLine { .titleLine {
display: flex; display: flex;
align-items: baseline; align-items: baseline;
...@@ -35,11 +38,9 @@ var css = csjs` ...@@ -35,11 +38,9 @@ var css = csjs`
color: ${styles.rightPanel.runTab.icon_AltColor_Instance_CopyToClipboard}; color: ${styles.rightPanel.runTab.icon_AltColor_Instance_CopyToClipboard};
} }
.instance { .instance {
${styles.rightPanel.runTab.box_Instance}; min-width: 310px;
margin-bottom: 10px; display: flex;
padding: 10px 15px 15px 15px; flex-direction: column;
position: relative;
overflow: visible;
} }
.instance .title:before { .instance .title:before {
content: "\\25BE"; content: "\\25BE";
...@@ -81,7 +82,9 @@ var css = csjs` ...@@ -81,7 +82,9 @@ var css = csjs`
.closeIcon { .closeIcon {
font-size: 12px; font-size: 12px;
cursor: pointer; cursor: pointer;
margin-left: 5px;
} }
.udapp {}
.udappClose { .udappClose {
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
...@@ -211,7 +214,7 @@ var css = csjs` ...@@ -211,7 +214,7 @@ var css = csjs`
margin-right: 5%; margin-right: 5%;
font-size: 10px; font-size: 10px;
border-width: 1px; border-width: 1px;
width: inherit; width: inherit;
} }
.multiHeader button { .multiHeader button {
display: inline-block; display: inline-block;
......
...@@ -14,7 +14,6 @@ var MultiParamManager = require('./multiParamManager') ...@@ -14,7 +14,6 @@ var MultiParamManager = require('./multiParamManager')
function UniversalDAppUI (udapp, opts = {}) { function UniversalDAppUI (udapp, opts = {}) {
var self = this var self = this
this.udapp = udapp this.udapp = udapp
self.el = yo`<div class=${css.udapp}></div>` self.el = yo`<div class=${css.udapp}></div>`
} }
...@@ -23,6 +22,10 @@ UniversalDAppUI.prototype.reset = function () { ...@@ -23,6 +22,10 @@ UniversalDAppUI.prototype.reset = function () {
} }
UniversalDAppUI.prototype.renderInstance = function (contract, address, contractName) { UniversalDAppUI.prototype.renderInstance = function (contract, address, contractName) {
var noInstances = document.querySelector('[class^="noInstancesText"]')
if (noInstances) {
noInstances.parentNode.removeChild(noInstances)
}
var abi = this.udapp.getABI(contract) var abi = this.udapp.getABI(contract)
return this.renderInstanceFromABI(abi, address, contractName) return this.renderInstanceFromABI(abi, address, contractName)
} }
...@@ -33,22 +36,25 @@ UniversalDAppUI.prototype.renderInstance = function (contract, address, contract ...@@ -33,22 +36,25 @@ UniversalDAppUI.prototype.renderInstance = function (contract, address, contract
// this returns a DOM element // this returns a DOM element
UniversalDAppUI.prototype.renderInstanceFromABI = function (contractABI, address, contractName) { UniversalDAppUI.prototype.renderInstanceFromABI = function (contractABI, address, contractName) {
var self = this var self = this
function remove () { instance.remove() }
address = (address.slice(0, 2) === '0x' ? '' : '0x') + address.toString('hex') address = (address.slice(0, 2) === '0x' ? '' : '0x') + address.toString('hex')
var instance = yo`<div class="instance ${css.instance}" id="instance${address}"></div>` var instance = yo`<div class="instance ${css.instance} ${css.hidesub}" id="instance${address}"></div>`
var context = self.udapp.context() var context = self.udapp.context()
var shortAddress = helper.shortenAddress(address) var shortAddress = helper.shortenAddress(address)
var title = yo`<div class="${css.title}" onclick=${toggleClass}> var title = yo`
<div class="${css.title}" onclick=${toggleClass}>
<div class="${css.titleText}"> ${contractName} at ${shortAddress} (${context}) </div> <div class="${css.titleText}"> ${contractName} at ${shortAddress} (${context}) </div>
${copyToClipboard(() => address)} ${copyToClipboard(() => address)}
</div>` </div>`
if (self.udapp.removable_instances) { if (self.udapp.removable_instances) {
var close = yo`<div class="${css.udappClose}" onclick=${remove}><i class="${css.closeIcon} fa fa-close" aria-hidden="true"></i></div>` var close = yo`<div class="${css.udappClose}" onclick=${remove}><i class="${css.closeIcon} fa fa-close" aria-hidden="true"></i></div>`
instance.appendChild(close) title.appendChild(close)
}
function remove () {
instance.remove()
// @TODO perhaps add a callack here to warn the caller that the instance has been removed
} }
function toggleClass () { function toggleClass () {
......
...@@ -43,7 +43,7 @@ function getCompiledContracts (browser, compiled, callback) { ...@@ -43,7 +43,7 @@ function getCompiledContracts (browser, compiled, callback) {
function createContract (browser, inputParams, callback) { function createContract (browser, inputParams, callback) {
browser.click('.runView') browser.click('.runView')
.setValue('div[class^="contractActionsContainerSingle"] input', inputParams, function () { .setValue('div[class^="contractActionsContainerSingle"] input', inputParams, function () {
browser.click('#runTabView button[class^="instanceButton"]').perform(function () { callback() }) browser.click('#runTabView button[class^="instanceButton"]').pause(500).perform(function () { callback() })
}) })
} }
......
...@@ -36,6 +36,8 @@ function runTests (browser, testData) { ...@@ -36,6 +36,8 @@ function runTests (browser, testData) {
}).click('.runView') }).click('.runView')
.setValue('input[placeholder="uint8 _numProposals"]', '1') .setValue('input[placeholder="uint8 _numProposals"]', '1')
.click('#runTabView button[class^="instanceButton"]') .click('#runTabView button[class^="instanceButton"]')
.waitForElementPresent('.instance:nth-of-type(2)')
.click('.instance:nth-of-type(2)')
.testFunction('delegate - transact (not payable)', '0x0571a2439ea58bd349dd130afb8aff62a33af14c06de0dbc3928519bdf13ce2e', .testFunction('delegate - transact (not payable)', '0x0571a2439ea58bd349dd130afb8aff62a33af14c06de0dbc3928519bdf13ce2e',
`[vm]\nfrom:0xca3...a733c\nto:Ballot.delegate(address) 0x692...77b3a\nvalue:0 wei\ndata:0x5c1...4d2db\nlogs:0\nhash:0x057...3ce2e`, `[vm]\nfrom:0xca3...a733c\nto:Ballot.delegate(address) 0x692...77b3a\nvalue:0 wei\ndata:0x5c1...4d2db\nlogs:0\nhash:0x057...3ce2e`,
{types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"'}, null, null) {types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"'}, null, null)
...@@ -83,9 +85,10 @@ function runTests (browser, testData) { ...@@ -83,9 +85,10 @@ function runTests (browser, testData) {
done() done()
}) })
}) })
.pause(500)
.perform((client, done) => { .perform((client, done) => {
console.log('delegate - transact (not payable)') console.log('delegate - transact (not payable)')
browser.testFunction('delegate - transact (not payable)', '0xd3cd54e2f76f3993078ecf9e1b54a148def4520afc141a182293b3610bddf10f', browser.waitForElementPresent('.instance:nth-of-type(2)').click('.instance:nth-of-type(2)').testFunction('delegate - transact (not payable)', '0xd3cd54e2f76f3993078ecf9e1b54a148def4520afc141a182293b3610bddf10f',
`[vm]\nfrom:0xca3...a733c\nto:Ballot.delegate(address) 0x692...77b3a\nvalue:0 wei\ndata:0x5c1...4d2db\nlogs:0\nhash:0xd3c...df10f`, `[vm]\nfrom:0xca3...a733c\nto:Ballot.delegate(address) 0x692...77b3a\nvalue:0 wei\ndata:0x5c1...4d2db\nlogs:0\nhash:0xd3c...df10f`,
{types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"'}, null, null, () => { done() }) {types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"'}, null, null, () => { done() })
}).end() }).end()
......
...@@ -39,7 +39,8 @@ function testSimpleContract (browser, callback) { ...@@ -39,7 +39,8 @@ function testSimpleContract (browser, callback) {
contractHelper.testContracts(browser, 'Untitled.sol', sources[0]['browser/Untitled.sol'], ['TestContract'], function () { contractHelper.testContracts(browser, 'Untitled.sol', sources[0]['browser/Untitled.sol'], ['TestContract'], function () {
browser.click('.runView') browser.click('.runView')
.click('#runTabView button[class^="instanceButton"]') .click('#runTabView button[class^="instanceButton"]')
.pause(500) .waitForElementPresent('.instance:nth-of-type(2)')
.click('.instance:nth-of-type(2)')
.click('#runTabView .instance div[class^="title"]') .click('#runTabView .instance div[class^="title"]')
.click('#runTabView .instance div[class^="title"]') .click('#runTabView .instance div[class^="title"]')
.testFunction('f - transact (not payable)', .testFunction('f - transact (not payable)',
...@@ -69,7 +70,8 @@ function testReturnValues (browser, callback) { ...@@ -69,7 +70,8 @@ function testReturnValues (browser, callback) {
contractHelper.testContracts(browser, 'returnValues.sol', sources[1]['browser/returnValues.sol'], ['testReturnValues'], function () { contractHelper.testContracts(browser, 'returnValues.sol', sources[1]['browser/returnValues.sol'], ['testReturnValues'], function () {
browser.click('.runView') browser.click('.runView')
.click('#runTabView button[class^="instanceButton"]') .click('#runTabView button[class^="instanceButton"]')
.pause(500) .waitForElementPresent('.instance:nth-of-type(2)')
.click('.instance:nth-of-type(2)')
.testFunction('retunValues1 - transact (not payable)', .testFunction('retunValues1 - transact (not payable)',
'0x79dc928d149d2ade02ab610a8ae290636222d034d4adce0bb08a68401e3d1f7f', '0x79dc928d149d2ade02ab610a8ae290636222d034d4adce0bb08a68401e3d1f7f',
`[vm]\nfrom:0xca3...a733c\nto:testReturnValues.retunValues1() 0x5e7...26e9f\nvalue:0 wei\ndata:0x9ed...59eb7\nlogs:0\nhash:0x79d...d1f7f`, `[vm]\nfrom:0xca3...a733c\nto:testReturnValues.retunValues1() 0x5e7...26e9f\nvalue:0 wei\ndata:0x9ed...59eb7\nlogs:0\nhash:0x79d...d1f7f`,
...@@ -107,7 +109,8 @@ function testInputValues (browser, callback) { ...@@ -107,7 +109,8 @@ function testInputValues (browser, callback) {
contractHelper.testContracts(browser, 'inputValues.sol', sources[2]['browser/inputValues.sol'], ['test'], function () { contractHelper.testContracts(browser, 'inputValues.sol', sources[2]['browser/inputValues.sol'], ['test'], function () {
browser.click('.runView') browser.click('.runView')
.click('#runTabView button[class^="instanceButton"]') .click('#runTabView button[class^="instanceButton"]')
.pause(500) .waitForElementPresent('.instance:nth-of-type(2)')
.click('.instance:nth-of-type(2)')
.testFunction('inputValue1 - transact (not payable)', .testFunction('inputValue1 - transact (not payable)',
'0x917a873d27d105213eaf5461e14780387ccceb66fed574f8432d1963917832ae', '0x917a873d27d105213eaf5461e14780387ccceb66fed574f8432d1963917832ae',
`[vm]\nfrom:0xca3...a733c\nto:test.inputValue1(uint256,int256,string) 0x8c1...401f5\nvalue:0 wei\ndata:0xd69...00000\nlogs:0\nhash:0x917...832ae`, `[vm]\nfrom:0xca3...a733c\nto:test.inputValue1(uint256,int256,string) 0x8c1...401f5\nvalue:0 wei\ndata:0xd69...00000\nlogs:0\nhash:0x917...832ae`,
......
...@@ -10,7 +10,12 @@ module.exports = { ...@@ -10,7 +10,12 @@ module.exports = {
contractHelper.addFile(browser, 'scenario.json', {content: records}, () => { contractHelper.addFile(browser, 'scenario.json', {content: records}, () => {
browser browser
.click('.runView') .click('.runView')
.click('div[class^="cardContainer"] i[class^="arrow"]')
.click('#runTabView .runtransaction') .click('#runTabView .runtransaction')
.waitForElementPresent('.instance:nth-of-type(2)')
.click('.instance:nth-of-type(2)')
.waitForElementPresent('.instance:nth-of-type(3)')
.click('.instance:nth-of-type(3)')
.clickFunction('getInt - call') .clickFunction('getInt - call')
.clickFunction('getAddress - call') .clickFunction('getAddress - call')
.clickFunction('getFromLib - call') .clickFunction('getFromLib - call')
...@@ -31,6 +36,8 @@ module.exports = { ...@@ -31,6 +36,8 @@ module.exports = {
done() done()
}) })
}) })
.waitForElementPresent('.instance:nth-of-type(2)')
.click('.instance:nth-of-type(2)')
.perform((client, done) => { .perform((client, done) => {
browser.clickFunction('set - transact (not payable)', {types: 'uint256 _p', values: '34'}) browser.clickFunction('set - transact (not payable)', {types: 'uint256 _p', values: '34'})
.click('i.savetransaction').modalFooterOKClick().getEditorValue(function (result) { .click('i.savetransaction').modalFooterOKClick().getEditorValue(function (result) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment