parent
3cdc02a88e
commit
3e4e35c913
@ -1,518 +0,0 @@ |
|||||||
'use strict' |
|
||||||
import { NightwatchBrowser } from 'nightwatch' |
|
||||||
import init from '../helpers/init' |
|
||||||
import examples from '../examples/editor-test-contracts' |
|
||||||
|
|
||||||
const autoCompleteLineElement = (name: string) => { |
|
||||||
return `//*[@class='editor-widget suggest-widget visible']//*[@class='contents' and contains(.,'${name}')]` |
|
||||||
} |
|
||||||
|
|
||||||
module.exports = { |
|
||||||
'@disabled': true, |
|
||||||
before: function (browser: NightwatchBrowser, done: VoidFunction) { |
|
||||||
init(browser, done, 'http://127.0.0.1:8080', false) |
|
||||||
}, |
|
||||||
'Should add test and base files #group2': function (browser: NightwatchBrowser) { |
|
||||||
browser.addFile(examples.testContract.name, examples.testContract) |
|
||||||
.addFile(examples.baseContract.name, examples.baseContract) |
|
||||||
.addFile(examples.import1Contract.name, examples.import1Contract) |
|
||||||
.addFile(examples.baseOfBaseContract.name, examples.baseOfBaseContract) |
|
||||||
.addFile(examples.secondimport.name, examples.secondimport) |
|
||||||
.addFile(examples.importbase.name, examples.importbase) |
|
||||||
.openFile(examples.testContract.name) |
|
||||||
}, |
|
||||||
'Should put cursor in the () of the function #group2': function (browser: NightwatchBrowser) { |
|
||||||
browser.scrollToLine(36) |
|
||||||
const path = "//*[@class='view-line' and contains(.,'myprivatefunction') and contains(.,'private')]//span//span[contains(.,'(')]" |
|
||||||
browser.waitForElementVisible('#editorView') |
|
||||||
.useXpath() |
|
||||||
.click(path).pause(1000) |
|
||||||
}, |
|
||||||
'Should complete variable declaration types in a function definition #group2': function (browser: NightwatchBrowser) { |
|
||||||
browser |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys('uint25') |
|
||||||
}) |
|
||||||
.waitForElementPresent(autoCompleteLineElement('uint256')) |
|
||||||
.click(autoCompleteLineElement('uint256')) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys(' abc') |
|
||||||
.sendKeys(this.Keys.ENTER) // we need to split lines for FF texts to pass because the screen is too narrow
|
|
||||||
.sendKeys(', testb') |
|
||||||
}) |
|
||||||
.waitForElementPresent(autoCompleteLineElement('"TestBookDefinition"')) |
|
||||||
.click(autoCompleteLineElement('"TestBookDefinition"')) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys(' memo') |
|
||||||
}) |
|
||||||
.waitForElementPresent(autoCompleteLineElement('memory')) |
|
||||||
.click(autoCompleteLineElement('memory')) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys(' btextbook') |
|
||||||
.sendKeys(this.Keys.ENTER) |
|
||||||
.sendKeys(', BaseB') |
|
||||||
}) |
|
||||||
.waitForElementPresent(autoCompleteLineElement('"BaseBook"')) |
|
||||||
.click(autoCompleteLineElement('"BaseBook"')) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys(' stor') |
|
||||||
}) |
|
||||||
.waitForElementPresent(autoCompleteLineElement('storage')) |
|
||||||
.click(autoCompleteLineElement('storage')) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys(' localbbook') |
|
||||||
}).pause(3000) |
|
||||||
}, |
|
||||||
'Should put cursor at the end of function #group2': function (browser: NightwatchBrowser) { |
|
||||||
|
|
||||||
const path = "//*[@class='view-line' and contains(.,'localbbook') and contains(.,'private')]//span//span[contains(.,'{')]" |
|
||||||
browser |
|
||||||
.useXpath() |
|
||||||
.click(path).pause(1000) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
// right arrow key
|
|
||||||
sendKeys(this.Keys.ARROW_RIGHT). |
|
||||||
sendKeys(this.Keys.ARROW_RIGHT) |
|
||||||
}) |
|
||||||
}, |
|
||||||
'Should autcomplete address types': function (browser: NightwatchBrowser) { |
|
||||||
browser |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys('addre') |
|
||||||
}) |
|
||||||
.waitForElementPresent(autoCompleteLineElement('address')) |
|
||||||
.click(autoCompleteLineElement('address')) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys(' someaddress;') |
|
||||||
.sendKeys(this.Keys.ENTER) |
|
||||||
}).pause(2000) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys('someaddress.') |
|
||||||
}) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('balance')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('send')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('transfer')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('code')) |
|
||||||
.click(autoCompleteLineElement('balance')) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions |
|
||||||
.sendKeys(this.Keys.ENTER) |
|
||||||
}) |
|
||||||
}, |
|
||||||
'Should autcomplete array types': function (browser: NightwatchBrowser) { |
|
||||||
browser |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys('uin') |
|
||||||
}) |
|
||||||
.waitForElementPresent(autoCompleteLineElement('uint')) |
|
||||||
.click(autoCompleteLineElement('uint')) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys('[] mem') |
|
||||||
}) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('memory')) |
|
||||||
.click(autoCompleteLineElement('memory')) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys(' somearray;') |
|
||||||
} |
|
||||||
).pause(2000) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions |
|
||||||
.sendKeys(this.Keys.ENTER) |
|
||||||
.sendKeys('somearray.') |
|
||||||
}) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('push')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('pop')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('length')) |
|
||||||
.click(autoCompleteLineElement('length')) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions |
|
||||||
.sendKeys(this.Keys.ENTER) |
|
||||||
}) |
|
||||||
}, |
|
||||||
'Should see and autocomplete second import because it was imported by the first import #group2': function (browser: NightwatchBrowser) { |
|
||||||
browser |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys('secondi') |
|
||||||
}) |
|
||||||
.waitForElementPresent(autoCompleteLineElement('secondimport')) |
|
||||||
.click(autoCompleteLineElement('secondimport')) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys(' sec;') |
|
||||||
.sendKeys(this.Keys.ENTER) |
|
||||||
}).pause(3000) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys('sec.') |
|
||||||
}) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('secondimportstring')) |
|
||||||
.click(autoCompleteLineElement('secondimportstring')) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys(';') |
|
||||||
.sendKeys(this.Keys.ENTER) |
|
||||||
}) |
|
||||||
|
|
||||||
}, |
|
||||||
'Should see and autocomplete imported local class #group2': function (browser: NightwatchBrowser) { |
|
||||||
browser |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys('import') |
|
||||||
}) |
|
||||||
.waitForElementPresent(autoCompleteLineElement('importedcontract')) |
|
||||||
.click(autoCompleteLineElement('importedcontract')) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys('.') |
|
||||||
}) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('externalimport')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('importbasestring')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('importedbook')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('importpublicstring')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('publicimport')) |
|
||||||
// no private
|
|
||||||
.waitForElementNotPresent(autoCompleteLineElement('importprivatestring')) |
|
||||||
.waitForElementNotPresent(autoCompleteLineElement('privateimport')) |
|
||||||
// no internal
|
|
||||||
.waitForElementNotPresent(autoCompleteLineElement('importinternalstring')) |
|
||||||
.waitForElementNotPresent(autoCompleteLineElement('internalimport')) |
|
||||||
.click(autoCompleteLineElement('importbasestring')) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys(';') |
|
||||||
.sendKeys(this.Keys.ENTER) |
|
||||||
}) |
|
||||||
|
|
||||||
}, |
|
||||||
'Should autocomplete derived and local event when not using this. #group2': function (browser: NightwatchBrowser) { |
|
||||||
browser.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys('emit base') |
|
||||||
}) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('BaseEvent')) |
|
||||||
.click(autoCompleteLineElement('BaseEvent')) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions |
|
||||||
.sendKeys('msg.sender') |
|
||||||
.sendKeys(this.Keys.TAB) |
|
||||||
.sendKeys(this.Keys.TAB) // somehow this is needed to get the cursor to the next parameter, only for selenium
|
|
||||||
.sendKeys('3232') |
|
||||||
.sendKeys(this.Keys.TAB) |
|
||||||
.sendKeys(this.Keys.ENTER) |
|
||||||
}) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys('emit MyEv') |
|
||||||
}) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('MyEvent')) |
|
||||||
.click(autoCompleteLineElement('MyEvent')) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions |
|
||||||
.sendKeys('3232') |
|
||||||
.sendKeys(this.Keys.TAB) |
|
||||||
.sendKeys(this.Keys.ENTER) |
|
||||||
}) |
|
||||||
}, |
|
||||||
|
|
||||||
'Should type and get msg options #group2': function (browser: NightwatchBrowser) { |
|
||||||
browser. |
|
||||||
perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys(this.Keys.ENTER). |
|
||||||
sendKeys('msg.') |
|
||||||
}) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('sender')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('data')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('value')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('gas')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('sig')) |
|
||||||
.click(autoCompleteLineElement('sender')) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys('.') |
|
||||||
}) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('balance')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('code')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('codehash')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('send')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('transfer')) |
|
||||||
.click(autoCompleteLineElement('balance')) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys(this.Keys.ENTER) |
|
||||||
}) |
|
||||||
}, |
|
||||||
'Should bo and get book #group2': function (browser: NightwatchBrowser) { |
|
||||||
browser. |
|
||||||
perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys(this.Keys.ENTER). |
|
||||||
sendKeys('bo') |
|
||||||
}) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('book')) |
|
||||||
.click(autoCompleteLineElement('book')) |
|
||||||
}, |
|
||||||
'Should autcomplete derived struct #group2': function (browser: NightwatchBrowser) { |
|
||||||
browser.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys('.') |
|
||||||
}) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('author')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('book_id')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('title')) |
|
||||||
.click(autoCompleteLineElement('title')) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys(';') |
|
||||||
.sendKeys(this.Keys.ENTER) |
|
||||||
}) |
|
||||||
}, |
|
||||||
'Should bo and get basebook #group2': function (browser: NightwatchBrowser) { |
|
||||||
browser. |
|
||||||
perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys(this.Keys.ENTER). |
|
||||||
sendKeys('base') |
|
||||||
}) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('basebook')) |
|
||||||
.click(autoCompleteLineElement('basebook')) |
|
||||||
}, |
|
||||||
'Should autcomplete derived struct from base class #group2': function (browser: NightwatchBrowser) { |
|
||||||
browser.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys('.') |
|
||||||
}) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('author')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('book_id')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('title')) |
|
||||||
.click(autoCompleteLineElement('title')) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys(';') |
|
||||||
.sendKeys(this.Keys.ENTER) |
|
||||||
}) |
|
||||||
}, |
|
||||||
'Should block scoped localbbook #group2': function (browser: NightwatchBrowser) { |
|
||||||
browser.pause(4000). |
|
||||||
perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys(this.Keys.ENTER). |
|
||||||
sendKeys('localb') |
|
||||||
}) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('localbbook')) |
|
||||||
.click(autoCompleteLineElement('localbbook')) |
|
||||||
}, |
|
||||||
'Should autcomplete derived struct from block localbbook #group2': function (browser: NightwatchBrowser) { |
|
||||||
browser.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys('.') |
|
||||||
}) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('author')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('book_id')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('title')) |
|
||||||
.click(autoCompleteLineElement('title')) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys(';') |
|
||||||
.sendKeys(this.Keys.ENTER) |
|
||||||
}) |
|
||||||
}, |
|
||||||
'Should block scoped btextbook #group2': function (browser: NightwatchBrowser) { |
|
||||||
browser. |
|
||||||
perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys(this.Keys.ENTER). |
|
||||||
sendKeys('btext') |
|
||||||
}) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('btextbook')) |
|
||||||
.click(autoCompleteLineElement('btextbook')) |
|
||||||
}, |
|
||||||
'Should autcomplete derived struct from block btextbook #group2': function (browser: NightwatchBrowser) { |
|
||||||
browser.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys('.') |
|
||||||
}) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('author')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('book_id')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('title')) |
|
||||||
.click(autoCompleteLineElement('title')) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys(';') |
|
||||||
.sendKeys(this.Keys.ENTER) |
|
||||||
}) |
|
||||||
}, |
|
||||||
'Should find private and internal local functions #group2': function (browser: NightwatchBrowser) { |
|
||||||
browser.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys('my') |
|
||||||
}) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('myprivatefunction')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('myinternalfunction')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('memory')) |
|
||||||
.click(autoCompleteLineElement('myinternalfunction')) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys(this.Keys.ENTER) |
|
||||||
}) |
|
||||||
}, |
|
||||||
'Should find internal functions and var from base and owner #group2': function (browser: NightwatchBrowser) { |
|
||||||
browser.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys('intern') |
|
||||||
}) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('internalbasefunction')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('internalstring')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('internalbasestring')) |
|
||||||
// keyword internal
|
|
||||||
.waitForElementVisible(autoCompleteLineElement('internal keyword')) |
|
||||||
.click(autoCompleteLineElement('internalbasefunction')) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions |
|
||||||
.sendKeys(this.Keys.ENTER) |
|
||||||
}) |
|
||||||
}, |
|
||||||
|
|
||||||
'Should not find external functions without this. #group2': function (browser: NightwatchBrowser) { |
|
||||||
browser.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys('extern') |
|
||||||
}) |
|
||||||
.waitForElementNotPresent(autoCompleteLineElement('externalbasefunction')) |
|
||||||
.waitForElementNotPresent(autoCompleteLineElement('myexternalfunction')) |
|
||||||
// keyword internal
|
|
||||||
.waitForElementVisible(autoCompleteLineElement('external keyword')) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions |
|
||||||
.sendKeys(this.Keys.BACK_SPACE) |
|
||||||
.sendKeys(this.Keys.BACK_SPACE) |
|
||||||
.sendKeys(this.Keys.BACK_SPACE) |
|
||||||
.sendKeys(this.Keys.BACK_SPACE) |
|
||||||
.sendKeys(this.Keys.BACK_SPACE) |
|
||||||
.sendKeys(this.Keys.BACK_SPACE) |
|
||||||
.sendKeys(this.Keys.BACK_SPACE) |
|
||||||
}) |
|
||||||
}, |
|
||||||
'Should find external functions using this. #group2': function (browser: NightwatchBrowser) { |
|
||||||
browser. |
|
||||||
perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys(this.Keys.ENTER). |
|
||||||
sendKeys('this.') |
|
||||||
}) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('externalbasefunction')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('myexternalfunction')) |
|
||||||
}, |
|
||||||
'Should find public functions and vars using this. but not private & other types of nodes #group2': function (browser: NightwatchBrowser) { |
|
||||||
browser |
|
||||||
.waitForElementVisible(autoCompleteLineElement('"publicbasefunction"')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('"publicstring"')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('"basebook"')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('"mybook"')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('"testing"')) |
|
||||||
// but no private functions or vars or other types of nodes
|
|
||||||
.waitForElementNotPresent(autoCompleteLineElement('"private"')) |
|
||||||
.waitForElementNotPresent(autoCompleteLineElement('"BaseEvent"')) |
|
||||||
.waitForElementNotPresent(autoCompleteLineElement('"BaseEnum"')) |
|
||||||
.waitForElementNotPresent(autoCompleteLineElement('"TestBookDefinition"')) |
|
||||||
.click(autoCompleteLineElement('"publicbasefunction"')) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions |
|
||||||
.sendKeys(this.Keys.ENTER) |
|
||||||
}) |
|
||||||
}, |
|
||||||
'Should autocomplete local and derived ENUMS #group2': function (browser: NightwatchBrowser) { |
|
||||||
browser.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys('BaseEnum.') |
|
||||||
}) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('SMALL')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('MEDIUM')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('LARGE')) |
|
||||||
.click(autoCompleteLineElement('SMALL')) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys(';') |
|
||||||
.sendKeys(this.Keys.ENTER) |
|
||||||
.sendKeys('MyEnum.') |
|
||||||
}) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('SMALL')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('MEDIUM')) |
|
||||||
.waitForElementVisible(autoCompleteLineElement('LARGE')) |
|
||||||
.click(autoCompleteLineElement('SMALL')) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
sendKeys(';') |
|
||||||
.sendKeys(this.Keys.ENTER) |
|
||||||
}) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
@ -1,236 +0,0 @@ |
|||||||
'use strict' |
|
||||||
import { NightwatchBrowser } from 'nightwatch' |
|
||||||
import init from '../helpers/init' |
|
||||||
|
|
||||||
const checkEditorHoverContent = (browser: NightwatchBrowser, path: string, expectedContent: string, offsetLeft: number = 0) => { |
|
||||||
browser.useXpath() |
|
||||||
.useXpath() |
|
||||||
.moveToElement('//body', 0, 0) // always move away from the hover before the next test in case we hover in the same line on a different element
|
|
||||||
.waitForElementVisible(path) |
|
||||||
.moveToElement(path, offsetLeft, 0) |
|
||||||
.useCss() |
|
||||||
.waitForElementContainsText('.monaco-hover-content', expectedContent).pause(1000) |
|
||||||
} |
|
||||||
|
|
||||||
module.exports = { |
|
||||||
'@disabled': true, |
|
||||||
before: function (browser: NightwatchBrowser, done: VoidFunction) { |
|
||||||
init(browser, done, 'http://127.0.0.1:8080', false) |
|
||||||
}, |
|
||||||
|
|
||||||
'Should load the test file': function (browser: NightwatchBrowser) { |
|
||||||
browser.openFile('contracts') |
|
||||||
.openFile('contracts/3_Ballot.sol') |
|
||||||
.waitForElementVisible('#editorView') |
|
||||||
.setEditorValue(BallotWithARefToOwner) |
|
||||||
.pause(4000) // wait for the compiler to finish
|
|
||||||
.scrollToLine(37) |
|
||||||
}, |
|
||||||
'Should show hover over contract in editor #group1': function (browser: NightwatchBrowser) { |
|
||||||
const path = "//*[contains(text(),'BallotHoverTest')]" |
|
||||||
checkEditorHoverContent(browser, path, 'contract BallotHoverTest is BallotHoverTest') |
|
||||||
checkEditorHoverContent(browser, path, 'contracts/3_Ballot.sol 10:0') |
|
||||||
checkEditorHoverContent(browser, path, '@title Ballot') |
|
||||||
}, |
|
||||||
'Should show hover over var definition in editor #group1': function (browser: NightwatchBrowser) { |
|
||||||
const path = "//*[@class='view-line' and contains(.,'chairperson') and contains(.,'address') and contains(.,'public')]//span//span[contains(.,'chairperson')]" |
|
||||||
const expectedContent = 'address public chairperson' |
|
||||||
checkEditorHoverContent(browser, path, expectedContent) |
|
||||||
}, |
|
||||||
'Should show hover over constructor in editor #group1': function (browser: NightwatchBrowser) { |
|
||||||
const path: string = "//*[@class='view-line' and contains(.,'constructor') and contains(.,'bytes32') and contains(.,'memory')]//span//span[contains(.,'constructor')]" |
|
||||||
const expectedContent = 'Estimated creation cost: infinite gas Estimated code deposit cost:' |
|
||||||
checkEditorHoverContent(browser, path, expectedContent) |
|
||||||
}, |
|
||||||
'Should show hover over function in editor #group1': function (browser: NightwatchBrowser) { |
|
||||||
browser.scrollToLine(58) |
|
||||||
const path: string = "//*[@class='view-line' and contains(.,'giveRightToVote(address') and contains(.,'function') and contains(.,'public')]//span//span[contains(.,'giveRightToVote')]" |
|
||||||
let expectedContent = 'Estimated execution cost' |
|
||||||
checkEditorHoverContent(browser, path, expectedContent) |
|
||||||
expectedContent = 'function giveRightToVote (address internal voter) public nonpayable returns ()' |
|
||||||
checkEditorHoverContent(browser, path, expectedContent) |
|
||||||
expectedContent = "@dev Give 'voter' the right to vote on this ballot. May only be called by 'chairperson'" |
|
||||||
checkEditorHoverContent(browser, path, expectedContent) |
|
||||||
}, |
|
||||||
'Should show hover over var components in editor #group1': function (browser: NightwatchBrowser) { |
|
||||||
browser.scrollToLine(37) |
|
||||||
let path = "//*[@class='view-line' and contains(.,'voters') and contains(.,'weight')]//span//span[contains(.,'voters')]" |
|
||||||
let expectedContent = 'mapping(address => struct BallotHoverTest.Voter) public voters' |
|
||||||
checkEditorHoverContent(browser, path, expectedContent, 15) |
|
||||||
path = "//*[@class='view-line' and contains(.,'voters') and contains(.,'weight')]//span//span[contains(.,'chairperson')]" |
|
||||||
expectedContent = 'address public chairperson' |
|
||||||
checkEditorHoverContent(browser, path, expectedContent, 3) |
|
||||||
path = "//*[@class='view-line' and contains(.,'voters') and contains(.,'weight')]//span//span[contains(.,'weight')]" |
|
||||||
expectedContent = 'uint256 internal weight' |
|
||||||
checkEditorHoverContent(browser, path, expectedContent) |
|
||||||
}, |
|
||||||
'Should show hover over new contract creation in editor #group1': function (browser: NightwatchBrowser) { |
|
||||||
let path = "//*[@class='view-line' and contains(.,'Owner') and contains(.,'new')]//span//span[contains(.,'cowner')]" |
|
||||||
let expectedContent = 'contract Owner internal cowner' |
|
||||||
checkEditorHoverContent(browser, path, expectedContent, 10) |
|
||||||
path = "//*[@class='view-line' and contains(.,'Owner') and contains(.,'new')]//span//span[contains(.,'Owner')]" |
|
||||||
expectedContent = 'contract Owner is Owner' |
|
||||||
checkEditorHoverContent(browser, path, expectedContent, 10) |
|
||||||
}, |
|
||||||
'Should show hover over external class member in editor #group1': function (browser: NightwatchBrowser) { |
|
||||||
const path = "//*[@class='view-line' and contains(.,'getOwner') and contains(.,'cowner')]//span//span[contains(.,'getOwner')]" |
|
||||||
let expectedContent = 'function getOwner () external view returns (address internal )' |
|
||||||
checkEditorHoverContent(browser, path, expectedContent, 0) |
|
||||||
expectedContent = 'contracts/2_Owner.sol' |
|
||||||
checkEditorHoverContent(browser, path, expectedContent, 0) |
|
||||||
expectedContent = '@dev Return owner address' |
|
||||||
checkEditorHoverContent(browser, path, expectedContent, 0) |
|
||||||
}, |
|
||||||
'Should show hover over struct definition in editor #group1': function (browser: NightwatchBrowser) { |
|
||||||
browser.scrollToLine(5) |
|
||||||
const path = "//*[@class='view-line' and contains(.,'Voter') and contains(.,'struct')]//span//span[contains(.,'Voter')]" |
|
||||||
const expectedContent = 'StructDefinition' |
|
||||||
checkEditorHoverContent(browser, path, expectedContent) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
const BallotWithARefToOwner = `// SPDX-License-Identifier: GPL-3.0
|
|
||||||
|
|
||||||
pragma solidity >=0.7.0 <0.9.0; |
|
||||||
|
|
||||||
import "./2_Owner.sol"; |
|
||||||
|
|
||||||
/** |
|
||||||
* @title Ballot |
|
||||||
* @dev Implements voting process along with vote delegation |
|
||||||
*/ |
|
||||||
contract BallotHoverTest { |
|
||||||
Owner cowner; |
|
||||||
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) { |
|
||||||
cowner = new Owner(); |
|
||||||
cowner.getOwner(); |
|
||||||
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; |
|
||||||
} |
|
||||||
} |
|
||||||
` |
|
@ -1,196 +0,0 @@ |
|||||||
'use strict' |
|
||||||
import { NightwatchBrowser } from 'nightwatch' |
|
||||||
import init from '../helpers/init' |
|
||||||
|
|
||||||
const openReferences = (browser: NightwatchBrowser, path: string) => { |
|
||||||
(browser as any).useXpath() |
|
||||||
.useXpath() |
|
||||||
.waitForElementVisible(path) |
|
||||||
.click(path) |
|
||||||
.perform(function () { |
|
||||||
const actions = this.actions({ async: true }); |
|
||||||
return actions. |
|
||||||
keyDown(this.Keys.SHIFT). |
|
||||||
sendKeys(this.Keys.F12) |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
module.exports = { |
|
||||||
before: function (browser: NightwatchBrowser, done: VoidFunction) { |
|
||||||
init(browser, done, 'http://127.0.0.1:8080', false) |
|
||||||
}, |
|
||||||
|
|
||||||
'Should load the test file': function (browser: NightwatchBrowser) { |
|
||||||
browser.openFile('contracts') |
|
||||||
.openFile('contracts/3_Ballot.sol') |
|
||||||
.waitForElementVisible('#editorView') |
|
||||||
.setEditorValue(BallotWithARefToOwner) |
|
||||||
.pause(10000) // wait for the compiler to finish
|
|
||||||
.scrollToLine(37) |
|
||||||
}, |
|
||||||
'Should show local references': function (browser: NightwatchBrowser) { |
|
||||||
browser.scrollToLine(48) |
|
||||||
const path = "//*[@class='view-line' and contains(.,'length') and contains(.,'proposalNames')]//span//span[contains(.,'proposalNames')]" |
|
||||||
openReferences(browser, path) |
|
||||||
browser.waitForElementVisible("//*[@class='monaco-highlighted-label referenceMatch']//span[contains(.,'length; i++')]") |
|
||||||
.waitForElementVisible("//*[@class='monaco-highlighted-label referenceMatch']//span[contains(.,'name:')]") |
|
||||||
.waitForElementVisible("//*[@class='monaco-highlighted-label referenceMatch']//span[contains(.,'constructor')]") |
|
||||||
.keys(browser.Keys.ESCAPE) |
|
||||||
}, |
|
||||||
'Should show references of getOwner': function (browser: NightwatchBrowser) { |
|
||||||
browser.scrollToLine(39) |
|
||||||
const path = "//*[@class='view-line' and contains(.,'getOwner') and contains(.,'cowner')]//span//span[contains(.,'getOwner')]" |
|
||||||
openReferences(browser, path) |
|
||||||
browser.useXpath() |
|
||||||
.waitForElementVisible("//*[@class='monaco-highlighted-label']//span[contains(.,'2_Owner.sol')]") |
|
||||||
.waitForElementVisible("//*[@class='monaco-highlighted-label']//span[contains(.,'3_Ballot.sol')]") |
|
||||||
.waitForElementVisible("//*[@class='monaco-highlighted-label referenceMatch']//span[contains(.,'cowner.getOwner')]") |
|
||||||
.waitForElementVisible("//*[contains(@class, 'results-loaded') and contains(., 'References (2)')]") |
|
||||||
.keys(browser.Keys.ESCAPE) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
const BallotWithARefToOwner = `// SPDX-License-Identifier: GPL-3.0
|
|
||||||
|
|
||||||
pragma solidity >=0.7.0 <0.9.0; |
|
||||||
|
|
||||||
import "./2_Owner.sol"; |
|
||||||
|
|
||||||
/** |
|
||||||
* @title Ballot |
|
||||||
* @dev Implements voting process along with vote delegation |
|
||||||
*/ |
|
||||||
contract BallotHoverTest { |
|
||||||
Owner cowner; |
|
||||||
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) { |
|
||||||
cowner = new Owner(); |
|
||||||
cowner.getOwner(); |
|
||||||
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; |
|
||||||
} |
|
||||||
} |
|
||||||
` |
|
Loading…
Reference in new issue