You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
512 lines
15 KiB
512 lines
15 KiB
'use strict'
|
|
|
|
import { NightwatchBrowser } from 'nightwatch'
|
|
import init from '../helpers/init'
|
|
import examples from '../examples/example-contracts'
|
|
|
|
const sources = [
|
|
{ 'Untitled.sol': { content: examples.ballot.content } }
|
|
]
|
|
|
|
module.exports = {
|
|
"@disabled": true,
|
|
before: function (browser: NightwatchBrowser, done: VoidFunction) {
|
|
init(browser, done)
|
|
},
|
|
'@sources': function () {
|
|
return sources
|
|
},
|
|
'Add Ballot #group2': function (browser: NightwatchBrowser) {
|
|
browser
|
|
.addFile('Untitled.sol', sources[0]['Untitled.sol'])
|
|
},
|
|
'Deploy Ballot #group1': function (browser: NightwatchBrowser) {
|
|
browser
|
|
.waitForElementVisible('*[data-id="remixIdeIconPanel"]', 10000)
|
|
.clickLaunchIcon('solidity')
|
|
.testContracts('Untitled.sol', sources[0]['Untitled.sol'], ['Ballot'])
|
|
.clickLaunchIcon('udapp')
|
|
.selectAccount('0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c')
|
|
.setValue('input[placeholder="bytes32[] proposalNames"]', '["0x48656c6c6f20576f726c64210000000000000000000000000000000000000000"]')
|
|
.click('*[data-id="Deploy - transact (not payable)"]')
|
|
.waitForElementPresent('*[data-id="universalDappUiContractActionWrapper"]', 60000)
|
|
.clickInstance(0)
|
|
.clickFunction('delegate - transact (not payable)', { types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"' })
|
|
.testFunction('last',
|
|
{
|
|
status: 'true Transaction mined and execution succeed',
|
|
'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' }
|
|
})
|
|
},
|
|
|
|
'Call method from Ballot to check return value #group1': function (browser: NightwatchBrowser) {
|
|
browser
|
|
.clickFunction('winnerName - call')
|
|
// Test in terminal
|
|
.testFunction('last',
|
|
{
|
|
to: 'Ballot.winnerName() 0x692a70D2e424a56D2C6C27aA97D1a86395877b3A',
|
|
'decoded output': { 0: 'bytes32: winnerName_ 0x48656c6c6f20576f726c64210000000000000000000000000000000000000000' }
|
|
})
|
|
// Test in Udapp UI , treeViewDiv0 shows returned value on method click
|
|
.assert.containsText('*[data-id="treeViewDiv0"]', 'bytes32: winnerName_ 0x48656c6c6f20576f726c64210000000000000000000000000000000000000000')
|
|
},
|
|
|
|
'Debug Ballot / delegate #group1': function (browser: NightwatchBrowser) {
|
|
browser.pause(500)
|
|
.debugTransaction(1)
|
|
.waitForElementVisible('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]')
|
|
.click('*[data-id="buttonNavigatorJumpPreviousBreakpoint"]')
|
|
.pause(2000)
|
|
.waitForElementVisible('#stepdetail')
|
|
.goToVMTraceStep(144)
|
|
.pause(2000)
|
|
.checkVariableDebug('soliditystate', stateCheck)
|
|
.checkVariableDebug('soliditylocals', localsCheck)
|
|
},
|
|
|
|
'Access Ballot via at address #group1': function (browser: NightwatchBrowser) {
|
|
browser.clickLaunchIcon('udapp')
|
|
.click('*[data-id="universalDappUiUdappClose"]')
|
|
.addFile('ballot.abi', { content: ballotABI })
|
|
.clickLaunchIcon('udapp')
|
|
.click({
|
|
selector: '*[data-id="deployAndRunClearInstances"]',
|
|
abortOnFailure: false,
|
|
suppressNotFoundErrors: true,
|
|
})
|
|
// we are not changing the visibility for not checksumed contracts
|
|
// .addAtAddressInstance('0x692a70D2e424a56D2C6C27aA97D1a86395877b3B', true, false)
|
|
.clickLaunchIcon('filePanel')
|
|
.addAtAddressInstance('0x692a70D2e424a56D2C6C27aA97D1a86395877b3A', true, true)
|
|
.waitForElementVisible({
|
|
locateStrategy: 'xpath',
|
|
selector: "//*[@id='instance0x692a70D2e424a56D2C6C27aA97D1a86395877b3A']"
|
|
})
|
|
.clickInstance(0)
|
|
.clickFunction('delegate - transact (not payable)', { types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"' })
|
|
.testFunction('last',
|
|
{
|
|
status: 'false Transaction mined but execution failed',
|
|
'decoded input': { 'address to': '0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB' }
|
|
})
|
|
},
|
|
|
|
'Deploy and use Ballot using external web3 #group2': function (browser: NightwatchBrowser) {
|
|
browser
|
|
.openFile('Untitled.sol')
|
|
.clickLaunchIcon('udapp')
|
|
.connectToExternalHttpProvider('http://localhost:8545', 'Custom')
|
|
.clickLaunchIcon('solidity')
|
|
.clickLaunchIcon('udapp')
|
|
.pause(2000)
|
|
.clearValue('input[placeholder="bytes32[] proposalNames"]')
|
|
.setValue('input[placeholder="bytes32[] proposalNames"]', '["0x48656c6c6f20576f726c64210000000000000000000000000000000000000000"]')
|
|
.click('*[data-id="Deploy - transact (not payable)"]')
|
|
.clickInstance(0)
|
|
.click('*[data-id="terminalClearConsole"]')
|
|
.clickFunction('delegate - transact (not payable)', { types: 'address to', values: '0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c' })
|
|
.journalLastChildIncludes('Ballot.delegate(address)')
|
|
.journalLastChildIncludes('data: 0x5c1...a733c')
|
|
},
|
|
|
|
'Call method from Ballot to check return value using external web3 #group2': function (browser: NightwatchBrowser) {
|
|
browser
|
|
.clickFunction('winnerName - call')
|
|
// Test in terminal
|
|
.journalLastChildIncludes('Ballot.winnerName()')
|
|
.testFunction('last',
|
|
{
|
|
'decoded output': { 0: 'bytes32: winnerName_ 0x48656c6c6f20576f726c64210000000000000000000000000000000000000000' }
|
|
})
|
|
// Test in Udapp UI , treeViewDiv0 shows returned value on method click
|
|
.assert.containsText('*[data-id="treeViewDiv0"]', 'bytes32: winnerName_ 0x48656c6c6f20576f726c64210000000000000000000000000000000000000000')
|
|
},
|
|
|
|
'Compile Ballot using config file #group2': function (browser: NightwatchBrowser) {
|
|
browser
|
|
.addFile('cf.json', { content: configFile })
|
|
.clickLaunchIcon('solidity')
|
|
.waitForElementVisible('*[data-id="scConfigExpander"]')
|
|
.click('*[data-id="scConfigExpander"]')
|
|
.waitForElementVisible('*[data-id="scFileConfiguration"]', 10000)
|
|
.click('*[data-id="scFileConfiguration"]')
|
|
// the input field behaves badly, it would often not receive the value, so retrying it a few times for now is the best thing to do
|
|
.waitForElementVisible({
|
|
selector: '*[data-id="scConfigChangeFilePath"]',
|
|
abortOnFailure: false
|
|
}, 10000)
|
|
.click({
|
|
selector: '*[data-id="scConfigChangeFilePath"]',
|
|
suppressNotFoundErrors: true,
|
|
timeout: 1000
|
|
})
|
|
.click({
|
|
selector: '*[data-id="scConfigChangeFilePath"]',
|
|
suppressNotFoundErrors: true,
|
|
timeout: 1000
|
|
})
|
|
.click({
|
|
selector: '*[data-id="scConfigChangeFilePath"]',
|
|
suppressNotFoundErrors: true,
|
|
timeout: 1000
|
|
})
|
|
|
|
.waitForElementVisible('*[data-id="scConfigFilePathInput"]', 10000)
|
|
.sendKeys('*[data-id="scConfigFilePathInput"]', 'cf.json')
|
|
.sendKeys('*[data-id="scConfigFilePathInput"]', browser.Keys.ENTER)
|
|
|
|
.isVisible({
|
|
selector:"//*[@class='py-2 remixui_compilerConfigPath' and contains(.,'cf.json')]",
|
|
suppressNotFoundErrors: true,
|
|
locateStrategy: 'xpath'
|
|
}, (okVisible) => {
|
|
// if it's not there yet, try again
|
|
if (!okVisible.value) {
|
|
browser.waitForElementVisible({
|
|
selector: '*[data-id="scConfigChangeFilePath"]',
|
|
abortOnFailure: false
|
|
}, 10000)
|
|
.click({
|
|
selector: '*[data-id="scConfigChangeFilePath"]',
|
|
suppressNotFoundErrors: true,
|
|
timeout: 1000
|
|
})
|
|
.click({
|
|
selector: '*[data-id="scConfigChangeFilePath"]',
|
|
suppressNotFoundErrors: true,
|
|
timeout: 1000
|
|
})
|
|
.click({
|
|
selector: '*[data-id="scConfigChangeFilePath"]',
|
|
suppressNotFoundErrors: true,
|
|
timeout: 1000
|
|
})
|
|
|
|
.waitForElementVisible('*[data-id="scConfigFilePathInput"]', 10000)
|
|
.sendKeys('*[data-id="scConfigFilePathInput"]', 'cf.json')
|
|
.sendKeys('*[data-id="scConfigFilePathInput"]', browser.Keys.ENTER)
|
|
}
|
|
})
|
|
|
|
.isVisible({
|
|
selector:"//*[@class='py-2 remixui_compilerConfigPath' and contains(.,'cf.json')]",
|
|
suppressNotFoundErrors: true,
|
|
locateStrategy: 'xpath'
|
|
}, (okVisible) => {
|
|
if (!okVisible.value) {
|
|
// if it's still not there, try again
|
|
browser.waitForElementVisible({
|
|
selector: '*[data-id="scConfigChangeFilePath"]',
|
|
abortOnFailure: false
|
|
}, 10000)
|
|
.click({
|
|
selector: '*[data-id="scConfigChangeFilePath"]',
|
|
suppressNotFoundErrors: true,
|
|
timeout: 1000
|
|
})
|
|
.click({
|
|
selector: '*[data-id="scConfigChangeFilePath"]',
|
|
suppressNotFoundErrors: true,
|
|
timeout: 1000
|
|
})
|
|
.click({
|
|
selector: '*[data-id="scConfigChangeFilePath"]',
|
|
suppressNotFoundErrors: true,
|
|
timeout: 1000
|
|
})
|
|
|
|
.waitForElementVisible('*[data-id="scConfigFilePathInput"]', 10000)
|
|
.sendKeys('*[data-id="scConfigFilePathInput"]', 'cf.json')
|
|
.sendKeys('*[data-id="scConfigFilePathInput"]', browser.Keys.ENTER)
|
|
}
|
|
})
|
|
|
|
.pause(5000)
|
|
.openFile('Untitled.sol')
|
|
.verifyContracts(['Ballot'], { wait: 2000, runs: '300' })
|
|
},
|
|
|
|
'Compile and deploy sample yul file #group2': function (browser: NightwatchBrowser) {
|
|
browser
|
|
.addFile('sample.yul', { content: yulSample })
|
|
.clickLaunchIcon('solidity')
|
|
.waitForElementVisible('*[data-id="scConfigExpander"]')
|
|
.click('*[data-id="scManualConfiguration"]')
|
|
.waitForElementVisible('select[id="compilierLanguageSelector"]', 10000)
|
|
.click('select[id="compilierLanguageSelector"]')
|
|
.click('select[id="compilierLanguageSelector"] option[value=Yul]')
|
|
.waitForElementContainsText('[data-id="compiledContracts"]', 'Contract', 65000)
|
|
.clickLaunchIcon('udapp')
|
|
.click('*[data-id="Deploy - transact (not payable)"]')
|
|
.waitForElementPresent('*[data-id="universalDappUiContractActionWrapper"]', 60000)
|
|
.journalLastChildIncludes('Contract.(constructor)')
|
|
.journalLastChildIncludes('data: 0x602...0565b')
|
|
.end()
|
|
}
|
|
}
|
|
|
|
const localsCheck = {
|
|
to: {
|
|
value: '0x4B0897B0513FDC7C541B6D9D7E929C4E5364D2DB',
|
|
type: 'address'
|
|
}
|
|
}
|
|
|
|
const stateCheck = {
|
|
chairperson: {
|
|
value: '0xCA35B7D915458EF540ADE6068DFE2F44E8FA733C',
|
|
type: 'address',
|
|
constant: false,
|
|
immutable: false
|
|
},
|
|
voters: {
|
|
value: {
|
|
'000000000000000000000000ca35b7d915458ef540ade6068dfe2f44e8fa733c': {
|
|
value: {
|
|
weight: {
|
|
value: '1',
|
|
type: 'uint256'
|
|
},
|
|
voted: {
|
|
value: false,
|
|
type: 'bool'
|
|
},
|
|
delegate: {
|
|
value: '0x0000000000000000000000000000000000000000',
|
|
type: 'address'
|
|
},
|
|
vote: {
|
|
value: '0',
|
|
type: 'uint256'
|
|
}
|
|
},
|
|
type: 'struct Ballot.Voter'
|
|
}
|
|
},
|
|
type: 'mapping(address => struct Ballot.Voter)',
|
|
constant: false,
|
|
immutable: false
|
|
},
|
|
proposals: {
|
|
value: [
|
|
{
|
|
value: {
|
|
name: {
|
|
value: '0x48656C6C6F20576F726C64210000000000000000000000000000000000000000',
|
|
type: 'bytes32'
|
|
},
|
|
voteCount: {
|
|
value: '0',
|
|
type: 'uint256'
|
|
}
|
|
},
|
|
type: 'struct Ballot.Proposal'
|
|
}
|
|
],
|
|
length: '0x1',
|
|
type: 'struct Ballot.Proposal[]',
|
|
constant: false,
|
|
immutable: false
|
|
}
|
|
}
|
|
|
|
const ballotABI = `[
|
|
{
|
|
"inputs": [
|
|
{
|
|
"internalType": "bytes32[]",
|
|
"name": "proposalNames",
|
|
"type": "bytes32[]"
|
|
}
|
|
],
|
|
"payable": false,
|
|
"stateMutability": "nonpayable",
|
|
"type": "constructor"
|
|
},
|
|
{
|
|
"constant": true,
|
|
"inputs": [],
|
|
"name": "chairperson",
|
|
"outputs": [
|
|
{
|
|
"internalType": "address",
|
|
"name": "",
|
|
"type": "address"
|
|
}
|
|
],
|
|
"payable": false,
|
|
"stateMutability": "view",
|
|
"type": "function"
|
|
},
|
|
{
|
|
"constant": false,
|
|
"inputs": [
|
|
{
|
|
"internalType": "address",
|
|
"name": "to",
|
|
"type": "address"
|
|
}
|
|
],
|
|
"name": "delegate",
|
|
"outputs": [],
|
|
"payable": false,
|
|
"stateMutability": "nonpayable",
|
|
"type": "function"
|
|
},
|
|
{
|
|
"constant": false,
|
|
"inputs": [
|
|
{
|
|
"internalType": "address",
|
|
"name": "voter",
|
|
"type": "address"
|
|
}
|
|
],
|
|
"name": "giveRightToVote",
|
|
"outputs": [],
|
|
"payable": false,
|
|
"stateMutability": "nonpayable",
|
|
"type": "function"
|
|
},
|
|
{
|
|
"constant": true,
|
|
"inputs": [
|
|
{
|
|
"internalType": "uint256",
|
|
"name": "",
|
|
"type": "uint256"
|
|
}
|
|
],
|
|
"name": "proposals",
|
|
"outputs": [
|
|
{
|
|
"internalType": "bytes32",
|
|
"name": "name",
|
|
"type": "bytes32"
|
|
},
|
|
{
|
|
"internalType": "uint256",
|
|
"name": "voteCount",
|
|
"type": "uint256"
|
|
}
|
|
],
|
|
"payable": false,
|
|
"stateMutability": "view",
|
|
"type": "function"
|
|
},
|
|
{
|
|
"constant": false,
|
|
"inputs": [
|
|
{
|
|
"internalType": "uint256",
|
|
"name": "proposal",
|
|
"type": "uint256"
|
|
}
|
|
],
|
|
"name": "vote",
|
|
"outputs": [],
|
|
"payable": false,
|
|
"stateMutability": "nonpayable",
|
|
"type": "function"
|
|
},
|
|
{
|
|
"constant": true,
|
|
"inputs": [
|
|
{
|
|
"internalType": "address",
|
|
"name": "",
|
|
"type": "address"
|
|
}
|
|
],
|
|
"name": "voters",
|
|
"outputs": [
|
|
{
|
|
"internalType": "uint256",
|
|
"name": "weight",
|
|
"type": "uint256"
|
|
},
|
|
{
|
|
"internalType": "bool",
|
|
"name": "voted",
|
|
"type": "bool"
|
|
},
|
|
{
|
|
"internalType": "address",
|
|
"name": "delegate",
|
|
"type": "address"
|
|
},
|
|
{
|
|
"internalType": "uint256",
|
|
"name": "vote",
|
|
"type": "uint256"
|
|
}
|
|
],
|
|
"payable": false,
|
|
"stateMutability": "view",
|
|
"type": "function"
|
|
},
|
|
{
|
|
"constant": true,
|
|
"inputs": [],
|
|
"name": "winnerName",
|
|
"outputs": [
|
|
{
|
|
"internalType": "bytes32",
|
|
"name": "winnerName_",
|
|
"type": "bytes32"
|
|
}
|
|
],
|
|
"payable": false,
|
|
"stateMutability": "view",
|
|
"type": "function"
|
|
},
|
|
{
|
|
"constant": true,
|
|
"inputs": [],
|
|
"name": "winningProposal",
|
|
"outputs": [
|
|
{
|
|
"internalType": "uint256",
|
|
"name": "winningProposal_",
|
|
"type": "uint256"
|
|
}
|
|
],
|
|
"payable": false,
|
|
"stateMutability": "view",
|
|
"type": "function"
|
|
}
|
|
]`
|
|
|
|
const configFile = `
|
|
{
|
|
"language": "Solidity",
|
|
"settings": {
|
|
"optimizer": {
|
|
"enabled": true,
|
|
"runs": 300
|
|
},
|
|
"outputSelection": {
|
|
"*": {
|
|
"": ["ast"],
|
|
"*": ["abi", "metadata", "devdoc", "userdoc", "storageLayout", "evm.legacyAssembly", "evm.bytecode", "evm.deployedBytecode", "evm.methodIdentifiers", "evm.gasEstimates", "evm.assembly"]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
`
|
|
|
|
const yulSample = `
|
|
object "Contract" {
|
|
code {
|
|
function power(base, exponent) -> result
|
|
{
|
|
result := 1
|
|
for { let i := 0 } lt(i, exponent) { i := add(i, 1) }
|
|
{
|
|
result := mul(result, base)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
` |