diff options
author | Whymarrh Whitby <whymarrh.whitby@gmail.com> | 2018-08-01 01:02:21 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-08-01 01:02:21 +0800 |
commit | 4f02726fd9a2b7509dfd00eb4b23d9fc81eb5dcd (patch) | |
tree | a4d80674801687b915ffad6c0530df2b5d1edbc3 | |
parent | 2cefab544d4ed24788dc09e7d7b527655676c2c1 (diff) | |
parent | c3ce2984ef078d39b88a1fd8b007063d6c994c23 (diff) | |
download | tangerine-wallet-browser-4f02726fd9a2b7509dfd00eb4b23d9fc81eb5dcd.tar tangerine-wallet-browser-4f02726fd9a2b7509dfd00eb4b23d9fc81eb5dcd.tar.gz tangerine-wallet-browser-4f02726fd9a2b7509dfd00eb4b23d9fc81eb5dcd.tar.bz2 tangerine-wallet-browser-4f02726fd9a2b7509dfd00eb4b23d9fc81eb5dcd.tar.lz tangerine-wallet-browser-4f02726fd9a2b7509dfd00eb4b23d9fc81eb5dcd.tar.xz tangerine-wallet-browser-4f02726fd9a2b7509dfd00eb4b23d9fc81eb5dcd.tar.zst tangerine-wallet-browser-4f02726fd9a2b7509dfd00eb4b23d9fc81eb5dcd.zip |
Merge pull request #4888 from whymarrh/suggest-new-ui
Add old UI component to suggest new UI
-rw-r--r-- | mascara/src/app/first-time/index.js | 20 | ||||
-rw-r--r-- | old-ui/app/account-qr.js | 86 | ||||
-rw-r--r-- | old-ui/app/app.js | 461 | ||||
-rw-r--r-- | old-ui/app/components/app-bar.js | 432 | ||||
-rw-r--r-- | old-ui/app/components/qr-code.js | 79 | ||||
-rw-r--r-- | old-ui/app/components/shapeshift-form.js | 4 | ||||
-rw-r--r-- | old-ui/app/css/index.css | 128 | ||||
-rw-r--r-- | old-ui/app/new-ui-annoucement.js | 85 | ||||
-rw-r--r-- | test/e2e/beta/from-import-beta-ui.spec.js | 67 | ||||
-rw-r--r-- | test/e2e/beta/metamask-beta-ui.spec.js | 70 | ||||
-rw-r--r-- | test/e2e/metamask.spec.js | 15 | ||||
-rw-r--r-- | test/integration/lib/first-time.js | 5 |
12 files changed, 861 insertions, 591 deletions
diff --git a/mascara/src/app/first-time/index.js b/mascara/src/app/first-time/index.js index dc254bb19..6e4dc74bb 100644 --- a/mascara/src/app/first-time/index.js +++ b/mascara/src/app/first-time/index.js @@ -3,7 +3,6 @@ import PropTypes from 'prop-types' import {connect} from 'react-redux' import { withRouter, Switch, Route } from 'react-router-dom' import { compose } from 'recompose' -import classnames from 'classnames' import CreatePasswordScreen from './create-password-screen' import UniqueImageScreen from './unique-image-screen' @@ -44,28 +43,9 @@ class FirstTimeFlow extends Component { noActiveNotices: false, }; - renderAppBar () { - const { welcomeScreenSeen } = this.props - - return ( - <div className="alpha-warning__container"> - <h2 className={classnames({ - 'alpha-warning': welcomeScreenSeen, - 'alpha-warning-welcome-screen': !welcomeScreenSeen, - })} - > - Please be aware that this version is still under development - </h2> - </div> - ) - } - render () { - const { isPopup } = this.props - return ( <div className="flex-column flex-grow"> - { !isPopup && this.renderAppBar() } <div className="first-time-flow"> <Switch> <Route exact path={INITIALIZE_IMPORT_ACCOUNT_ROUTE} component={ImportAccountScreen} /> diff --git a/old-ui/app/account-qr.js b/old-ui/app/account-qr.js new file mode 100644 index 000000000..b41cc5112 --- /dev/null +++ b/old-ui/app/account-qr.js @@ -0,0 +1,86 @@ +const PropTypes = require('prop-types') +const {PureComponent} = require('react') +const h = require('react-hyperscript') +const {qrcode: qrCode} = require('qrcode-npm') +const {connect} = require('react-redux') +const {isHexPrefixed} = require('ethereumjs-util') +const actions = require('../../ui/app/actions') +const CopyButton = require('./components/copyButton') + +class AccountQrScreen extends PureComponent { + static defaultProps = { + warning: null, + } + + static propTypes = { + dispatch: PropTypes.func.isRequired, + buyView: PropTypes.any.isRequired, + Qr: PropTypes.object.isRequired, + selectedAddress: PropTypes.string.isRequired, + warning: PropTypes.node, + } + + render () { + const {dispatch, Qr, selectedAddress, warning} = this.props + const address = `${isHexPrefixed(Qr.data) ? 'ethereum:' : ''}${Qr.data}` + const qrImage = qrCode(4, 'M') + + qrImage.addData(address) + qrImage.make() + + return h('div.flex-column.full-width', { + style: { + alignItems: 'center', + boxSizing: 'border-box', + padding: '50px', + }, + }, [ + h('div.flex-row.full-width', { + style: { + alignItems: 'flex-start', + }, + }, [ + h('i.fa.fa-arrow-left.fa-lg.cursor-pointer.color-orange', { + onClick () { + dispatch(actions.backToAccountDetail(selectedAddress)) + }, + }), + ]), + h('div.qr-header', Qr.message), + warning && h('span.error.flex-center', { + style: { + textAlign: 'center', + width: '229px', + height: '82px', + }, + }, [ + this.props.warning, + ]), + h('div#qr-container.flex-column', { + style: { + marginTop: '25px', + marginBottom: '15px', + }, + dangerouslySetInnerHTML: { + __html: qrImage.createTableTag(4), + }, + }), + h('div.flex-row.full-width', [ + h('h3.ellip-address.grow-tenx', Qr.data), + h(CopyButton, { + value: Qr.data, + }), + ]), + ]) + } +} + +function mapStateToProps (state) { + return { + Qr: state.appState.Qr, + buyView: state.appState.buyView, + warning: state.appState.warning, + } +} + +module.exports = connect(mapStateToProps)(AccountQrScreen) diff --git a/old-ui/app/app.js b/old-ui/app/app.js index 0637e3b5b..d3e9e823b 100644 --- a/old-ui/app/app.js +++ b/old-ui/app/app.js @@ -14,6 +14,7 @@ const NewKeyChainScreen = require('./new-keychain') const UnlockScreen = require('./unlock') // accounts const AccountDetailScreen = require('./account-detail') +const AccountQrScreen = require('./account-qr') const SendTransactionScreen = require('./send') const ConfirmTxScreen = require('./conf-tx') // notice @@ -24,17 +25,13 @@ const ConfigScreen = require('./config') const AddTokenScreen = require('./add-token') const Import = require('./accounts/import') const InfoScreen = require('./info') +const NewUiAnnouncement = require('./new-ui-annoucement') +const AppBar = require('./components/app-bar') const Loading = require('./components/loading') -const SandwichExpando = require('sandwich-expando') -const Dropdown = require('./components/dropdown').Dropdown -const DropdownMenuItem = require('./components/dropdown').DropdownMenuItem -const NetworkIndicator = require('./components/network') const BuyView = require('./components/buy-button-subview') -const QrView = require('./components/qr-code') const HDCreateVaultComplete = require('./keychains/hd/create-vault-complete') const HDRestoreVaultScreen = require('./keychains/hd/restore-vault') const RevealSeedConfirmation = require('./keychains/hd/recover-seed/confirmation') -const AccountDropdowns = require('./components/account-dropdowns').AccountDropdowns module.exports = connect(mapStateToProps)(App) @@ -86,13 +83,29 @@ function mapStateToProps (state) { } App.prototype.render = function () { - var props = this.props - const { isLoading, loadingMessage, transForward, network } = props - const isLoadingNetwork = network === 'loading' && props.currentView.name !== 'config' - const loadMessage = loadingMessage || isLoadingNetwork ? - `Connecting to ${this.getNetworkName()}` : null + const { + currentView, + dispatch, + isLoading, + loadingMessage, + transForward, + network, + featureFlags, + } = this.props + const isLoadingNetwork = network === 'loading' && currentView.name !== 'config' + const loadMessage = loadingMessage || isLoadingNetwork + ? `Connecting to ${this.getNetworkName()}` + : null log.debug('Main ui render function') + if (!featureFlags.skipAnnounceBetaUI) { + return ( + h(NewUiAnnouncement, { + dispatch, + }) + ) + } + return ( h('.flex-column.full-height', { style: { @@ -102,12 +115,9 @@ App.prototype.render = function () { alignItems: 'center', }, }, [ - - // app bar - this.renderAppBar(), - this.renderNetworkDropdown(), - this.renderDropdown(), - + h(AppBar, { + ...this.props, + }), this.renderLoadingIndicator({ isLoading, isLoadingNetwork, loadMessage }), // panel content @@ -121,299 +131,6 @@ App.prototype.render = function () { ]) ) } - -App.prototype.renderAppBar = function () { - if (window.METAMASK_UI_TYPE === 'notification') { - return null - } - - const props = this.props - const state = this.state || {} - const isNetworkMenuOpen = state.isNetworkMenuOpen || false - const {isMascara, isOnboarding} = props - - // Do not render header if user is in mascara onboarding - if (isMascara && isOnboarding) { - return null - } - - // Do not render header if user is in mascara buy ether - if (isMascara && props.currentView.name === 'buyEth') { - return null - } - - return ( - - h('.full-width', { - height: '38px', - }, [ - - h('.app-header.flex-row.flex-space-between', { - style: { - alignItems: 'center', - visibility: props.isUnlocked ? 'visible' : 'none', - background: props.isUnlocked ? 'white' : 'none', - height: '38px', - position: 'relative', - zIndex: 12, - }, - }, [ - - h('div.left-menu-section', { - style: { - display: 'flex', - flexDirection: 'row', - alignItems: 'center', - }, - }, [ - - // mini logo - h('img', { - height: 24, - width: 24, - src: './images/icon-128.png', - }), - - h(NetworkIndicator, { - network: this.props.network, - provider: this.props.provider, - onClick: (event) => { - event.preventDefault() - event.stopPropagation() - this.setState({ isNetworkMenuOpen: !isNetworkMenuOpen }) - }, - }), - - ]), - - props.isUnlocked && h('div', { - style: { - display: 'flex', - flexDirection: 'row', - alignItems: 'center', - }, - }, [ - - props.isUnlocked && h(AccountDropdowns, { - style: {}, - enableAccountsSelector: true, - identities: this.props.identities, - selected: this.props.selectedAddress, - network: this.props.network, - keyrings: this.props.keyrings, - }, []), - - // hamburger - props.isUnlocked && h(SandwichExpando, { - className: 'sandwich-expando', - width: 16, - barHeight: 2, - padding: 0, - isOpen: state.isMainMenuOpen, - color: 'rgb(247,146,30)', - onClick: () => { - this.setState({ - isMainMenuOpen: !state.isMainMenuOpen, - }) - }, - }), - ]), - ]), - ]) - ) -} - -App.prototype.renderNetworkDropdown = function () { - const props = this.props - const { provider: { type: providerType, rpcTarget: activeNetwork } } = props - const rpcList = props.frequentRpcList - const state = this.state || {} - const isOpen = state.isNetworkMenuOpen - - return h(Dropdown, { - useCssTransition: true, - isOpen, - onClickOutside: (event) => { - const { classList } = event.target - const isNotToggleElement = [ - classList.contains('menu-icon'), - classList.contains('network-name'), - classList.contains('network-indicator'), - ].filter(bool => bool).length === 0 - // classes from three constituent nodes of the toggle element - - if (isNotToggleElement) { - this.setState({ isNetworkMenuOpen: false }) - } - }, - zIndex: 11, - style: { - position: 'absolute', - left: '2px', - top: '36px', - }, - innerStyle: { - padding: '2px 16px 2px 0px', - }, - }, [ - - h( - DropdownMenuItem, - { - key: 'main', - closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }), - onClick: () => props.dispatch(actions.setProviderType('mainnet')), - style: { - fontSize: '18px', - }, - }, - [ - h('.menu-icon.diamond'), - 'Main Ethereum Network', - providerType === 'mainnet' ? h('.check', '✓') : null, - ] - ), - - h( - DropdownMenuItem, - { - key: 'ropsten', - closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }), - onClick: () => props.dispatch(actions.setProviderType('ropsten')), - style: { - fontSize: '18px', - }, - }, - [ - h('.menu-icon.red-dot'), - 'Ropsten Test Network', - providerType === 'ropsten' ? h('.check', '✓') : null, - ] - ), - - h( - DropdownMenuItem, - { - key: 'kovan', - closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }), - onClick: () => props.dispatch(actions.setProviderType('kovan')), - style: { - fontSize: '18px', - }, - }, - [ - h('.menu-icon.hollow-diamond'), - 'Kovan Test Network', - providerType === 'kovan' ? h('.check', '✓') : null, - ] - ), - - h( - DropdownMenuItem, - { - key: 'rinkeby', - closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }), - onClick: () => props.dispatch(actions.setProviderType('rinkeby')), - style: { - fontSize: '18px', - }, - }, - [ - h('.menu-icon.golden-square'), - 'Rinkeby Test Network', - providerType === 'rinkeby' ? h('.check', '✓') : null, - ] - ), - - h( - DropdownMenuItem, - { - key: 'default', - closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }), - onClick: () => props.dispatch(actions.setProviderType('localhost')), - style: { - fontSize: '18px', - }, - }, - [ - h('i.fa.fa-question-circle.fa-lg.menu-icon'), - 'Localhost 8545', - activeNetwork === 'http://localhost:8545' ? h('.check', '✓') : null, - ] - ), - - this.renderCustomOption(props.provider), - this.renderCommonRpc(rpcList, props.provider), - - h( - DropdownMenuItem, - { - closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }), - onClick: () => this.props.dispatch(actions.showConfigPage()), - style: { - fontSize: '18px', - }, - }, - [ - h('i.fa.fa-question-circle.fa-lg.menu-icon'), - 'Custom RPC', - activeNetwork === 'custom' ? h('.check', '✓') : null, - ] - ), - - ]) -} - -App.prototype.renderDropdown = function () { - const state = this.state || {} - const isOpen = state.isMainMenuOpen - - return h(Dropdown, { - useCssTransition: true, - isOpen: isOpen, - zIndex: 11, - onClickOutside: (event) => { - const classList = event.target.classList - const parentClassList = event.target.parentElement.classList - - const isToggleElement = classList.contains('sandwich-expando') || - parentClassList.contains('sandwich-expando') - - if (isOpen && !isToggleElement) { - this.setState({ isMainMenuOpen: false }) - } - }, - style: { - position: 'absolute', - right: '2px', - top: '38px', - }, - innerStyle: {}, - }, [ - h(DropdownMenuItem, { - closeMenu: () => this.setState({ isMainMenuOpen: !isOpen }), - onClick: () => { this.props.dispatch(actions.showConfigPage()) }, - }, 'Settings'), - - h(DropdownMenuItem, { - closeMenu: () => this.setState({ isMainMenuOpen: !isOpen }), - onClick: () => { this.props.dispatch(actions.lockMetamask()) }, - }, 'Log Out'), - - h(DropdownMenuItem, { - closeMenu: () => this.setState({ isMainMenuOpen: !isOpen }), - onClick: () => { this.props.dispatch(actions.showInfoPage()) }, - }, 'Info/Help'), - - h(DropdownMenuItem, { - closeMenu: () => this.setState({ isMainMenuOpen: !isOpen }), - onClick: () => { - this.props.dispatch(actions.setFeatureFlag('betaUI', true, 'BETA_UI_NOTIFICATION_MODAL')) - }, - }, 'Try Beta!'), - ]) -} - App.prototype.renderLoadingIndicator = function ({ isLoading, isLoadingNetwork, loadMessage }) { const { isMascara } = this.props @@ -425,25 +142,6 @@ App.prototype.renderLoadingIndicator = function ({ isLoading, isLoadingNetwork, }) } -App.prototype.renderBackButton = function (style, justArrow = false) { - var props = this.props - return ( - h('.flex-row', { - key: 'leftArrow', - style: style, - onClick: () => props.dispatch(actions.goBackToInitView()), - }, [ - h('i.fa.fa-arrow-left.cursor-pointer'), - justArrow ? null : h('div.cursor-pointer', { - style: { - marginLeft: '3px', - }, - onClick: () => props.dispatch(actions.goBackToInitView()), - }, 'BACK'), - ]) - ) -} - App.prototype.renderPrimary = function () { log.debug('rendering primary') var props = this.props @@ -465,22 +163,6 @@ App.prototype.renderPrimary = function () { key: 'NoticeScreen', onConfirm: () => props.dispatch(actions.markNoticeRead(props.nextUnreadNotice)), }), - - !props.isInitialized && h('.flex-row.flex-center.flex-grow', [ - h('p.pointer', { - onClick: () => { - global.platform.openExtensionInBrowser() - props.dispatch(actions.setFeatureFlag('betaUI', true, 'BETA_UI_NOTIFICATION_MODAL')) - }, - style: { - fontSize: '0.8em', - color: '#aeaeae', - textDecoration: 'underline', - marginTop: '32px', - }, - }, 'Try Beta Version'), - ]), - ]) } else if (props.lostAccounts && props.lostAccounts.length > 0) { log.debug('rendering notice screen for lost accounts view.') @@ -580,31 +262,10 @@ App.prototype.renderPrimary = function () { case 'qr': log.debug('rendering show qr screen') - return h('div', { - style: { - position: 'absolute', - height: '100%', - top: '0px', - left: '0px', - }, - }, [ - h('i.fa.fa-arrow-left.fa-lg.cursor-pointer.color-orange', { - onClick: () => props.dispatch(actions.backToAccountDetail(props.selectedAddress)), - style: { - marginLeft: '10px', - marginTop: '50px', - }, - }), - h('div', { - style: { - position: 'absolute', - left: '44px', - width: '285px', - }, - }, [ - h(QrView, {key: 'qr'}), - ]), - ]) + return h(AccountQrScreen, { + key: 'account-qr', + selectedAddress: props.selectedAddress, + }) default: log.debug('rendering default, account detail screen') @@ -623,41 +284,6 @@ App.prototype.toggleMetamaskActive = function () { this.props.dispatch(actions.lockMetamask(false)) } } - -App.prototype.renderCustomOption = function (provider) { - const { rpcTarget, type } = provider - const props = this.props - - if (type !== 'rpc') return null - - // Concatenate long URLs - let label = rpcTarget - if (rpcTarget.length > 31) { - label = label.substr(0, 34) + '...' - } - - switch (rpcTarget) { - - case 'http://localhost:8545': - return null - - default: - return h( - DropdownMenuItem, - { - key: rpcTarget, - onClick: () => props.dispatch(actions.setRpcTarget(rpcTarget)), - closeMenu: () => this.setState({ isNetworkMenuOpen: false }), - }, - [ - h('i.fa.fa-question-circle.fa-lg.menu-icon'), - label, - h('.check', '✓'), - ] - ) - } -} - App.prototype.getNetworkName = function () { const { provider } = this.props const providerName = provider.type @@ -678,28 +304,3 @@ App.prototype.getNetworkName = function () { return name } - -App.prototype.renderCommonRpc = function (rpcList, provider) { - const props = this.props - const rpcTarget = provider.rpcTarget - - return rpcList.map((rpc) => { - if ((rpc === 'http://localhost:8545') || (rpc === rpcTarget)) { - return null - } else { - return h( - DropdownMenuItem, - { - key: `common${rpc}`, - closeMenu: () => this.setState({ isNetworkMenuOpen: false }), - onClick: () => props.dispatch(actions.setRpcTarget(rpc)), - }, - [ - h('i.fa.fa-question-circle.fa-lg.menu-icon'), - rpc, - rpcTarget === rpc ? h('.check', '✓') : null, - ] - ) - } - }) -} diff --git a/old-ui/app/components/app-bar.js b/old-ui/app/components/app-bar.js new file mode 100644 index 000000000..8ab647efd --- /dev/null +++ b/old-ui/app/components/app-bar.js @@ -0,0 +1,432 @@ +const PropTypes = require('prop-types') +const {Component} = require('react') +const h = require('react-hyperscript') +const actions = require('../../../ui/app/actions') +const SandwichExpando = require('sandwich-expando') +const {Dropdown} = require('./dropdown') +const {DropdownMenuItem} = require('./dropdown') +const NetworkIndicator = require('./network') +const {AccountDropdowns} = require('./account-dropdowns') + +const LOCALHOST_RPC_URL = 'http://localhost:8545' + +module.exports = class AppBar extends Component { + static defaultProps = { + selectedAddress: undefined, + } + + static propTypes = { + dispatch: PropTypes.func.isRequired, + frequentRpcList: PropTypes.array.isRequired, + isMascara: PropTypes.bool.isRequired, + isOnboarding: PropTypes.bool.isRequired, + identities: PropTypes.any.isRequired, + selectedAddress: PropTypes.string, + isUnlocked: PropTypes.bool.isRequired, + network: PropTypes.any.isRequired, + keyrings: PropTypes.any.isRequired, + provider: PropTypes.any.isRequired, + } + + static renderSpace () { + return ( + h('span', { + dangerouslySetInnerHTML: { + __html: ' ', + }, + }) + ) + } + + state = { + isNetworkMenuOpen: false, + } + + renderAppBar () { + if (window.METAMASK_UI_TYPE === 'notification') { + return null + } + + const props = this.props + const {isMascara, isOnboarding} = props + + // Do not render header if user is in mascara onboarding + if (isMascara && isOnboarding) { + return null + } + + // Do not render header if user is in mascara buy ether + if (isMascara && props.currentView.name === 'buyEth') { + return null + } + + return ( + h('div.app-bar', [ + this.renderAppBarNewUiNotice(), + this.renderAppBarAppHeader(), + ]) + ) + } + + renderAppBarNewUiNotice () { + const {dispatch} = this.props + + return ( + h('div.app-bar__new-ui-banner', { + style: { + height: '28px', + zIndex: 12, + }, + }, [ + 'Try the New MetaMask', + AppBar.renderSpace(), + h('span.banner__link', { + async onClick () { + await dispatch(actions.setFeatureFlag('betaUI', true)) + global.platform.openExtensionInBrowser() + }, + }, [ + 'Now', + ]), + AppBar.renderSpace(), + 'or', + AppBar.renderSpace(), + h('span.banner__link', { + onClick () { + global.platform.openWindow({ + url: 'https://medium.com/metamask/74dba32cc7f7', + }) + }, + }, [ + 'Learn More', + ]), + ]) + ) + } + + renderAppBarAppHeader () { + const { + identities, + selectedAddress, + isUnlocked, + network, + keyrings, + provider, + } = this.props + const { + isNetworkMenuOpen, + isMainMenuOpen, + } = this.state + + return ( + h('.full-width', { + style: { + display: 'flex', + flexDirection: 'column', + height: '38px', + }, + }, [ + h('.app-header.flex-row.flex-space-between', { + style: { + alignItems: 'center', + visibility: isUnlocked ? 'visible' : 'none', + background: isUnlocked ? 'white' : 'none', + height: '38px', + position: 'relative', + zIndex: 12, + }, + }, [ + h('div.left-menu-section', { + style: { + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + }, + }, [ + // mini logo + h('img', { + height: 24, + width: 24, + src: './images/icon-128.png', + }), + h(NetworkIndicator, { + network: network, + provider: provider, + onClick: (event) => { + event.preventDefault() + event.stopPropagation() + this.setState({ isNetworkMenuOpen: !isNetworkMenuOpen }) + }, + }), + ]), + isUnlocked && h('div', { + style: { + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + }, + }, [ + h(AccountDropdowns, { + style: {}, + enableAccountsSelector: true, + identities: identities, + selected: selectedAddress, + network, + keyrings, + }, []), + h(SandwichExpando, { + className: 'sandwich-expando', + width: 16, + barHeight: 2, + padding: 0, + isOpen: isMainMenuOpen, + color: 'rgb(247,146,30)', + onClick: () => { + this.setState({ + isMainMenuOpen: !isMainMenuOpen, + }) + }, + }), + ]), + ]), + ]) + ) + } + + renderNetworkDropdown () { + const { + dispatch, + frequentRpcList: rpcList, + provider, + } = this.props + const { + type: providerType, + rpcTarget: activeNetwork, + } = provider + const isOpen = this.state.isNetworkMenuOpen + + return h(Dropdown, { + useCssTransition: true, + isOpen, + onClickOutside: (event) => { + const { classList } = event.target + const isNotToggleElement = [ + classList.contains('menu-icon'), + classList.contains('network-name'), + classList.contains('network-indicator'), + ].filter(bool => bool).length === 0 + // classes from three constituent nodes of the toggle element + + if (isNotToggleElement) { + this.setState({ isNetworkMenuOpen: false }) + } + }, + zIndex: 11, + style: { + position: 'absolute', + left: '2px', + top: '64px', + }, + innerStyle: { + padding: '2px 16px 2px 0px', + }, + }, [ + h(DropdownMenuItem, { + key: 'main', + closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }), + onClick: () => dispatch(actions.setProviderType('mainnet')), + style: { + fontSize: '18px', + }, + }, [ + h('.menu-icon.diamond'), + 'Main Ethereum Network', + providerType === 'mainnet' + ? h('.check', '✓') + : null, + ]), + h(DropdownMenuItem, { + key: 'ropsten', + closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }), + onClick: () => dispatch(actions.setProviderType('ropsten')), + style: { + fontSize: '18px', + }, + }, [ + h('.menu-icon.red-dot'), + 'Ropsten Test Network', + providerType === 'ropsten' + ? h('.check', '✓') + : null, + ]), + h(DropdownMenuItem, { + key: 'kovan', + closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }), + onClick: () => dispatch(actions.setProviderType('kovan')), + style: { + fontSize: '18px', + }, + }, [ + h('.menu-icon.hollow-diamond'), + 'Kovan Test Network', + providerType === 'kovan' + ? h('.check', '✓') + : null, + ]), + h(DropdownMenuItem, { + key: 'rinkeby', + closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }), + onClick: () => dispatch(actions.setProviderType('rinkeby')), + style: { + fontSize: '18px', + }, + }, [ + h('.menu-icon.golden-square'), + 'Rinkeby Test Network', + providerType === 'rinkeby' + ? h('.check', '✓') + : null, + ]), + h(DropdownMenuItem, { + key: 'default', + closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }), + onClick: () => dispatch(actions.setProviderType('localhost')), + style: { + fontSize: '18px', + }, + }, [ + h('i.fa.fa-question-circle.fa-lg.menu-icon'), + 'Localhost 8545', + activeNetwork === LOCALHOST_RPC_URL + ? h('.check', '✓') + : null, + ]), + + this.renderCustomOption(provider), + this.renderCommonRpc(rpcList, provider), + + h(DropdownMenuItem, { + closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }), + onClick: () => dispatch(actions.showConfigPage()), + style: { + fontSize: '18px', + }, + }, [ + h('i.fa.fa-question-circle.fa-lg.menu-icon'), + 'Custom RPC', + activeNetwork === 'custom' + ? h('.check', '✓') + : null, + ]), + ]) + } + + renderCustomOption ({ rpcTarget, type }) { + const {dispatch} = this.props + + if (type !== 'rpc') { + return null + } + + // Concatenate long URLs + let label = rpcTarget + if (rpcTarget.length > 31) { + label = label.substr(0, 34) + '...' + } + + switch (rpcTarget) { + case LOCALHOST_RPC_URL: + return null + default: + return h(DropdownMenuItem, { + key: rpcTarget, + onClick: () => dispatch(actions.setRpcTarget(rpcTarget)), + closeMenu: () => this.setState({ isNetworkMenuOpen: false }), + }, [ + h('i.fa.fa-question-circle.fa-lg.menu-icon'), + label, + h('.check', '✓'), + ]) + } + } + + renderCommonRpc (rpcList, {rpcTarget}) { + const {dispatch} = this.props + + return rpcList.map((rpc) => { + if ((rpc === LOCALHOST_RPC_URL) || (rpc === rpcTarget)) { + return null + } else { + return h(DropdownMenuItem, { + key: `common${rpc}`, + closeMenu: () => this.setState({ isNetworkMenuOpen: false }), + onClick: () => dispatch(actions.setRpcTarget(rpc)), + }, [ + h('i.fa.fa-question-circle.fa-lg.menu-icon'), + rpc, + rpcTarget === rpc + ? h('.check', '✓') + : null, + ]) + } + }) + } + + renderDropdown () { + const {dispatch} = this.props + const isOpen = this.state.isMainMenuOpen + + return h(Dropdown, { + useCssTransition: true, + isOpen: isOpen, + zIndex: 11, + onClickOutside: (event) => { + const classList = event.target.classList + const parentClassList = event.target.parentElement.classList + + const isToggleElement = classList.contains('sandwich-expando') || + parentClassList.contains('sandwich-expando') + + if (isOpen && !isToggleElement) { + this.setState({ isMainMenuOpen: false }) + } + }, + style: { + position: 'absolute', + right: '2px', + top: '66px', + }, + innerStyle: {}, + }, [ + h(DropdownMenuItem, { + closeMenu: () => this.setState({ isMainMenuOpen: !isOpen }), + onClick: () => { dispatch(actions.showConfigPage()) }, + }, 'Settings'), + + h(DropdownMenuItem, { + closeMenu: () => this.setState({ isMainMenuOpen: !isOpen }), + onClick: () => { dispatch(actions.lockMetamask()) }, + }, 'Log Out'), + + h(DropdownMenuItem, { + closeMenu: () => this.setState({ isMainMenuOpen: !isOpen }), + onClick: () => { dispatch(actions.showInfoPage()) }, + }, 'Info/Help'), + + h(DropdownMenuItem, { + closeMenu: () => this.setState({ isMainMenuOpen: !isOpen }), + onClick: () => { + dispatch(actions.setFeatureFlag('betaUI', true, 'BETA_UI_NOTIFICATION_MODAL')) + }, + }, 'Try Beta!'), + ]) + } + + render () { + return h('div.full-width', [ + this.renderAppBar(), + this.renderNetworkDropdown(), + this.renderDropdown(), + ]) + } +} diff --git a/old-ui/app/components/qr-code.js b/old-ui/app/components/qr-code.js deleted file mode 100644 index 06b9aed9b..000000000 --- a/old-ui/app/components/qr-code.js +++ /dev/null @@ -1,79 +0,0 @@ -const Component = require('react').Component -const h = require('react-hyperscript') -const qrCode = require('qrcode-npm').qrcode -const inherits = require('util').inherits -const connect = require('react-redux').connect -const isHexPrefixed = require('ethereumjs-util').isHexPrefixed -const CopyButton = require('./copyButton') - -module.exports = connect(mapStateToProps)(QrCodeView) - -function mapStateToProps (state) { - return { - Qr: state.appState.Qr, - buyView: state.appState.buyView, - warning: state.appState.warning, - } -} - -inherits(QrCodeView, Component) - -function QrCodeView () { - Component.call(this) -} - -QrCodeView.prototype.render = function () { - const props = this.props - const Qr = props.Qr - const address = `${isHexPrefixed(Qr.data) ? 'ethereum:' : ''}${Qr.data}` - const qrImage = qrCode(4, 'M') - qrImage.addData(address) - qrImage.make() - return h('.main-container.flex-column', { - key: 'qr', - style: { - justifyContent: 'center', - paddingBottom: '45px', - paddingLeft: '45px', - paddingRight: '45px', - alignItems: 'center', - }, - }, [ - Array.isArray(Qr.message) ? h('.message-container', this.renderMultiMessage()) : h('.qr-header', Qr.message), - - this.props.warning ? this.props.warning && h('span.error.flex-center', { - style: { - textAlign: 'center', - width: '229px', - height: '82px', - }, - }, - this.props.warning) : null, - - h('#qr-container.flex-column', { - style: { - marginTop: '25px', - marginBottom: '15px', - }, - dangerouslySetInnerHTML: { - __html: qrImage.createTableTag(4), - }, - }), - h('.flex-row', [ - h('h3.ellip-address', { - style: { - width: '247px', - }, - }, Qr.data), - h(CopyButton, { - value: Qr.data, - }), - ]), - ]) -} - -QrCodeView.prototype.renderMultiMessage = function () { - var Qr = this.props.Qr - var multiMessage = Qr.message.map((message) => h('.qr-message', message)) - return multiMessage -} diff --git a/old-ui/app/components/shapeshift-form.js b/old-ui/app/components/shapeshift-form.js index 97068db0a..14de309ab 100644 --- a/old-ui/app/components/shapeshift-form.js +++ b/old-ui/app/components/shapeshift-form.js @@ -3,7 +3,6 @@ const h = require('react-hyperscript') const inherits = require('util').inherits const connect = require('react-redux').connect const actions = require('../../../ui/app/actions') -const Qr = require('./qr-code') const isValidAddress = require('../util').isValidAddress module.exports = connect(mapStateToProps)(ShapeshiftForm) @@ -11,7 +10,6 @@ function mapStateToProps (state) { return { warning: state.appState.warning, isSubLoading: state.appState.isSubLoading, - qrRequested: state.appState.qrRequested, } } @@ -23,7 +21,7 @@ function ShapeshiftForm () { } ShapeshiftForm.prototype.render = function () { - return this.props.qrRequested ? h(Qr, {key: 'qr'}) : this.renderMain() + return this.renderMain() } ShapeshiftForm.prototype.renderMain = function () { diff --git a/old-ui/app/css/index.css b/old-ui/app/css/index.css index 7af713336..d209b4754 100644 --- a/old-ui/app/css/index.css +++ b/old-ui/app/css/index.css @@ -720,7 +720,131 @@ div.message-container > div:first-child { transform: scale(1.1); } -//Notification Modal +.new-ui-announcement { + display: flex; + flex-direction: column; + height: 100%; + background: white; + color: #4D4D4D; + font-family: Roboto, Arial, sans-serif; + padding: 1.5rem; +} + +.new-ui-announcement__announcement-header { + display: flex; + flex-direction: row; + justify-content: space-between; + padding-bottom: 1rem; +} + +.new-ui-announcement__announcement-header a.close { + cursor: pointer; + font-size: 32px; + line-height: 17px; +} + +.new-ui-announcement__announcement-header a.close:hover { + color: inherit; +} + +.new-ui-announcement__announcement-header h1 { + color: #33A4E7; + text-transform: uppercase; + font-size: 18px; + font-weight: 400; +} + +.new-ui-announcement__body { + display: flex; + flex: 1; + flex-direction: column; + font-size: 10.5pt; + font-weight: 300; +} + +.new-ui-announcement__body h1 { + font-size: 22px; + font-weight: 600; + padding-bottom: 1rem; +} + +.new-ui-announcement__body a { + color: #33A4E7; +} + +.new-ui-announcement__body .updates-list { + padding: .5rem 1rem; +} + +.new-ui-announcement__body .updates-list h2 { + font-weight: 600; +} + +.new-ui-announcement__body .updates-list ul { + list-style: disc inside; +} + +.new-ui-announcement__footer { + display: flex; + flex-direction: column; + align-items: center; +} + +.new-ui-announcement__footer h1 { + font-family: inherit; + font-weight: 600; +} + +.new-ui-announcement__footer button:hover { + transform: none; +} + +.new-ui-announcement__footer button.positive { + padding: 1rem; + margin: 1rem; + background: #33A4E7; + color: white; + text-transform: uppercase; + box-shadow: none; + border-radius: 5px; + font-family: inherit; + font-size: 13px; + font-weight: 400; + width: 90%; +} + +.new-ui-announcement__footer button.negative { + margin: 0; + padding: 0; + background: white; + color: #33A4E7; + font-family: inherit; + font-size: 13px; + font-weight: 400; + box-shadow: none; +} + +.app-bar { + width: 100%; + display: flex; + flex-direction: column; +} + +.app-bar__new-ui-banner { + background: #33A4E7; + color: white; + font-size: 12px; + line-height: 12px; + padding: 8px; + font-family: Roboto, Arial, sans-serif; + font-weight: 400; + width: 100%; +} + +.banner__link { + cursor: pointer; + text-decoration: underline; +} .notification-modal-wrapper { display: flex; @@ -812,4 +936,4 @@ div.message-container > div:first-child { .notification-modal__link { color: #2f9ae0; -}
\ No newline at end of file +} diff --git a/old-ui/app/new-ui-annoucement.js b/old-ui/app/new-ui-annoucement.js new file mode 100644 index 000000000..59b126279 --- /dev/null +++ b/old-ui/app/new-ui-annoucement.js @@ -0,0 +1,85 @@ +const PropTypes = require('prop-types') +const {PureComponent} = require('react') +const h = require('react-hyperscript') +const actions = require('../../ui/app/actions') + +module.exports = class NewUiAnnouncement extends PureComponent { + static propTypes = { + dispatch: PropTypes.func.isRequired, + }; + + close = async () => { + await this.props.dispatch(actions.setFeatureFlag('skipAnnounceBetaUI', true)) + } + + switchToNewUi = async () => { + const flag = 'betaUI' + const enabled = true + await this.props.dispatch(actions.setFeatureFlag( + flag, + enabled, + )) + await this.close() + global.platform.openExtensionInBrowser() + } + + render () { + return ( + h('div.new-ui-announcement', [ + h('section.new-ui-announcement__announcement-header', [ + h('h1', 'Announcement'), + h('a.close', { + onClick: this.close, + }, '×'), + ]), + h('section.new-ui-announcement__body', [ + h('h1', 'A New Version of MetaMask'), + h('p', [ + "We're excited to announce a brand-new version of MetaMask with enhanced features and functionality.", + ]), + h('div.updates-list', [ + h('h2', 'Updates include'), + h('ul', [ + h('li', 'New user interface'), + h('li', 'Full-screen mode'), + h('li', 'Better token support'), + h('li', 'Better gas controls'), + h('li', 'Advanced features for developers'), + h('li', 'New confirmation screens'), + h('li', 'And more!'), + ]), + ]), + h('p', [ + 'You can still use the current version of MetaMask. The new version is still in beta, ' + + 'however we encourage you to try it out as we transition into this exciting new update.', + h('span', { + dangerouslySetInnerHTML: { + __html: ' ', + }, + }), + h('a', { + href: 'https://medium.com/metamask/74dba32cc7f7', + onClick ({target}) { + const url = target.href + global.platform.openWindow({ + url, + }) + }, + }, [ + 'Learn more.', + ]), + ]), + ]), + h('section.new-ui-announcement__footer', [ + h('h1', 'Ready to try the new MetaMask?'), + h('button.positive', { + onClick: this.switchToNewUi, + }, 'Try it now'), + h('button.negative', { + onClick: this.close, + }, 'No thanks, maybe later'), + ]), + ]) + ) + } +} diff --git a/test/e2e/beta/from-import-beta-ui.spec.js b/test/e2e/beta/from-import-beta-ui.spec.js index 32f57b157..06e669e5b 100644 --- a/test/e2e/beta/from-import-beta-ui.spec.js +++ b/test/e2e/beta/from-import-beta-ui.spec.js @@ -12,9 +12,11 @@ const { } = require('../func') const { checkBrowserForConsoleErrors, + closeAllWindowHandlesExcept, verboseReportOnFailure, findElement, findElements, + loadExtension, } = require('./helpers') @@ -25,6 +27,7 @@ describe('Using MetaMask with an existing account', function () { const testSeedPhrase = 'phrase upgrade clock rough situate wedding elder clever doctor stamp excess tent' const testAddress = '0xE18035BF8712672935FDB4e5e431b1a0183d2DFC' const testPrivateKey2 = '14abe6f4aab7f9f626fe981c864d0adeb5685f289ac9270c27b8fd790b4235d6' + const tinyDelayMs = 500 const regularDelayMs = 1000 const largeDelayMs = regularDelayMs * 2 @@ -74,37 +77,51 @@ describe('Using MetaMask with an existing account', function () { describe('New UI setup', async function () { it('switches to first tab', async function () { + await delay(tinyDelayMs) const [firstTab] = await driver.getAllWindowHandles() await driver.switchTo().window(firstTab) await delay(regularDelayMs) }) - it('use the local network', async function () { - const networkSelector = await findElement(driver, By.css('#network_component')) - await networkSelector.click() - await delay(regularDelayMs) - - const [localhost] = await findElements(driver, By.xpath(`//li[contains(text(), 'Localhost')]`)) - await localhost.click() - await delay(regularDelayMs) - }) - it('selects the new UI option', async () => { - const button = await findElement(driver, By.xpath("//p[contains(text(), 'Try Beta Version')]")) + try { + const overlay = await findElement(driver, By.css('.full-flex-height')) + await driver.wait(until.stalenessOf(overlay)) + } catch (e) {} + + const button = await findElement(driver, By.xpath("//button[contains(text(), 'Try it now')]")) await button.click() await delay(regularDelayMs) // Close all other tabs - const [oldUi, infoPage, newUi] = await driver.getAllWindowHandles() - - const newUiOrInfoPage = newUi || infoPage - await driver.switchTo().window(oldUi) - await driver.close() - if (infoPage !== newUiOrInfoPage) { - await driver.switchTo().window(infoPage) - await driver.close() + const [tab0, tab1, tab2] = await driver.getAllWindowHandles() + await driver.switchTo().window(tab0) + await delay(tinyDelayMs) + + let selectedUrl = await driver.getCurrentUrl() + await delay(tinyDelayMs) + if (tab0 && selectedUrl.match(/popup.html/)) { + await closeAllWindowHandlesExcept(driver, tab0) + } else if (tab1) { + await driver.switchTo().window(tab1) + selectedUrl = await driver.getCurrentUrl() + await delay(tinyDelayMs) + if (selectedUrl.match(/popup.html/)) { + await closeAllWindowHandlesExcept(driver, tab1) + } else if (tab2) { + await driver.switchTo().window(tab2) + selectedUrl = await driver.getCurrentUrl() + selectedUrl.match(/popup.html/) && await closeAllWindowHandlesExcept(driver, tab2) + } + } else { + throw new Error('popup.html not found') } - await driver.switchTo().window(newUiOrInfoPage) + await delay(regularDelayMs) + const [appTab] = await driver.getAllWindowHandles() + await driver.switchTo().window(appTab) + await delay(tinyDelayMs) + + await loadExtension(driver, extensionId) await delay(regularDelayMs) const continueBtn = await findElement(driver, By.css('.welcome-screen__button')) @@ -208,6 +225,16 @@ describe('Using MetaMask with an existing account', function () { }) describe('Add an account', () => { + it('switches to localhost', async () => { + const networkDropdown = await findElement(driver, By.css('.network-name')) + await networkDropdown.click() + await delay(regularDelayMs) + + const [localhost] = await findElements(driver, By.xpath(`//span[contains(text(), 'Localhost')]`)) + await localhost.click() + await delay(largeDelayMs * 2) + }) + it('choose Create Account from the account menu', async () => { await driver.findElement(By.css('.account-menu__icon')).click() await delay(regularDelayMs) diff --git a/test/e2e/beta/metamask-beta-ui.spec.js b/test/e2e/beta/metamask-beta-ui.spec.js index ca1977c5a..98132e68c 100644 --- a/test/e2e/beta/metamask-beta-ui.spec.js +++ b/test/e2e/beta/metamask-beta-ui.spec.js @@ -75,30 +75,11 @@ describe('MetaMask', function () { }) describe('New UI setup', async function () { - let networkSelector it('switches to first tab', async function () { + await delay(tinyDelayMs) const [firstTab] = await driver.getAllWindowHandles() await driver.switchTo().window(firstTab) await delay(regularDelayMs) - try { - networkSelector = await findElement(driver, By.css('#network_component')) - } catch (e) { - await loadExtension(driver, extensionId) - await delay(largeDelayMs * 2) - networkSelector = await findElement(driver, By.css('#network_component')) - } - await delay(regularDelayMs) - }) - - it('uses the local network', async function () { - await networkSelector.click() - await delay(regularDelayMs) - - const networks = await findElements(driver, By.css('.dropdown-menu-item')) - const localhost = networks[4] - await driver.wait(until.elementTextMatches(localhost, /Localhost/)) - await localhost.click() - await delay(regularDelayMs) }) it('selects the new UI option', async () => { @@ -107,27 +88,40 @@ describe('MetaMask', function () { await driver.wait(until.stalenessOf(overlay)) } catch (e) {} - const button = await findElement(driver, By.xpath("//p[contains(text(), 'Try Beta Version')]")) + const button = await findElement(driver, By.xpath("//button[contains(text(), 'Try it now')]")) await button.click() await delay(regularDelayMs) // Close all other tabs - const [oldUi, tab1, tab2] = await driver.getAllWindowHandles() - await driver.switchTo().window(oldUi) - await driver.close() + const [tab0, tab1, tab2] = await driver.getAllWindowHandles() + await driver.switchTo().window(tab0) + await delay(tinyDelayMs) - await driver.switchTo().window(tab1) - const tab1Url = await driver.getCurrentUrl() - if (tab1Url.match(/metamask.io/)) { - await driver.switchTo().window(tab1) - await driver.close() - await driver.switchTo().window(tab2) - } else if (tab2) { - await driver.switchTo().window(tab2) - await driver.close() + let selectedUrl = await driver.getCurrentUrl() + await delay(tinyDelayMs) + if (tab0 && selectedUrl.match(/popup.html/)) { + await closeAllWindowHandlesExcept(driver, tab0) + } else if (tab1) { await driver.switchTo().window(tab1) + selectedUrl = await driver.getCurrentUrl() + await delay(tinyDelayMs) + if (selectedUrl.match(/popup.html/)) { + await closeAllWindowHandlesExcept(driver, tab1) + } else if (tab2) { + await driver.switchTo().window(tab2) + selectedUrl = await driver.getCurrentUrl() + selectedUrl.match(/popup.html/) && await closeAllWindowHandlesExcept(driver, tab2) + } + } else { + throw new Error('popup.html not found') } await delay(regularDelayMs) + const [appTab] = await driver.getAllWindowHandles() + await driver.switchTo().window(appTab) + await delay(tinyDelayMs) + + await loadExtension(driver, extensionId) + await delay(regularDelayMs) const continueBtn = await findElement(driver, By.css('.welcome-screen__button')) await continueBtn.click() @@ -389,6 +383,16 @@ describe('MetaMask', function () { await delay(regularDelayMs) }) + it('switches to localhost', async () => { + const networkDropdown = await findElement(driver, By.css('.network-name')) + await networkDropdown.click() + await delay(regularDelayMs) + + const [localhost] = await findElements(driver, By.xpath(`//span[contains(text(), 'Localhost')]`)) + await localhost.click() + await delay(largeDelayMs * 2) + }) + it('balance renders', async () => { const balance = await findElement(driver, By.css('.balance-display .token-amount')) await driver.wait(until.elementTextMatches(balance, /100.+ETH/)) diff --git a/test/e2e/metamask.spec.js b/test/e2e/metamask.spec.js index b6efae5b3..ac7600f09 100644 --- a/test/e2e/metamask.spec.js +++ b/test/e2e/metamask.spec.js @@ -59,6 +59,13 @@ describe('Metamask popup page', function () { await driver.switchTo().window(windowHandles[0]) }) + it('does not select the new UI option', async () => { + await delay(300) + const button = await driver.findElement(By.xpath("//button[contains(text(), 'No thanks, maybe later')]")) + await button.click() + await delay(1000) + }) + it('sets provider type to localhost', async function () { await delay(300) await setProviderType('localhost') @@ -133,9 +140,9 @@ describe('Metamask popup page', function () { }) it('adds a second account', async function () { - await driver.findElement(By.css('#app-content > div > div.full-width > div > div:nth-child(2) > span > div')).click() + await driver.findElement(By.css('div.full-width > div > div:nth-child(2) > span > div')).click() await delay(300) - await driver.findElement(By.css('#app-content > div > div.full-width > div > div:nth-child(2) > span > div > div > span > div > li:nth-child(3) > span')).click() + await driver.findElement(By.css('div.full-width > div > div:nth-child(2) > span > div > div > span > div > li:nth-child(3) > span')).click() }) it('shows account address', async function () { @@ -146,7 +153,7 @@ describe('Metamask popup page', function () { it('logs out of the vault', async () => { await driver.findElement(By.css('.sandwich-expando')).click() await delay(500) - const logoutButton = await driver.findElement(By.css('#app-content > div > div:nth-child(3) > span > div > li:nth-child(3)')) + const logoutButton = await driver.findElement(By.css('.menu-droppo > li:nth-child(3)')) assert.equal(await logoutButton.getText(), 'Log Out') await logoutButton.click() }) @@ -178,7 +185,7 @@ describe('Metamask popup page', function () { it('logs out', async function () { await driver.findElement(By.css('.sandwich-expando')).click() await delay(200) - const logOut = await driver.findElement(By.css('#app-content > div > div:nth-child(3) > span > div > li:nth-child(3)')) + const logOut = await driver.findElement(By.css('.menu-droppo > li:nth-child(3)')) assert.equal(await logOut.getText(), 'Log Out') await logOut.click() await delay(300) diff --git a/test/integration/lib/first-time.js b/test/integration/lib/first-time.js index 052d89518..8cacd7f14 100644 --- a/test/integration/lib/first-time.js +++ b/test/integration/lib/first-time.js @@ -27,6 +27,11 @@ async function runFirstTimeUsageTest(assert, done) { const app = $('#app-content') + // Selects new ui + const tryNewUIButton = (await findAsync(app, 'button.negative'))[0] + tryNewUIButton.click() + await timeout() + // recurse notices while (true) { const button = await findAsync(app, 'button') |