From a0da1a5ae912d45d9825313cca8c5f265eb72deb Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Thu, 20 Sep 2018 17:36:44 +0300 Subject: [PATCH 1/7] token menu --- .circleci/config.yml | 44 ++++----- .nvmrc | 2 +- old-ui/app/components/account-dropdowns.js | 20 +--- .../app/components/delete-imported-account.js | 1 - old-ui/app/components/token-cell.js | 93 +++++++++++++++++-- old-ui/app/components/token-list.js | 9 +- old-ui/app/css/index.css | 8 ++ package-lock.json | 8 +- package.json | 6 +- 9 files changed, 135 insertions(+), 56 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 64aaa2674..20765d1a9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -96,7 +96,7 @@ workflows: jobs: prep-deps-npm: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -104,14 +104,14 @@ jobs: - run: name: Install npm 6 + deps via npm command: | - sudo npm install -g npm@6.1.0 && npm install --no-save + sudo npm install -g npm@6.4.1 && npm install --no-save - save_cache: key: dependency-cache-{{ .Revision }} paths: - node_modules prep-deps-firefox: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -126,7 +126,7 @@ jobs: prep-build: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -145,7 +145,7 @@ jobs: prep-docs: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -160,7 +160,7 @@ jobs: prep-scss: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -179,7 +179,7 @@ jobs: test-lint: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -190,7 +190,7 @@ jobs: test-deps: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -201,7 +201,7 @@ jobs: test-e2e-chrome: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -217,7 +217,7 @@ jobs: test-e2e-firefox: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -238,7 +238,7 @@ jobs: test-e2e-beta-chrome: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -254,7 +254,7 @@ jobs: test-e2e-beta-firefox: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -275,7 +275,7 @@ jobs: job-screens: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -292,7 +292,7 @@ jobs: job-publish-prerelease: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -319,7 +319,7 @@ jobs: job-publish-release: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -332,7 +332,7 @@ jobs: job-publish-postrelease: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -355,7 +355,7 @@ jobs: test-unit: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -368,7 +368,7 @@ jobs: environment: browsers: '["Firefox"]' docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -392,7 +392,7 @@ jobs: environment: browsers: '["Chrome"]' docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -411,7 +411,7 @@ jobs: environment: browsers: '["Firefox"]' docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -435,7 +435,7 @@ jobs: environment: browsers: '["Chrome"]' docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -452,7 +452,7 @@ jobs: all-tests-pass: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - run: name: All Tests Passed diff --git a/.nvmrc b/.nvmrc index 08df4d99f..368fe859d 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v8.11.4 +v8.12.0 diff --git a/old-ui/app/components/account-dropdowns.js b/old-ui/app/components/account-dropdowns.js index 45e584510..84df18066 100644 --- a/old-ui/app/components/account-dropdowns.js +++ b/old-ui/app/components/account-dropdowns.js @@ -177,17 +177,14 @@ class AccountDropdowns extends Component { } renderAccountOptions () { - const { actions, network } = this.props + const { actions } = this.props const { optionsMenuActive } = this.state - const isSokol = parseInt(network) === 77 - const isPOA = parseInt(network) === 99 - const explorerStr = (isSokol || isPOA) ? 'POA explorer' : 'Etherscan' - return h( Dropdown, { style: { + position: 'relative', marginLeft: '-234px', minWidth: '180px', marginTop: '30px', @@ -213,7 +210,7 @@ class AccountDropdowns extends Component { global.platform.openWindow({ url }) }, }, - `View account on ${explorerStr}`, + `View on block explorer`, ), h( DropdownMenuItem, @@ -237,7 +234,7 @@ class AccountDropdowns extends Component { copyToClipboard(checkSumAddress) }, }, - 'Copy Address to clipboard', + 'Copy address to clipboard', ), h( DropdownMenuItem, @@ -283,15 +280,8 @@ class AccountDropdowns extends Component { this.renderAccountSelector(), ), enableAccountOptions && h( - 'div.account-dropdown', + 'div.address-dropdown.account-dropdown', { - style: { - backgroundImage: 'url(../images/more.svg)', - width: '30px', - height: '24px', - backgroundRepeat: 'no-repeat', - backgroundPosition: 'center', - }, onClick: (event) => { event.stopPropagation() this.setState({ diff --git a/old-ui/app/components/delete-imported-account.js b/old-ui/app/components/delete-imported-account.js index 625288f9c..906969f82 100644 --- a/old-ui/app/components/delete-imported-account.js +++ b/old-ui/app/components/delete-imported-account.js @@ -20,7 +20,6 @@ function DeleteImportedAccount () { } DeleteImportedAccount.prototype.render = function () { - console.log('this.props:', this.props) return h('.flex-column.flex-grow', { style: { overflowX: 'auto', diff --git a/old-ui/app/components/token-cell.js b/old-ui/app/components/token-cell.js index cb1d0c7fd..b8742ed33 100644 --- a/old-ui/app/components/token-cell.js +++ b/old-ui/app/components/token-cell.js @@ -3,23 +3,32 @@ const h = require('react-hyperscript') const inherits = require('util').inherits const Identicon = require('./identicon') const ethNetProps = require('eth-net-props') +const Dropdown = require('./dropdown').Dropdown +const DropdownMenuItem = require('./dropdown').DropdownMenuItem +const ethUtil = require('ethereumjs-util') +const copyToClipboard = require('copy-to-clipboard') module.exports = TokenCell inherits(TokenCell, Component) function TokenCell () { Component.call(this) + + this.state = { + optionsMenuActive: false, + } + this.optionsMenuToggleClassName = 'token-dropdown' } TokenCell.prototype.render = function () { - const props = this.props - const { address, symbol, string, network, userAddress } = props + const { address, symbol, string, network, userAddress, isLastTokenCell, menuToTop } = this.props + const { optionsMenuActive } = this.state return ( h('li.token-cell', { style: { cursor: network === '1' ? 'pointer' : 'default', - borderBottom: props.isLastTokenCell ? 'none' : '1px solid #e2e2e2', + borderBottom: isLastTokenCell ? 'none' : '1px solid #e2e2e2', padding: '20px 0', margin: '0 30px', }, @@ -41,13 +50,18 @@ TokenCell.prototype.render = function () { h('span', { style: { flex: '1 0 auto' } }), - h('span.trash', { - style: { cursor: 'pointer' }, - onClick: (event) => { - event.stopPropagation() - this.props.removeToken({ address, symbol, string, network, userAddress }) + h('div.address-dropdown.token-dropdown', + { + style: { cursor: 'pointer' }, + onClick: (event) => { + event.stopPropagation() + this.setState({ + optionsMenuActive: !optionsMenuActive, + }) + }, }, - }, ''), + this.renderTokenOptions(menuToTop) + ), /* h('button', { @@ -59,6 +73,67 @@ TokenCell.prototype.render = function () { ) } +TokenCell.prototype.renderTokenOptions = function (menuToTop) { + const { address, symbol, string, network, userAddress } = this.props + const { optionsMenuActive } = this.state + + return h( + Dropdown, + { + style: { + position: 'relative', + marginLeft: '-263px', + minWidth: '180px', + marginTop: menuToTop ? '-200px' : '30px', + width: '280px', + }, + isOpen: optionsMenuActive, + onClickOutside: (event) => { + const { classList } = event.target + const isNotToggleElement = !classList.contains(this.optionsMenuToggleClassName) + if (optionsMenuActive && isNotToggleElement) { + this.setState({ optionsMenuActive: false }) + } + }, + }, + [ + h( + DropdownMenuItem, + { + closeMenu: () => {}, + onClick: () => { + const { network } = this.props + const url = ethNetProps.explorerLinks.getExplorerTokenLinkFor(address, userAddress, network) + global.platform.openWindow({ url }) + }, + }, + `View token on block explorer`, + ), + h( + DropdownMenuItem, + { + closeMenu: () => {}, + onClick: () => { + const checkSumAddress = address && ethUtil.toChecksumAddress(address) + copyToClipboard(checkSumAddress) + }, + }, + 'Copy address to clipboard', + ), + h( + DropdownMenuItem, + { + closeMenu: () => {}, + onClick: () => { + this.props.removeToken({ address, symbol, string, network, userAddress }) + }, + }, + 'Remove', + ), + ] + ) +} + TokenCell.prototype.send = function (address, event) { event.preventDefault() event.stopPropagation() diff --git a/old-ui/app/components/token-list.js b/old-ui/app/components/token-list.js index f49dd1c0d..d068a15d0 100644 --- a/old-ui/app/components/token-list.js +++ b/old-ui/app/components/token-list.js @@ -52,10 +52,17 @@ TokenList.prototype.render = function () { const tokenViews = tokensFromCurrentNetwork.map((tokenData, ind) => { tokenData.userAddress = userAddress - const isLastTokenCell = ind === (tokens.length - 1) + const isPenultimateTokenCell = ind === (tokensFromCurrentNetwork.length - 2) + const isLastTokenCell = ind === (tokensFromCurrentNetwork.length - 1) + const multipleTokens = tokensFromCurrentNetwork.length > 1 + const more2Tokens = tokensFromCurrentNetwork.length > 2 + const last2Tokens = more2Tokens && (isLastTokenCell || isPenultimateTokenCell) + const last1Token = !more2Tokens && isLastTokenCell + const menuToTop = multipleTokens && (last1Token || last2Tokens) return h(TokenCell, { ...tokenData, isLastTokenCell, + menuToTop, removeToken: this.props.removeToken, }) }) diff --git a/old-ui/app/css/index.css b/old-ui/app/css/index.css index 446a0efa6..2ed9014f9 100644 --- a/old-ui/app/css/index.css +++ b/old-ui/app/css/index.css @@ -29,6 +29,14 @@ html { overflow: -moz-scrollbars-none; } +.address-dropdown { + background-image: url(../images/more.svg); + width: 30px; + height: 24px; + background-repeat: no-repeat; + background-position: center; +} + .account-detail-section::-webkit-scrollbar { width: 0; } diff --git a/package-lock.json b/package-lock.json index 686c31651..935d327d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8453,7 +8453,7 @@ } }, "eth-contract-metadata": { - "version": "github:MetaMask/eth-contract-metadata#966a891dd9c79b873fd8968a0155b067ca630502", + "version": "github:MetaMask/eth-contract-metadata#bd23fa120512dcbb6fad31559297f96f17c3a8e0", "from": "github:MetaMask/eth-contract-metadata#master" }, "eth-ens-namehash": { @@ -8754,9 +8754,9 @@ } }, "eth-net-props": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/eth-net-props/-/eth-net-props-1.0.2.tgz", - "integrity": "sha512-lstMFwDb3GU3mUmWi1aGT+JlcK2qf54E+edE5x6uLrJEPr9ZYrFCuTaXyXZU8R1CEHTSaDtwRB7iTyTBVsIzoQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/eth-net-props/-/eth-net-props-1.0.3.tgz", + "integrity": "sha512-iHY/o2/JwEk+HOTFmn5ju1LXsMf+qNsJZ30SdD3WZ9PJH9jc7lqI6fh80xQHWqV7Q2pkZqD5YvO3G6fdrKzQ0Q==", "requires": { "chai": "^4.1.2" } diff --git a/package.json b/package.json index e9383019d..e3569e7a9 100644 --- a/package.json +++ b/package.json @@ -109,7 +109,7 @@ "eth-json-rpc-filters": "^1.2.6", "eth-json-rpc-infura": "^3.0.0", "eth-method-registry": "^1.0.0", - "eth-net-props": "^1.0.2", + "eth-net-props": "^1.0.3", "eth-phishing-detect": "^1.1.4", "eth-query": "^2.1.2", "eth-sig-util": "^1.4.2", @@ -318,7 +318,7 @@ "watchify": "^3.11.0" }, "engines": { - "node": "8.11.4", - "npm": "^6.1.0" + "node": "8.12.0", + "npm": "^6.4.1" } } From 3104f01ae13be34ccefe030ddcaa6e63906cbb79 Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Thu, 20 Sep 2018 18:38:04 +0300 Subject: [PATCH 2/7] when click to menu of one token, close other token's dropdown --- old-ui/app/components/token-cell.js | 19 +++++++++++-------- old-ui/app/components/token-list.js | 9 ++------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/old-ui/app/components/token-cell.js b/old-ui/app/components/token-cell.js index b8742ed33..e24000318 100644 --- a/old-ui/app/components/token-cell.js +++ b/old-ui/app/components/token-cell.js @@ -8,6 +8,8 @@ const DropdownMenuItem = require('./dropdown').DropdownMenuItem const ethUtil = require('ethereumjs-util') const copyToClipboard = require('copy-to-clipboard') +const tokenCellDropDownPrefix = 'token-cell_dropdown_' + module.exports = TokenCell inherits(TokenCell, Component) @@ -21,11 +23,11 @@ function TokenCell () { } TokenCell.prototype.render = function () { - const { address, symbol, string, network, userAddress, isLastTokenCell, menuToTop } = this.props + const { address, symbol, string, network, userAddress, isLastTokenCell, menuToTop, ind } = this.props const { optionsMenuActive } = this.state return ( - h('li.token-cell', { + h(`li#token-cell_${ind}.token-cell`, { style: { cursor: network === '1' ? 'pointer' : 'default', borderBottom: isLastTokenCell ? 'none' : '1px solid #e2e2e2', @@ -50,7 +52,7 @@ TokenCell.prototype.render = function () { h('span', { style: { flex: '1 0 auto' } }), - h('div.address-dropdown.token-dropdown', + h(`div#${tokenCellDropDownPrefix}${ind}.address-dropdown.token-dropdown`, { style: { cursor: 'pointer' }, onClick: (event) => { @@ -60,7 +62,7 @@ TokenCell.prototype.render = function () { }) }, }, - this.renderTokenOptions(menuToTop) + this.renderTokenOptions(menuToTop, ind) ), /* @@ -73,7 +75,7 @@ TokenCell.prototype.render = function () { ) } -TokenCell.prototype.renderTokenOptions = function (menuToTop) { +TokenCell.prototype.renderTokenOptions = function (menuToTop, ind) { const { address, symbol, string, network, userAddress } = this.props const { optionsMenuActive } = this.state @@ -89,9 +91,10 @@ TokenCell.prototype.renderTokenOptions = function (menuToTop) { }, isOpen: optionsMenuActive, onClickOutside: (event) => { - const { classList } = event.target - const isNotToggleElement = !classList.contains(this.optionsMenuToggleClassName) - if (optionsMenuActive && isNotToggleElement) { + const { classList, id: targetID } = event.target + const isNotToggleCell = !classList.contains(this.optionsMenuToggleClassName) + const isAnotherCell = targetID !== `${tokenCellDropDownPrefix}${ind}` + if (optionsMenuActive && (isNotToggleCell || (!isNotToggleCell && isAnotherCell))) { this.setState({ optionsMenuActive: false }) } }, diff --git a/old-ui/app/components/token-list.js b/old-ui/app/components/token-list.js index d068a15d0..fd5708b5b 100644 --- a/old-ui/app/components/token-list.js +++ b/old-ui/app/components/token-list.js @@ -52,14 +52,10 @@ TokenList.prototype.render = function () { const tokenViews = tokensFromCurrentNetwork.map((tokenData, ind) => { tokenData.userAddress = userAddress - const isPenultimateTokenCell = ind === (tokensFromCurrentNetwork.length - 2) const isLastTokenCell = ind === (tokensFromCurrentNetwork.length - 1) - const multipleTokens = tokensFromCurrentNetwork.length > 1 - const more2Tokens = tokensFromCurrentNetwork.length > 2 - const last2Tokens = more2Tokens && (isLastTokenCell || isPenultimateTokenCell) - const last1Token = !more2Tokens && isLastTokenCell - const menuToTop = multipleTokens && (last1Token || last2Tokens) + const menuToTop = true return h(TokenCell, { + ind, ...tokenData, isLastTokenCell, menuToTop, @@ -72,7 +68,6 @@ TokenList.prototype.render = function () { h('ol.full-flex-height.flex-column', { style: { - overflowY: 'auto', display: 'flex', flexDirection: 'column', }, From 521edbb4ea0d4639784d1e8f4b6a7ebd65d5e17f Mon Sep 17 00:00:00 2001 From: dennistikhomirov Date: Fri, 21 Sep 2018 03:55:42 -0700 Subject: [PATCH 3/7] e2e: token menu tests --- test/e2e/elements.js | 13 ++++- test/e2e/metamask.spec.js | 104 ++++++++++++++++++++++++++++++++++---- 2 files changed, 105 insertions(+), 12 deletions(-) diff --git a/test/e2e/elements.js b/test/e2e/elements.js index b443e46ca..ea2da4e3d 100644 --- a/test/e2e/elements.js +++ b/test/e2e/elements.js @@ -5,6 +5,16 @@ module.exports = { loader: By.css('#app-content > div > div.full-flex-height > img'), }, menus: { + token: { + menu: By.id('token-cell_dropdown_0'), + items: By.className('dropdown-menu-item'), + view: By.css('#token-cell_dropdown_0 > div > div > li:nth-child(2)'), + copy: By.css('#token-cell_dropdown_0 > div > div > li:nth-child(3)'), + remove: By.css('#token-cell_dropdown_0 > div > div > li:nth-child(4)'), + viewText: 'View token on block explorer', + copyText: 'Copy address to clipboard', + removeText: 'Remove', + }, sandwich: { menu: By.css('.sandwich-expando'), settings: By.css('#app-content > div > div:nth-child(3) > span > div > li:nth-child(2)'), @@ -148,7 +158,6 @@ module.exports = { balance: By.css('#app-content > div > div.app-primary.from-right > div > div > div.flex-row > div.ether-balance.ether-balance-amount > div > div > div:nth-child(1) > div:nth-child(1)'), address: By.css('#app-content > div > div.app-primary.from-left > div > div > div:nth-child(1) > flex-column > div.flex-row > div'), tokens: { - remove: By.className('trash'), menu: By.className('inactiveForm pointer'), token: By.css('#app-content > div > div.app-primary.from-left > div > section > div.full-flex-height > ol > li'), balance: By.css('#app-content > div > div.app-primary.from-left > div > section > div.full-flex-height > ol > li:nth-child(2) > h3'), @@ -169,7 +178,7 @@ module.exports = { title: By.className('page-subtitle'), titleText: 'Remove Token', label: By.className('confirm-label'), - labelText: 'Are you sure you want to remove token', + labelText: 'Are you sure you want to remove token "TST"?', buttons: { back: By.className('fa fa-arrow-left fa-lg cursor-pointer'), no: By.className('btn-violet'), diff --git a/test/e2e/metamask.spec.js b/test/e2e/metamask.spec.js index 83a8c06ba..0a591d3ee 100644 --- a/test/e2e/metamask.spec.js +++ b/test/e2e/metamask.spec.js @@ -8,7 +8,7 @@ const { By, Key } = webdriver const { delay, buildChromeWebDriver, buildFirefoxWebdriver, installWebExt, getExtensionIdChrome, getExtensionIdFirefox } = require('./func') const { menus, screens, elements, NETWORKS } = require('./elements') -describe('Metamask popup page', async function () { +describe('Nifty wallet popup page', async function () { let driver, accountAddress, tokenAddress, extensionId let password = '123456789' @@ -50,7 +50,7 @@ describe('Metamask popup page', async function () { }) after(async function () { - await driver.quit() + // await driver.quit() }) describe('Setup', async function () { @@ -698,6 +698,14 @@ describe('Metamask popup page', async function () { const tokenBalance = await waitUntilShowUp(screens.main.tokens.balance) assert.equal(await tokenBalance.getText(), '0 TST') }) + + it('click to token opens the etherscan', async function () { + await (await waitUntilShowUp(screens.main.tokens.token)).click() + await switchToLastPage() + const title = await driver.getCurrentUrl() + assert.equal(title.includes('https://etherscan.io/token/'), true, 'link leads to wrong page') + await switchToFirstPage() + }) }) describe('Check support of token per network basis ', async function () { @@ -792,14 +800,50 @@ describe('Metamask popup page', async function () { }) }) }) + describe('Token menu', function () { + it('token menu is displayed and clickable ', async function () { + const menu = await waitUntilShowUp(menus.token.menu) + await menu.click() + }) + + it('link \'View on blockexplorer...\' leads to correct page ', async function () { + const menu = await waitUntilShowUp(menus.token.view) + assert.notEqual(menu, false, 'item isn\'t displayed') + assert.equal(await menu.getText(), menus.token.viewText, 'incorrect name') + await menu.click() + await switchToLastPage() + const title = await driver.getCurrentUrl() + assert.equal(title.includes('https://etherscan.io/token/'), true, 'link leads to wrong page') + await switchToFirstPage() + }) + + it('item \'Copy\' is displayed and clickable ', async function () { + let menu = await waitUntilShowUp(menus.token.menu) + await menu.click() + const item = await waitUntilShowUp(menus.token.copy) + assert.notEqual(item, false, 'item isn\'t displayed') + assert.equal(await item.getText(), menus.token.copyText, 'incorrect name') + await item.click() + menu = await waitUntilShowUp(menus.token.menu, 10) + assert.notEqual(menu, false, 'menu wasn\'t closed') + }) + it('item \'Remove\' is displayed', async function () { + const menu = await waitUntilShowUp(menus.token.menu) + await menu.click() + const item = await waitUntilShowUp(menus.token.remove) + assert.notEqual(item, false, 'item isn\'t displayed') + assert.equal(await item.getText(), menus.token.removeText, 'incorrect name') + }) + }) describe('Remove Token', function () { - it('button \'Remove token\' displayed', async function () { + it('remove option open \'Remove token\' screen ', async function () { await setProvider(NETWORKS.LOCALHOST) - const removeTokenButton = await waitUntilShowUp(screens.main.tokens.remove) - assert.notEqual(removeTokenButton, false, 'button isn\'t displayed') - await removeTokenButton.click() + const menu = await waitUntilShowUp(menus.token.menu) + await menu.click() + const remove = await waitUntilShowUp(menus.token.remove) + await remove.click() }) it('screen \'Remove token\' has correct title', async function () { @@ -807,6 +851,11 @@ describe('Metamask popup page', async function () { assert.equal(await title.getText(), screens.removeToken.titleText, 'title is incorrect') }) + it('screen \'Remove token\' has correct label', async function () { + const title = await waitUntilShowUp(screens.removeToken.label) + assert.equal(await title.getText(), screens.removeToken.labelText, 'label is incorrect') + }) + it('button "No" bring back to "Main" screen', async function () { const title = await waitUntilShowUp(screens.removeToken.title) assert.equal(await title.getText(), screens.removeToken.titleText, 'title is incorrect') @@ -819,9 +868,11 @@ describe('Metamask popup page', async function () { }) it('button "Yes" delete token', async function () { - const removeTokenButton = await waitUntilShowUp(screens.main.tokens.remove) - assert.notEqual(removeTokenButton, false, 'button isn\'t displayed') - await removeTokenButton.click() + const menu = await waitUntilShowUp(menus.token.menu) + await menu.click() + const remove = await waitUntilShowUp(menus.token.remove) + await remove.click() + const title = await waitUntilShowUp(screens.removeToken.title) assert.equal(await title.getText(), screens.removeToken.titleText, 'title is incorrect') @@ -1079,7 +1130,7 @@ describe('Metamask popup page', async function () { } async function waitUntilShowUp (by, Twait) { - if (Twait === undefined) Twait = 2000 + if (Twait === undefined) Twait = 200 do { await delay(100) if (await isElementDisplayed(by)) return await driver.findElement(by) @@ -1166,5 +1217,38 @@ describe('Metamask popup page', async function () { const htmlSource = await driver.getPageSource() await pify(fs.writeFile)(`${filepathBase}-dom.html`, htmlSource) } + + async function switchToLastPage () { + try { + const allHandles = await driver.getAllWindowHandles() + await driver.switchTo().window(allHandles[allHandles.length - 1]) + let counter = 100 + do { + await delay(500) + if (await driver.getCurrentUrl() !== '') return true + } + while (counter-- > 0) + return true + } catch (err) { + return false + } + } + + async function switchToFirstPage () { + try { + const allHandles = await driver.getAllWindowHandles() + await driver.switchTo().window(allHandles[0]) + let counter = 100 + do { + await delay(500) + if (await driver.getCurrentUrl() !== '') return true + } + while (counter-- > 0) + return true + } catch (err) { + return false + } + } + }) From 2ba1146a636ba953985f18a29f9c42ea64540559 Mon Sep 17 00:00:00 2001 From: dennistikhomirov Date: Fri, 21 Sep 2018 05:10:26 -0700 Subject: [PATCH 4/7] e2e:test for links to block explorers --- test/e2e/metamask.spec.js | 70 +++++++++++++++++++++++++++++++++------ 1 file changed, 59 insertions(+), 11 deletions(-) diff --git a/test/e2e/metamask.spec.js b/test/e2e/metamask.spec.js index 0a591d3ee..4af5ce5a9 100644 --- a/test/e2e/metamask.spec.js +++ b/test/e2e/metamask.spec.js @@ -50,7 +50,7 @@ describe('Nifty wallet popup page', async function () { }) after(async function () { - // await driver.quit() + await driver.quit() }) describe('Setup', async function () { @@ -698,14 +698,6 @@ describe('Nifty wallet popup page', async function () { const tokenBalance = await waitUntilShowUp(screens.main.tokens.balance) assert.equal(await tokenBalance.getText(), '0 TST') }) - - it('click to token opens the etherscan', async function () { - await (await waitUntilShowUp(screens.main.tokens.token)).click() - await switchToLastPage() - const title = await driver.getCurrentUrl() - assert.equal(title.includes('https://etherscan.io/token/'), true, 'link leads to wrong page') - await switchToFirstPage() - }) }) describe('Check support of token per network basis ', async function () { @@ -755,6 +747,14 @@ describe('Nifty wallet popup page', async function () { assert.notEqual(await tokenBalance.getText(), '') }) + it('click to token opens the PoaExplorer', async function () { + await (await waitUntilShowUp(screens.main.tokens.token)).click() + await switchToLastPage() + const title = await driver.getCurrentUrl() + assert.equal(title.includes('https://poaexplorer.com/address/' + tokenAddress), true, 'link leads to wrong page') + await switchToFirstPage() + }) + it('adds token with the same address to SOKOL network', async function () { await setProvider(NETWORKS.SOKOL) await addToken(tokenAddress, tokenName, tokenDecimals) @@ -762,6 +762,14 @@ describe('Nifty wallet popup page', async function () { assert.notEqual(await tokenBalance.getText(), '') }) + it('click to token opens the Sokol PoaExplorer', async function () { + await (await waitUntilShowUp(screens.main.tokens.token)).click() + await switchToLastPage() + const title = await driver.getCurrentUrl() + assert.equal(title.includes('https://sokol.poaexplorer.com/address/search/' + tokenAddress), true, 'link leads to wrong page') + await switchToFirstPage() + }) + it('adds token with the same address to MAINNET network', async function () { await setProvider(NETWORKS.MAINNET) await addToken(tokenAddress, tokenName, tokenDecimals) @@ -769,6 +777,14 @@ describe('Nifty wallet popup page', async function () { assert.notEqual(await tokenBalance.getText(), '') }) + it('click to token opens the Etherscan', async function () { + await (await waitUntilShowUp(screens.main.tokens.token)).click() + await switchToLastPage() + const title = await driver.getCurrentUrl() + assert.equal(title.includes('https://etherscan.io/token/' + tokenAddress), true, 'link leads to wrong page') + await switchToFirstPage() + }) + it('adds token with the same address to ROPSTEN network', async function () { await setProvider(NETWORKS.ROPSTEN) await addToken(tokenAddress, tokenName, tokenDecimals) @@ -776,6 +792,14 @@ describe('Nifty wallet popup page', async function () { assert.notEqual(await tokenBalance.getText(), '') }) + it('click to token opens the Ropsten Etherscan', async function () { + await (await waitUntilShowUp(screens.main.tokens.token)).click() + await switchToLastPage() + const title = await driver.getCurrentUrl() + assert.equal(title.includes('https://ropsten.etherscan.io/token/' + tokenAddress), true, 'link leads to wrong page') + await switchToFirstPage() + }) + it('adds token with the same address to KOVAN network', async function () { await setProvider(NETWORKS.KOVAN) await addToken(tokenAddress, tokenName, tokenDecimals) @@ -783,6 +807,14 @@ describe('Nifty wallet popup page', async function () { assert.notEqual(await tokenBalance.getText(), '') }) + it('click to token opens the Kovan Etherscan', async function () { + await (await waitUntilShowUp(screens.main.tokens.token)).click() + await switchToLastPage() + const title = await driver.getCurrentUrl() + assert.equal(title.includes('https://kovan.etherscan.io/token/' + tokenAddress), true, 'link leads to wrong page') + await switchToFirstPage() + }) + it('adds token with the same address to RINKEBY network', async function () { await setProvider(NETWORKS.RINKEBY) await addToken(tokenAddress, tokenName, tokenDecimals) @@ -790,6 +822,14 @@ describe('Nifty wallet popup page', async function () { assert.notEqual(await tokenBalance.getText(), '') }) + it('click to token opens the Rinkeby Etherscan', async function () { + await (await waitUntilShowUp(screens.main.tokens.token)).click() + await switchToLastPage() + const title = await driver.getCurrentUrl() + assert.equal(title.includes('https://rinkeby.etherscan.io/token/' + tokenAddress), true, 'link leads to wrong page') + await switchToFirstPage() + }) + it('token still should be displayed in LOCALHOST network', async function () { await setProvider(NETWORKS.LOCALHOST) await waitUntilDisappear(screens.main.tokens.amount) @@ -798,6 +838,14 @@ describe('Nifty wallet popup page', async function () { assert.equal(tokens.length, 1, '\'Tokens\' section doesn\'t contain field with amount of tokens') assert.equal(await tokens[0].getText(), screens.main.tokens.textYouOwn1token, 'Token isn\'t displayed') }) + + it('click to token opens the Etherscan', async function () { + await (await waitUntilShowUp(screens.main.tokens.token)).click() + await switchToLastPage() + const title = await driver.getCurrentUrl() + assert.equal(title.includes('https://etherscan.io/token/' + tokenAddress), true, 'link leads to wrong page') + await switchToFirstPage() + }) }) }) describe('Token menu', function () { @@ -1225,7 +1273,7 @@ describe('Nifty wallet popup page', async function () { let counter = 100 do { await delay(500) - if (await driver.getCurrentUrl() !== '') return true + if (await driver.getCurrentUrl() !== 'about:blank') return true } while (counter-- > 0) return true @@ -1241,7 +1289,7 @@ describe('Nifty wallet popup page', async function () { let counter = 100 do { await delay(500) - if (await driver.getCurrentUrl() !== '') return true + if (await driver.getCurrentUrl() !== 'about:blank') return true } while (counter-- > 0) return true From 896ed821205311f40c75767e15600aaa26b8c5c0 Mon Sep 17 00:00:00 2001 From: dennistikhomirov Date: Fri, 21 Sep 2018 05:28:58 -0700 Subject: [PATCH 5/7] e2e:skip poaexplrer check --- test/e2e/metamask.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/metamask.spec.js b/test/e2e/metamask.spec.js index 4af5ce5a9..b86041178 100644 --- a/test/e2e/metamask.spec.js +++ b/test/e2e/metamask.spec.js @@ -747,7 +747,7 @@ describe('Nifty wallet popup page', async function () { assert.notEqual(await tokenBalance.getText(), '') }) - it('click to token opens the PoaExplorer', async function () { + it.skip('click to token opens the PoaExplorer', async function () { await (await waitUntilShowUp(screens.main.tokens.token)).click() await switchToLastPage() const title = await driver.getCurrentUrl() From fe04bb896fc35d01b7a5dcf4b68307451913e76e Mon Sep 17 00:00:00 2001 From: dennistikhomirov Date: Fri, 21 Sep 2018 05:43:32 -0700 Subject: [PATCH 6/7] e2e:skip poaexplrer check --- test/e2e/metamask.spec.js | 70 ++++++--------------------------------- 1 file changed, 11 insertions(+), 59 deletions(-) diff --git a/test/e2e/metamask.spec.js b/test/e2e/metamask.spec.js index b86041178..fbecd27e0 100644 --- a/test/e2e/metamask.spec.js +++ b/test/e2e/metamask.spec.js @@ -50,7 +50,7 @@ describe('Nifty wallet popup page', async function () { }) after(async function () { - await driver.quit() + await driver.quit() }) describe('Setup', async function () { @@ -698,6 +698,14 @@ describe('Nifty wallet popup page', async function () { const tokenBalance = await waitUntilShowUp(screens.main.tokens.balance) assert.equal(await tokenBalance.getText(), '0 TST') }) + + it('click to token opens the etherscan', async function () { + await (await waitUntilShowUp(screens.main.tokens.token)).click() + await switchToLastPage() + const title = await driver.getCurrentUrl() + assert.equal(title.includes('https://etherscan.io/token/'), true, 'link leads to wrong page') + await switchToFirstPage() + }) }) describe('Check support of token per network basis ', async function () { @@ -747,14 +755,6 @@ describe('Nifty wallet popup page', async function () { assert.notEqual(await tokenBalance.getText(), '') }) - it.skip('click to token opens the PoaExplorer', async function () { - await (await waitUntilShowUp(screens.main.tokens.token)).click() - await switchToLastPage() - const title = await driver.getCurrentUrl() - assert.equal(title.includes('https://poaexplorer.com/address/' + tokenAddress), true, 'link leads to wrong page') - await switchToFirstPage() - }) - it('adds token with the same address to SOKOL network', async function () { await setProvider(NETWORKS.SOKOL) await addToken(tokenAddress, tokenName, tokenDecimals) @@ -762,14 +762,6 @@ describe('Nifty wallet popup page', async function () { assert.notEqual(await tokenBalance.getText(), '') }) - it('click to token opens the Sokol PoaExplorer', async function () { - await (await waitUntilShowUp(screens.main.tokens.token)).click() - await switchToLastPage() - const title = await driver.getCurrentUrl() - assert.equal(title.includes('https://sokol.poaexplorer.com/address/search/' + tokenAddress), true, 'link leads to wrong page') - await switchToFirstPage() - }) - it('adds token with the same address to MAINNET network', async function () { await setProvider(NETWORKS.MAINNET) await addToken(tokenAddress, tokenName, tokenDecimals) @@ -777,14 +769,6 @@ describe('Nifty wallet popup page', async function () { assert.notEqual(await tokenBalance.getText(), '') }) - it('click to token opens the Etherscan', async function () { - await (await waitUntilShowUp(screens.main.tokens.token)).click() - await switchToLastPage() - const title = await driver.getCurrentUrl() - assert.equal(title.includes('https://etherscan.io/token/' + tokenAddress), true, 'link leads to wrong page') - await switchToFirstPage() - }) - it('adds token with the same address to ROPSTEN network', async function () { await setProvider(NETWORKS.ROPSTEN) await addToken(tokenAddress, tokenName, tokenDecimals) @@ -792,14 +776,6 @@ describe('Nifty wallet popup page', async function () { assert.notEqual(await tokenBalance.getText(), '') }) - it('click to token opens the Ropsten Etherscan', async function () { - await (await waitUntilShowUp(screens.main.tokens.token)).click() - await switchToLastPage() - const title = await driver.getCurrentUrl() - assert.equal(title.includes('https://ropsten.etherscan.io/token/' + tokenAddress), true, 'link leads to wrong page') - await switchToFirstPage() - }) - it('adds token with the same address to KOVAN network', async function () { await setProvider(NETWORKS.KOVAN) await addToken(tokenAddress, tokenName, tokenDecimals) @@ -807,14 +783,6 @@ describe('Nifty wallet popup page', async function () { assert.notEqual(await tokenBalance.getText(), '') }) - it('click to token opens the Kovan Etherscan', async function () { - await (await waitUntilShowUp(screens.main.tokens.token)).click() - await switchToLastPage() - const title = await driver.getCurrentUrl() - assert.equal(title.includes('https://kovan.etherscan.io/token/' + tokenAddress), true, 'link leads to wrong page') - await switchToFirstPage() - }) - it('adds token with the same address to RINKEBY network', async function () { await setProvider(NETWORKS.RINKEBY) await addToken(tokenAddress, tokenName, tokenDecimals) @@ -822,14 +790,6 @@ describe('Nifty wallet popup page', async function () { assert.notEqual(await tokenBalance.getText(), '') }) - it('click to token opens the Rinkeby Etherscan', async function () { - await (await waitUntilShowUp(screens.main.tokens.token)).click() - await switchToLastPage() - const title = await driver.getCurrentUrl() - assert.equal(title.includes('https://rinkeby.etherscan.io/token/' + tokenAddress), true, 'link leads to wrong page') - await switchToFirstPage() - }) - it('token still should be displayed in LOCALHOST network', async function () { await setProvider(NETWORKS.LOCALHOST) await waitUntilDisappear(screens.main.tokens.amount) @@ -838,14 +798,6 @@ describe('Nifty wallet popup page', async function () { assert.equal(tokens.length, 1, '\'Tokens\' section doesn\'t contain field with amount of tokens') assert.equal(await tokens[0].getText(), screens.main.tokens.textYouOwn1token, 'Token isn\'t displayed') }) - - it('click to token opens the Etherscan', async function () { - await (await waitUntilShowUp(screens.main.tokens.token)).click() - await switchToLastPage() - const title = await driver.getCurrentUrl() - assert.equal(title.includes('https://etherscan.io/token/' + tokenAddress), true, 'link leads to wrong page') - await switchToFirstPage() - }) }) }) describe('Token menu', function () { @@ -1273,7 +1225,7 @@ describe('Nifty wallet popup page', async function () { let counter = 100 do { await delay(500) - if (await driver.getCurrentUrl() !== 'about:blank') return true + if (await driver.getCurrentUrl() !== '') return true } while (counter-- > 0) return true @@ -1289,7 +1241,7 @@ describe('Nifty wallet popup page', async function () { let counter = 100 do { await delay(500) - if (await driver.getCurrentUrl() !== 'about:blank') return true + if (await driver.getCurrentUrl() !== '') return true } while (counter-- > 0) return true From 6cf2b148c0669d30757d13265446bf382b5a2118 Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Tue, 2 Oct 2018 18:50:55 +0300 Subject: [PATCH 7/7] account menu position fix --- old-ui/app/components/account-dropdowns.js | 1 + 1 file changed, 1 insertion(+) diff --git a/old-ui/app/components/account-dropdowns.js b/old-ui/app/components/account-dropdowns.js index 84df18066..010385adf 100644 --- a/old-ui/app/components/account-dropdowns.js +++ b/old-ui/app/components/account-dropdowns.js @@ -188,6 +188,7 @@ class AccountDropdowns extends Component { marginLeft: '-234px', minWidth: '180px', marginTop: '30px', + top: '30px', width: '280px', }, isOpen: optionsMenuActive,