diff --git a/old-ui/app/components/buy-button-subview.js b/old-ui/app/components/buy-button-subview.js index ae9e08a61..edcd7c460 100644 --- a/old-ui/app/components/buy-button-subview.js +++ b/old-ui/app/components/buy-button-subview.js @@ -170,7 +170,9 @@ class BuyButtonSubview extends Component { backButtonContext () { if (this.props.context === 'confTx') { - this.props.dispatch(actions.showConfTxPage(false)) + this.props.dispatch(actions.showConfTxPage({ + isContractExecutionByUser: this.props.isContractExecutionByUser, + })) } else { this.props.dispatch(actions.goHome()) } @@ -192,6 +194,7 @@ BuyButtonSubview.propTypes = { buyView: PropTypes.object, context: PropTypes.string, provider: PropTypes.object, + isContractExecutionByUser: PropTypes.bool, } function mapStateToProps (state) { @@ -205,6 +208,7 @@ function mapStateToProps (state) { provider: state.metamask.provider, context: state.appState.currentView.context, isSubLoading: state.appState.isSubLoading, + isContractExecutionByUser: state.appState.buyView.isContractExecutionByUser, } } diff --git a/old-ui/app/components/send/choose-contract-executor.js b/old-ui/app/components/send/choose-contract-executor.js index fd52db460..9725d492d 100644 --- a/old-ui/app/components/send/choose-contract-executor.js +++ b/old-ui/app/components/send/choose-contract-executor.js @@ -120,6 +120,7 @@ class ChooseContractExecutor extends Component { const { selectedExecutor } = this.state this.props.setSelectedAddress(selectedExecutor) txParams.from = selectedExecutor + txParams.isContractExecutionByUser = true this.props.signTx(txParams) } diff --git a/old-ui/app/conf-tx.js b/old-ui/app/conf-tx.js index 9afcdd87d..067e52055 100644 --- a/old-ui/app/conf-tx.js +++ b/old-ui/app/conf-tx.js @@ -6,6 +6,7 @@ const actions = require('../../ui/app/actions') const LoadingIndicator = require('./components/loading') const txHelper = require('../lib/tx-helper') const log = require('loglevel') +const { getCurrentKeyring, ifContractAcc } = require('./util') const PendingTx = require('./components/pending-tx') import PendingMsg from './components/pending-msg' @@ -22,6 +23,7 @@ function mapStateToProps (state) { return { identities: metamask.identities, accounts: getMetaMaskAccounts(state), + keyrings: metamask.keyrings, selectedAddress: metamask.selectedAddress, unapprovedTxs: metamask.unapprovedTxs, unapprovedMsgs: metamask.unapprovedMsgs, @@ -39,6 +41,7 @@ function mapStateToProps (state) { tokenSymbol: (screenParams && screenParams.tokenSymbol), tokensToSend: (screenParams && screenParams.tokensToSend), tokensTransferTo: (screenParams && screenParams.tokensTransferTo), + isContractExecutionByUser: (screenParams && screenParams.isContractExecutionByUser), } } @@ -110,7 +113,7 @@ ConfirmTxScreen.prototype.render = function () { tokensToSend: props.tokensToSend, tokensTransferTo: props.tokensTransferTo, // Actions - buyEth: this.buyEth.bind(this, txParams.from || props.selectedAddress), + buyEth: this.buyEth.bind(this, txParams.from || props.selectedAddress, props.isContractExecutionByUser), sendTransaction: this.sendTransaction.bind(this), cancelTransaction: this.cancelTransaction.bind(this, txData), cancelAllTransactions: this.cancelAllTransactions.bind(this, unconfTxList), @@ -149,26 +152,29 @@ function currentTxView (opts) { } } -ConfirmTxScreen.prototype.buyEth = function (address, event) { +ConfirmTxScreen.prototype.buyEth = function (address, isContractExecutionByUser, event) { event.preventDefault() - this.props.dispatch(actions.buyEthView(address)) + this.props.dispatch(actions.buyEthView(address, isContractExecutionByUser)) } ConfirmTxScreen.prototype.sendTransaction = function (txData, event) { this.stopPropagation(event) this.props.dispatch(actions.updateAndApproveTx(txData)) + this._checkIfContractExecutionAndUnlockContract(txData) } ConfirmTxScreen.prototype.cancelTransaction = function (txData, event) { this.stopPropagation(event) event.preventDefault() this.props.dispatch(actions.cancelTx(txData)) + this._checkIfContractExecutionAndUnlockContract(txData) } ConfirmTxScreen.prototype.cancelAllTransactions = function (unconfTxList, event) { this.stopPropagation(event) event.preventDefault() this.props.dispatch(actions.cancelAllTx(unconfTxList)) + this._checkIfMultipleContractExecutionAndUnlockContract(unconfTxList) } ConfirmTxScreen.prototype.signMessage = function (msgData, event) { @@ -219,6 +225,46 @@ ConfirmTxScreen.prototype.cancelTypedMessage = function (msgData, event) { this.props.dispatch(actions.cancelTypedMsg(msgData)) } +ConfirmTxScreen.prototype._checkIfMultipleContractExecutionAndUnlockContract = function (unconfTxList) { + const areTxsToOneContractFromTheList = unconfTxList.slice(0).reduce((res, txData, ind, unconfTxList) => { + if (txData.txParams.data && this.props.isContractExecutionByUser) { + const to = txData && txData.txParams && txData.txParams.to + const targetContractIsInTheList = Object.keys(this.props.accounts).some((acc) => acc === to) + if (targetContractIsInTheList && Object.keys(res).length === 0) { + res = { status: true, to } + } else if (res.status && res.to !== to) { + res = { status: false } + unconfTxList.splice(1) + } + } else { + res = { status: false } + unconfTxList.splice(1) + } + return res + }, {}) + + if (areTxsToOneContractFromTheList.status) { + this._unlockContract(areTxsToOneContractFromTheList.to) + } +} + +ConfirmTxScreen.prototype._checkIfContractExecutionAndUnlockContract = function (txData) { + if (txData.txParams.data && this.props.isContractExecutionByUser) { + const to = txData && txData.txParams && txData.txParams.to + const targetContractIsInTheList = Object.keys(this.props.accounts).some((acc) => acc === to) + if (targetContractIsInTheList) { + this._unlockContract(to) + } + } +} + +ConfirmTxScreen.prototype._unlockContract = function (to) { + const currentKeyring = getCurrentKeyring(to, this.props.network, this.props.keyrings, this.props.identities) + if (ifContractAcc(currentKeyring)) { + this.props.dispatch(actions.showAccountDetail(to)) + } +} + function warningIfExists (warning) { if (warning && // Do not display user rejections on this screen: diff --git a/package-lock.json b/package-lock.json index 9d44d0328..9e2fcf227 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10527,7 +10527,6 @@ "resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-1.4.2.tgz", "integrity": "sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA=", "requires": { - "ethereumjs-abi": "git+https://github.com/ethereumjs/ethereumjs-abi.git#2863c40e0982acfc0b7163f0285d4c56427c7799", "ethereumjs-util": "^5.1.1" } }, @@ -10949,7 +10948,6 @@ "resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-1.4.2.tgz", "integrity": "sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA=", "requires": { - "ethereumjs-abi": "git+https://github.com/ethereumjs/ethereumjs-abi.git#2863c40e0982acfc0b7163f0285d4c56427c7799", "ethereumjs-util": "^5.1.1" } }, diff --git a/test/e2e/elements.js b/test/e2e/elements.js index 0b359e8fe..30a537169 100644 --- a/test/e2e/elements.js +++ b/test/e2e/elements.js @@ -2,6 +2,7 @@ const webdriver = require('selenium-webdriver') const { By } = webdriver module.exports = { elements: { + buttonArrow: By.className('fa fa-arrow-left fa-lg cursor-pointer'), errorClose: By.css('.send-screen > div:nth-child(3) > div:nth-child(1)'), error: By.className('error'), loader: By.css('#app-content > div > div.full-flex-height > img'), @@ -32,12 +33,15 @@ module.exports = { item: By.className('dropdown-menu-item'), account1: By.css('#app-content > div > div.full-width > div.full-width > div > div:nth-child(2) > span > div > div > span > div > li:nth-child(2) > span'), account2: By.css('#app-content > div > div.full-width > div.full-width > div > div:nth-child(2) > span > div > div > span > div > li:nth-child(3) > span'), + account3: By.css('#app-content > div > div.full-width > div.full-width > div > div:nth-child(2) > span > div > div > span > div > li:nth-child(4) > span'), + account4: By.css('#app-content > div > div.full-width > div.full-width > div > div:nth-child(2) > span > div > div > span > div > li:nth-child(5) > span'), menu: By.css('#app-content > div > div.full-width > div.full-width > div > div:nth-child(2) > span > div'), - delete: By.css('#app-content > div > div.full-width > div.full-width > div > div:nth-child(2) > span > div > div > span > div > li:nth-child(4) > div.remove'), + delete: By.className('remove'), createAccount: By.css('#app-content > div > div.full-width > div.full-width > div > div:nth-child(2) > span > div > div > span > div > li:nth-child(3) > span'), // import: By.css('#app-content > div > div.full-width > div.full-width > div > div:nth-child(2) > span > div > div > span > div > li:nth-child(5) > span'), import: By.css('li.dropdown-menu-item:nth-child(5) > span:nth-child(1)'), - labelImported: By.css('#app-content > div > div.full-width > div.full-width > div > div:nth-child(2) > span > div > div > span > div > li:nth-child(4) > div.keyring-label'), + import2: By.css('#app-content > div > div.full-width > div.full-width > div > div:nth-child(2) > span > div > div > span > div > li:nth-child(6)'), + label: By.className('keyring-label'), }, dot: { menu: By.className('account-dropdown'), @@ -85,7 +89,7 @@ module.exports = { buttonNext: By.css('.section > div:nth-child(1) > button:nth-child(2)'), buttonArrow: By.className('fa fa-arrow-left fa-lg cursor-pointer'), buttonCopyABI: By.className('btn-violet'), - buttonExecuteMethod: By.css('#app-content > div > div.app-primary.from-right > div > div > div.flex-row > button'), + buttonExecuteMethod: By.xpath('//*[@id="app-content"]/div/div[2]/div/div/div[2]/button'), }, eventsEmitter: { button: By.className('btn btn-default'), @@ -207,6 +211,8 @@ module.exports = { button: { submit: By.css('#pending-tx-form > div.flex-row.flex-space-around.conf-buttons > input'), reject: By.css('.cancel'), + rejectAll: By.css('#pending-tx-form > div:nth-child(4) > button'), + buyEther: By.css('#pending-tx-form > div.flex-row.flex-space-around.conf-buttons > button.btn-green'), }, fields: { gasLimit: By.css('#pending-tx-form > div:nth-child(1) > div.table-box > div:nth-child(3) > div.cell.value > div > div > input'), @@ -245,7 +251,7 @@ module.exports = { error: By.css('span.error'), selectArrow: By.className('Select-arrow-zone'), selectType: By.name('import-type-select'), - itemContract: By.id('react-select-2--option-2'), + itemContract: By.id('react-select-3--option-2'), contractAddress: By.id('address-box'), contractABI: By.id('abi-box'), title: By.css('#app-content > div > div.app-primary.from-right > div > div:nth-child(2) > div.flex-row.flex-center > h2'), @@ -277,6 +283,7 @@ module.exports = { }, }, main: { + accountAddress: By.xpath('//*[@id="app-content"]/div/div[2]/div/div/div[1]/flex-column/div[2]/div/span'), identicon: By.className('identicon-wrapper select-none'), fieldAccountName: By.className('sizing-input'), accountName: By.className('font-medium color-forest'), @@ -310,6 +317,9 @@ module.exports = { counterFF: By.css('div.full-flex-height:nth-child(2) > div:nth-child(1) > span:nth-child(1)'), }, }, + buyEther: { + title: By.className('flex-center buy-title'), + }, info: { title: By.className('section-title flex-row flex-center'), titleText: 'Info', diff --git a/test/e2e/metamask.spec.js b/test/e2e/metamask.spec.js index bfd8195fb..f19aecdfe 100644 --- a/test/e2e/metamask.spec.js +++ b/test/e2e/metamask.spec.js @@ -12,10 +12,11 @@ const { menus, screens, elements, NETWORKS } = require('./elements') const testSeedPhrase = 'horn among position unable audit puzzle cannon apology gun autumn plug parrot' const account1 = '0x2E428ABd9313D256d64D1f69fe3929C3BE18fD1f' const account2 = '0xd7b7AFeCa35e32594e29504771aC847E2a803742' +const createdAccounts = [] const eventsEmitter = 'https://vbaranov.github.io/event-listener-dapp/' describe('Metamask popup page', async function () { - let driver, accountAddress, tokenAddress, extensionId + let driver, tokenAddress, extensionId let password = '123456789' let abiClipboard const newPassword = { @@ -76,8 +77,7 @@ describe('Metamask popup page', async function () { }) }) - describe('Account Creation', async () => { - const newAccountName = 'new name' + describe('Log In', async () => { it('title is \'Nifty Wallet\'', async () => { const title = await driver.getTitle() @@ -130,6 +130,9 @@ describe('Metamask popup page', async function () { assert.equal(await continueAfterSeedPhrase.getText(), screens.seedPhrase.textButtonIveCopied) await click(continueAfterSeedPhrase) }) + }) + describe('Account Creation', async () => { + const newAccountName = 'new name' it('sets provider type to localhost', async function () { await setProvider(NETWORKS.LOCALHOST) @@ -142,6 +145,12 @@ describe('Metamask popup page', async function () { assert.notEqual(field, false, 'copy icon doesn\'t present') }) + it("Account's address is displayed and has length 20 symbols", async () => { + const field = await waitUntilShowUp(screens.main.address) + createdAccounts.push((await field.getText()).toUpperCase()) + console.log(createdAccounts[0]) + assert.notEqual(createdAccounts[0].length, 20, "address isn't displayed") + }) it('Check clipboard buffer', async function () { const text = clipboardy.readSync() assert.equal(text.length, 42, "address account wasn't copied to clipboard") @@ -187,10 +196,11 @@ describe('Metamask popup page', async function () { await item.click() }) - it('shows account address', async function () { - await delay(300) - const account = await waitUntilShowUp(screens.main.address) - accountAddress = await account.getText() + it("Account's address is displayed and has length 20 symbols", async () => { + const field = await waitUntilShowUp(screens.main.address) + createdAccounts.push((await field.getText()).toUpperCase()) + console.log(createdAccounts[1]) + assert.notEqual(createdAccounts[1].length, 20, "address isn't displayed") }) it('logs out of the vault', async () => { @@ -220,7 +230,7 @@ describe('Metamask popup page', async function () { it('checks QR code address is the same as account details address', async () => { const field = await waitUntilShowUp(screens.QRcode.address) const text = await field.getText() - assert.equal(text.toLowerCase(), accountAddress.toLowerCase(), 'QR addres doesn\'t match') + assert.equal(text.toUpperCase(), createdAccounts[1], 'QR address doesn\'t match') }) it('copy icon is displayed and clickable', async () => { @@ -344,18 +354,74 @@ describe('Metamask popup page', async function () { const ident = await waitUntilShowUp(screens.main.identicon, 20) assert.notEqual(ident, false, "main screen isn't opened") }) + describe('Import Account', () => { + + it('Open import account menu', async function () { + await setProvider(NETWORKS.POA) + await delay(2000) + const menu = await waitUntilShowUp(menus.account.menu) + await menu.click() + const item = await waitUntilShowUp(menus.account.import) + await item.click() + const importAccountTitle = await waitUntilShowUp(screens.importAccounts.title) + assert.equal(await importAccountTitle.getText(), screens.importAccounts.textTitle) + }) + + it('Imports account', async function () { + const privateKeyBox = await waitUntilShowUp(screens.importAccounts.fieldPrivateKey) + await privateKeyBox.sendKeys('76bd0ced0a47055bb5d060e1ae4a8cb3ece658d668823e250dae6e79d3ab4435')// 0xf4702CbA917260b2D6731Aea6385215073e8551b + const button = await waitUntilShowUp(screens.importAccounts.buttonImport) + await click(button) + assert.equal(await button.getText(), 'Import', 'button has incorrect name') + const menu = await waitUntilShowUp(menus.account.menu) + await menu.click() + await waitUntilShowUp(menus.account.label) + const label = (await driver.findElements(menus.account.label))[0] + assert.equal(await label.getText(), 'IMPORTED') + await menu.click() + }) + + it('Auto-detect tokens for POA core network ', async function () { + // await setProvider(NETWORKS.POA) + const tab = await waitUntilShowUp(screens.main.tokens.menu) + await tab.click() + const balance = await waitUntilShowUp(screens.main.tokens.balance) + console.log(await balance.getText()) + assert.equal(await balance.getText(), '1 DOPR', 'token isnt\' auto-detected') + }) + + it.skip('Auto-detect tokens for MAIN core network ', async function () { + await setProvider(NETWORKS.MAINNET) + await waitUntilShowUp(elements.loader, 25) + await waitUntilDisappear(elements.loader, 25) + const balance = await waitUntilShowUp(screens.main.tokens.balance) + console.log(await balance.getText()) + assert.equal(await balance.getText(), '0.001 WETH', 'token isnt\' auto-detected') + }) + + it('Check Sokol balance', async function () { + await setProvider(NETWORKS.POA) + await delay(2000) + const balanceField = await waitUntilShowUp(screens.main.balance) + const balance = await balanceField.getText() + console.log('Account = 0xf4702CbA917260b2D6731Aea6385215073e8551b') + console.log('Balance = ' + balance) + assert.equal(parseFloat(balance) > 0.001, true, 'Balance of account 0xf4702CbA917260b2D6731Aea6385215073e8551b TOO LOW !!! Please refill with Sokol eth!!!!') + }) + }) describe('Import Contract account', async () => { const contractSokol = '0x215b2ab35749e5a9f3efe890de602fb9844e842f' console.log('Contract ' + contractSokol + ' , Sokol') const wrongAddress = '0xB87b6077D59B01Ab9fa8cd5A1A21D02a4d60D35' const notContractAddress = '0x56B2e3C3cFf7f3921Dc2e0F8B8e20d1eEc29216b' + describe('Import Contract', async () => { it('opens import account menu', async function () { await setProvider(NETWORKS.ROPSTEN) const menu = await waitUntilShowUp(menus.account.menu) await menu.click() - const item = await waitUntilShowUp(menus.account.import) + const item = await waitUntilShowUp(menus.account.import2) await item.click() const importAccountTitle = await waitUntilShowUp(screens.importAccounts.title) assert.equal(await importAccountTitle.getText(), screens.importAccounts.textTitle) @@ -375,7 +441,6 @@ describe('Metamask popup page', async function () { }) it("Field 'Address' is displayed", async function () { - await delay(2000) const field = await waitUntilShowUp(screens.importAccounts.contractAddress) assert.notEqual(field, false, "field 'Address' isn't displayed") await field.sendKeys(wrongAddress) @@ -936,21 +1001,21 @@ describe('Metamask popup page', async function () { }) describe('Choose Contract Executor', () => { - it('title is displayed and correct', async function () { + it('Title is displayed and correct', async function () { await delay(5000) const title = await waitUntilShowUp(screens.chooseContractExecutor.title) assert.notEqual(title, false, 'title isn\'t displayed') assert.equal(await title.getText(), screens.chooseContractExecutor.titleText, 'incorrect text') }) - it('two accounts displayed', async function () { + it('Two accounts displayed', async function () { const accs = await waitUntilShowUp(screens.chooseContractExecutor.account) assert.notEqual(accs, false, 'accounts aren\'t displayed') const accounts = await driver.findElements(screens.chooseContractExecutor.account) - assert.equal(accounts.length, 3, "number of accounts isn't 2") + assert.equal(accounts.length, 4, "number of accounts isn't 2") }) - it("Click arrow button leads to 'Execute Method' screen ", async function () { + it("Click arrow button leads to 'Execute Method' screen ", async function () { const button = await waitUntilShowUp(screens.chooseContractExecutor.buttonArrow) assert.notEqual(button, false, 'button isn\'t displayed') await button.click() @@ -989,26 +1054,90 @@ describe('Metamask popup page', async function () { assert.equal(selected.length, 1, 'more than one accounts are selected') }) + it("Click button 'Next' open 'Confirm transaction' screen", async function () { const button = await waitUntilShowUp(screens.chooseContractExecutor.buttonNext) await button.click() - await delay(5000) + await delay(3000) const reject = await waitUntilShowUp(screens.confirmTransaction.button.reject) assert.notEqual(reject, false, "button reject isn't displayed") - await click(reject) - const identicon = await waitUntilShowUp(screens.main.identicon) - assert.notEqual(identicon, false, 'main screen didn\'t opened') }) - it("Label 'CONTRACT' present", async function () { + + it("Button 'Buy Ether' is displayed", async function () { + const button = await waitUntilShowUp(screens.confirmTransaction.button.buyEther) + assert.equal(await button.getText(), 'Buy Ether', 'button has incorrect name') + assert.equal(await button.isEnabled(), true, 'button is disabled') + }) + + it("Open screen 'Buy Ether'", async function () { + const button = await waitUntilShowUp(screens.confirmTransaction.button.buyEther) + await button.click() + const title = await waitUntilShowUp(screens.buyEther.title) + assert.equal(await title.getText(), 'Buy POA', "screen 'Buy Ether' has incorrect title text") + const arrow = await waitUntilShowUp(elements.buttonArrow) + await arrow.click() + }) + + it("Click button 'Reject' open contract's account screen", async function () { + const reject = await waitUntilShowUp(screens.confirmTransaction.button.reject) + assert.equal(await reject.getText(), 'Reject', 'button has incorrect name') + await reject.click() + const buttonExecute = await waitUntilShowUp(screens.executeMethod.buttonExecuteMethod) + assert.notEqual(buttonExecute, false, "contract's account hasn't opened") + }) + + it("Button arrow leads to executor's account screen", async function () { + assert.equal(await executeTransferMethod(0), true, "can't execute the method 'transfer'") + await delay(2000) + const arrow = await waitUntilShowUp(elements.buttonArrow) + await arrow.click() + await delay(2000) + const address = await waitUntilShowUp(screens.main.address) + assert.equal((await address.getText()).toUpperCase(), createdAccounts[0], "executors account isn't opened") + }) + + it('Switch to contract account ', async function () { + const accountMenu = await waitUntilShowUp(menus.account.menu) + await accountMenu.click() + const item = await waitUntilShowUp(menus.account.account4) + await item.click() + await delay(2000) + const address = await waitUntilShowUp(screens.main.address) + assert.equal((await address.getText()).toUpperCase(), contractSokol.toUpperCase(), "contract's account isn't opened") + }) + + it("Confirm transaction: button 'Reject All' leads to contract's account screen", async function () { + assert.equal(await executeTransferMethod(0), true, "can't execute the method 'transfer'") + const rejectAll = await waitUntilShowUp(screens.confirmTransaction.button.rejectAll) + assert.equal(await rejectAll.getText(), 'Reject All', 'button has incorrect name') + await rejectAll.click() + await delay(2000) + const address = await waitUntilShowUp(screens.main.address) + assert.equal((await address.getText()).toUpperCase(), contractSokol.toUpperCase(), "contract account isn't opened") + }) + + it("Confirm transaction: button 'Submit' leads to contract's account screen", async function () { + assert.equal(await executeTransferMethod(2), true, "can't execute the method 'transfer'") + await delay(2000) + const button = await waitUntilShowUp(screens.confirmTransaction.button.submit) + // assert.equal(await button.getText(), 'Submit', "button has incorrect name") + await button.click() + await delay(2000) + const address = await waitUntilShowUp(screens.main.address) + assert.equal((await address.getText()).toUpperCase(), contractSokol.toUpperCase(), "contract account isn't opened") + }) + + it("Label 'CONTRACT' present", async function () { const menu = await waitUntilShowUp(menus.account.menu) await menu.click() - await waitUntilShowUp(menus.account.labelImported) - const label = (await driver.findElements(menus.account.labelImported))[0] + await waitUntilShowUp(menus.account.label) + const label = (await driver.findElements(menus.account.label))[1] assert.equal(await label.getText(), 'CONTRACT', 'label incorrect') }) it('Delete imported account', async function () { - const item = await waitUntilShowUp(menus.account.delete) - await item.click() + await waitUntilShowUp(menus.account.delete) + const items = await driver.findElements(menus.account.delete) + await items[1].click() const button = await waitUntilShowUp(screens.deleteImportedAccount.buttons.yes) await button.click() const buttonArrow = await waitUntilShowUp(screens.settings.buttons.arrow) @@ -1018,10 +1147,60 @@ describe('Metamask popup page', async function () { }) }) }) + describe('Delete Imported Account', () => { + + it('Open delete imported account screen', async function () { + const menu = await waitUntilShowUp(menus.account.menu) + await menu.click() + const item = await waitUntilShowUp(menus.account.delete) + await item.click() + const deleteImportedAccountTitle = await waitUntilShowUp(screens.deleteImportedAccount.title) + assert.equal(await deleteImportedAccountTitle.getText(), screens.deleteImportedAccount.titleText) + }) + + it("Can't remove imported account with 'No' button", async function () { + const button = await waitUntilShowUp(screens.deleteImportedAccount.buttons.no) + assert.equal(await button.getText(), 'No', 'button has incorrect name') + await click(button) + const settingsTitle = await waitUntilShowUp(screens.settings.title) + assert.equal(await settingsTitle.getText(), 'Settings') + // check, that imported account still exists + const menu = await waitUntilShowUp(menus.account.menu) + await menu.click() + await delay(2000) + const label = await waitUntilShowUp(menus.account.label) + assert.equal(await label.getText(), 'IMPORTED') + }) + + it('Open delete imported account screen again', async function () { + const menu = await waitUntilShowUp(menus.account.menu) + await menu.click() + await delay(2000) + await menu.click() + await waitUntilShowUp(menus.account.delete) + const buttons = await driver.findElements(menus.account.delete) + assert.notEqual(buttons[0], false, "icon 'remove' isn't displayed") + await buttons[0].click() + }) + + it("Remove imported account with 'Yes' button", async function () { + const button = await waitUntilShowUp(screens.deleteImportedAccount.buttons.yes) + assert.equal(await button.getText(), 'Yes', 'button has incorrect name') + await click(button) + const settingsTitle = await waitUntilShowUp(screens.settings.title) + assert.equal(await settingsTitle.getText(), 'Settings') + // check, that imported account is removed + const menu = await waitUntilShowUp(menus.account.menu) + await menu.click() + await waitUntilShowUp(menus.account.label, 25) + const labels = await driver.findElements(menus.account.label) + assert.ok(labels.length === 0) + await menu.click() + }) + }) describe('Sign Data', () => { - - it('simulate sign request ', async function () { + it('Simulate sign request ', async function () { await setProvider(NETWORKS.LOCALHOST) await driver.get('https://danfinlay.github.io/js-eth-personal-sign-examples/') await delay(5000) @@ -1048,7 +1227,7 @@ describe('Metamask popup page', async function () { it('account name is displayed and correct', async function () { const name = await waitUntilShowUp(screens.signMessage.accountName) assert.notEqual(name, false, 'account name isn\'t displayed') - assert.equal(await name.getText(), 'Account 2', 'account name is incorrect') + assert.equal(await name.getText(), 'new name', 'account name is incorrect') }) it('title is displayed and correct', async function () { @@ -1078,94 +1257,7 @@ describe('Metamask popup page', async function () { assert.notEqual(identicon, false, 'main screen didn\'t opened') }) }) - describe('Import Account', () => { - it('opens import account menu', async function () { - await setProvider(NETWORKS.POA) - await delay(2000) - const menu = await waitUntilShowUp(menus.account.menu) - await menu.click() - const item = await waitUntilShowUp(menus.account.import) - await item.click() - const importAccountTitle = await waitUntilShowUp(screens.importAccounts.title) - assert.equal(await importAccountTitle.getText(), screens.importAccounts.textTitle) - }) - - it('imports account', async function () { - const privateKeyBox = await waitUntilShowUp(screens.importAccounts.fieldPrivateKey) - await privateKeyBox.sendKeys('76bd0ced0a47055bb5d060e1ae4a8cb3ece658d668823e250dae6e79d3ab4435')// 0xf4702CbA917260b2D6731Aea6385215073e8551b - const button = await waitUntilShowUp(screens.importAccounts.buttonImport) - await click(button) - assert.equal(await button.getText(), 'Import', 'button has incorrect name') - const menu = await waitUntilShowUp(menus.account.menu) - await menu.click() - await waitUntilShowUp(menus.account.labelImported) - const label = (await driver.findElements(menus.account.labelImported))[0] - assert.equal(await label.getText(), 'IMPORTED') - await menu.click() - }) - - it('Auto-detect tokens for POA core network ', async function () { - // await setProvider(NETWORKS.POA) - const tab = await waitUntilShowUp(screens.main.tokens.menu) - await tab.click() - const balance = await waitUntilShowUp(screens.main.tokens.balance) - console.log(await balance.getText()) - assert.equal(await balance.getText(), '1 DOPR', 'token isnt\' auto-detected') - }) - - it.skip('Auto-detect tokens for MAIN core network ', async function () { - await setProvider(NETWORKS.MAINNET) - await waitUntilShowUp(elements.loader, 25) - await waitUntilDisappear(elements.loader, 25) - const balance = await waitUntilShowUp(screens.main.tokens.balance) - console.log(await balance.getText()) - assert.equal(await balance.getText(), '0.001 WETH', 'token isnt\' auto-detected') - }) - - it('opens delete imported account screen', async function () { - await setProvider(NETWORKS.LOCALHOST) - const menu = await waitUntilShowUp(menus.account.menu) - await menu.click() - const item = await waitUntilShowUp(menus.account.delete) - await item.click() - const deleteImportedAccountTitle = await waitUntilShowUp(screens.deleteImportedAccount.title) - assert.equal(await deleteImportedAccountTitle.getText(), screens.deleteImportedAccount.titleText) - }) - - it('doesn\'t remove imported account with \'No\' button', async function () { - const button = await waitUntilShowUp(screens.deleteImportedAccount.buttons.no) - assert.equal(await button.getText(), 'No', 'button has incorrect name') - await click(button) - const settingsTitle = await waitUntilShowUp(screens.settings.title) - assert.equal(await settingsTitle.getText(), 'Settings') - // check, that imported account still exists - const menu = await waitUntilShowUp(menus.account.menu) - await menu.click() - const importedLabel = await waitUntilShowUp(menus.account.labelImported) - assert.equal(await importedLabel.getText(), 'IMPORTED') - }) - - it('opens delete imported account screen again', async function () { - const menu = await waitUntilShowUp(menus.account.delete) - await menu.click() - }) - - it('removes imported account with \'Yes\' button', async function () { - const button = await waitUntilShowUp(screens.deleteImportedAccount.buttons.yes) - assert.equal(await button.getText(), 'Yes', 'button has incorrect name') - await click(button) - const settingsTitle = await waitUntilShowUp(screens.settings.title) - assert.equal(await settingsTitle.getText(), 'Settings') - // check, that imported account is removed - const menu = await waitUntilShowUp(menus.account.menu) - await menu.click() - await waitUntilShowUp(menus.account.labelImported, 25) - const importedAccounts = await driver.findElements(menus.account.labelImported) - assert.ok(importedAccounts.length === 0) - await menu.click() - }) - }) describe('Export private key', async () => { it('open dialog', async function () { @@ -3026,6 +3118,44 @@ describe('Metamask popup page', async function () { return contractInstance.address } + async function executeTransferMethod (executor) { + try { + const buttonExecute = await waitUntilShowUp(screens.executeMethod.buttonExecuteMethod) + assert.notEqual(buttonExecute, false, "button doesn't displayed") + await buttonExecute.click() + // Select method transfer + const menu = await waitUntilShowUp(screens.executeMethod.selectArrow) + await menu.click() + await waitUntilShowUp(screens.executeMethod.items) + const list = await driver.findElements(screens.executeMethod.items) + await list[21].click() + // Fill out value + await waitUntilShowUp(screens.executeMethod.fieldParameter) + const fields = await driver.findElements(screens.executeMethod.fieldParameter) + assert.notEqual(fields[1], false, "field value isn't displayed") + await fields[1].sendKeys('1') + // Fill out address + await clearField(fields[0], 100) + await fields[0].sendKeys(account1) + assert.notEqual(fields[0], false, "field address isn't displayed") + // Click button next + const buttonNext = await waitUntilShowUp(screens.executeMethod.buttonNext) + assert.notEqual(buttonNext, false, "button 'Next' isn't displayed") + await buttonNext.click() + // Select executor + await waitUntilShowUp(screens.chooseContractExecutor.account) + const accounts = await driver.findElements(screens.chooseContractExecutor.account) + const account = accounts[executor + 1] + await account.click() + // Open confirm transaction + const button = await waitUntilShowUp(screens.chooseContractExecutor.buttonNext) + await button.click() + return true + } catch (err) { + return false + } + } + }) diff --git a/test/unit/ui/app/actions.spec.js b/test/unit/ui/app/actions.spec.js index f123c0fe5..e29c22c67 100644 --- a/test/unit/ui/app/actions.spec.js +++ b/test/unit/ui/app/actions.spec.js @@ -813,7 +813,12 @@ describe('Actions', () => { const store = mockStore() const expectedActions = [ { type: 'DISPLAY_WARNING', value: 'error' }, - { type: 'SHOW_CONF_TX_PAGE', transForward: true, id: undefined, value: {} }, + { + type: 'SHOW_CONF_TX_PAGE', + transForward: true, + id: undefined, + value: {isContractExecutionByUser: undefined}, + }, ] sendTransactionSpy.callsFake((txData, callback) => { callback(new Error('error')) diff --git a/ui/app/actions.js b/ui/app/actions.js index 8dd51fc80..fa901fe41 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -975,7 +975,7 @@ function signTx (txData) { return dispatch(actions.displayWarning(err.message)) } }) - dispatch(actions.showConfTxPage({})) + dispatch(actions.showConfTxPage({isContractExecutionByUser: txData && txData.isContractExecutionByUser})) } } @@ -2299,10 +2299,13 @@ function onboardingBuyEthView (address) { } } -function buyEthView (address) { +function buyEthView (address, isContractExecutionByUser) { return { type: actions.BUY_ETH_VIEW, - value: address, + value: { + address, + isContractExecutionByUser, + }, } } diff --git a/ui/app/reducers/app.js b/ui/app/reducers/app.js index 86a05bc64..613f00535 100644 --- a/ui/app/reducers/app.js +++ b/ui/app/reducers/app.js @@ -695,11 +695,12 @@ function reduceApp (state, action) { name: 'buyEth', context: appState.currentView.name, }, - identity: state.metamask.identities[action.value], + identity: state.metamask.identities[action.value.address], buyView: { subview: 'Coinbase', amount: '15.00', - buyAddress: action.value, + buyAddress: action.value.address, + isContractExecutionByUser: action.value.isContractExecutionByUser, formView: { coinbase: true, shapeshift: false,