From b8dec6827127ebd5a1fba19a389a361ebc3a9a4d Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 7 Mar 2018 12:47:33 -0330 Subject: [PATCH 01/16] Make new-ui create password screen responsive. --- .../app/first-time/create-password-screen.js | 2 +- mascara/src/app/first-time/index.css | 56 +++++++++++++++++++ .../css/itcss/components/newui-sections.scss | 24 -------- 3 files changed, 57 insertions(+), 25 deletions(-) diff --git a/mascara/src/app/first-time/create-password-screen.js b/mascara/src/app/first-time/create-password-screen.js index 450d6a479..ff56542d7 100644 --- a/mascara/src/app/first-time/create-password-screen.js +++ b/mascara/src/app/first-time/create-password-screen.js @@ -60,7 +60,7 @@ class CreatePasswordScreen extends Component { : (
-
+
Date: Wed, 7 Mar 2018 14:50:23 -0330 Subject: [PATCH 02/16] Change fonts in new-ui onboarding to Roboto, with weight 400. --- mascara/src/app/first-time/index.css | 54 ++++++++++++++++------------ 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/mascara/src/app/first-time/index.css b/mascara/src/app/first-time/index.css index f59eb4ce1..e8a50d988 100644 --- a/mascara/src/app/first-time/index.css +++ b/mascara/src/app/first-time/index.css @@ -1,3 +1,10 @@ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + src: local('Roboto'), local('Roboto-Regular'), url('/fonts/Roboto/Roboto-Regular.ttf') format('truetype'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} .first-time-flow { width: 100vw; @@ -6,6 +13,7 @@ display: flex; justify-content: center; flex: 1 0 auto; + font-weight: 400; } .alpha-warning { @@ -180,11 +188,11 @@ color: #1B344D; font-size: 16px; line-height: 23px; - font-family: Montserrat UltraLight; + font-family: Roboto; } .buy-ether__small-body-text { - font-family: Montserrat UltraLight; + font-family: Roboto; height: 14px; color: #757575; font-size: 12px; @@ -212,7 +220,7 @@ height: 334px; overflow-y: auto; color: #757575; - font-family: Montserrat UltraLight; + font-family: Roboto; font-size: 12px; line-height: 15px; text-align: justify; @@ -237,7 +245,7 @@ color: #5B5D67; font-size: 16px; line-height: 23px; - font-family: Montserrat UltraLight; + font-family: Roboto; } .backup-phrase__secret { @@ -255,7 +263,7 @@ .backup-phrase__secret-words { width: 310px; color: #5B5D67; - font-family: Montserrat Light; + font-family: Roboto; font-size: 20px; line-height: 26px; text-align: center; @@ -284,7 +292,7 @@ background: none; box-shadow: none; color: #FFFFFF; - font-family: Montserrat Regular; + font-family: Roboto; font-size: 12px; font-weight: bold; line-height: 15px; @@ -338,7 +346,7 @@ button.backup-phrase__reveal-button:hover { .backup-phrase__confirm-seed-option { color: #5B5D67; - font-family: Montserrat Light; + font-family: Roboto; font-size: 16px; line-height: 21px; background-color: #E7E7E7; @@ -360,7 +368,7 @@ button.backup-phrase__confirm-seed-option:hover { .import-account__faq-link { font-size: 18px; line-height: 23px; - font-family: Montserrat Light; + font-family: Roboto; } .import-account__selector-label { @@ -375,7 +383,7 @@ button.backup-phrase__confirm-seed-option:hover { background-color: #FFFFFF; margin-top: 14px; color: #5B5D67; - font-family: Montserrat Light; + font-family: Roboto; font-size: 18px; line-height: 23px; padding: 14px 21px; @@ -390,7 +398,7 @@ button.backup-phrase__confirm-seed-option:hover { font-size: 18px; line-height: 23px; margin-top: 21px; - font-family: Montserrat UltraLight; + font-family: Roboto; } .import-account__input-wrapper { @@ -436,7 +444,7 @@ button.backup-phrase__confirm-seed-option:hover { border: 1px solid #1B344D; border-radius: 4px; color: #1B344D; - font-family: Montserrat Light; + font-family: Roboto; font-size: 18px; display: flex; flex-flow: column nowrap; @@ -453,7 +461,7 @@ button.backup-phrase__confirm-seed-option:hover { .import-account__file-name { color: #000000; - font-family: Montserrat Light; + font-family: Roboto; font-size: 18px; line-height: 23px; margin-left: 22px; @@ -474,7 +482,7 @@ button.backup-phrase__confirm-seed-option:hover { .buy-ether__content-headline { color: #1B344D; - font-family: Montserrat Light; + font-family: Roboto; font-size: 18px; line-height: 23px; } @@ -503,7 +511,7 @@ button.backup-phrase__confirm-seed-option:hover { align-items: center; padding: 20px 0; color: #9B9B9B; - font-family: Montserrat Light; + font-family: Roboto; font-size: 14px; line-height: 18px; cursor: pointer; @@ -538,7 +546,7 @@ button.backup-phrase__confirm-seed-option:hover { .buy-ether__button-separator-text { font-size: 20px; line-height: 26px; - font-family: Montserrat Light; + font-family: Roboto; margin: 35px 0 14px 30px; display: flex; flex-flow: column nowrap; @@ -550,7 +558,7 @@ button.backup-phrase__confirm-seed-option:hover { color: #1B344D !important; font-size: 14px !important; line-height: 18px !important; - font-family: Montserrat UltraLight !important; + font-family: Roboto; } .buy-ether__action-content-wrapper { @@ -608,7 +616,7 @@ button.first-time-flow__button:hover { color: #1B344D; font-size: 20px; line-height: 26px; - font-family: Montserrat Light; + font-family: Roboto; text-align: center; margin: 35px 0 14px; background-color: transparent; @@ -660,7 +668,7 @@ button.first-time-flow__button--tertiary:hover { font-size: 20px; line-height: 26px; text-align: center; - font-family: Montserrat UltraLight; + font-family: Roboto; } .icon { @@ -708,7 +716,7 @@ button.first-time-flow__button--tertiary:hover { .shapeshift-form__deposit-instruction { color: #757575; color: rgba(0, 0, 0, 0.45); - font-family: Montserrat Light; + font-family: Roboto; font-weight: 300; line-height: 19px; padding-bottom: 6px; @@ -725,7 +733,7 @@ button.first-time-flow__button--tertiary:hover { width: 100%; height: 45px; line-height: 44px; - font-family: Montserrat Light; + font-family: Roboto; } .shapeshift-form__address-input-label { @@ -734,7 +742,7 @@ button.first-time-flow__button--tertiary:hover { font-weight: 500; line-height: 18px; padding-bottom: 6px; - font-family: Montserrat Light; + font-family: Roboto; } .shapeshift-form__address-input { @@ -753,7 +761,7 @@ button.first-time-flow__button--tertiary:hover { .shapeshift-form__address-input-error-message { color: #FF001F; - font-family: Montserrat Light; + font-family: Roboto; font-size: 12px; height: 24px; line-height: 18px; @@ -763,7 +771,7 @@ button.first-time-flow__button--tertiary:hover { display: flex; flex-flow: row wrap; color: #9B9B9B; - font-family: Montserrat Light; + font-family: Roboto; font-size: 10px; line-height: 16px; } From 6c400c2e925053784befa199f734b08f14e3b404 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 7 Mar 2018 22:37:53 -0330 Subject: [PATCH 03/16] Update first time flow button fonts, and first-time-flow default font, to Roboto. --- mascara/src/app/first-time/index.css | 2 ++ ui/app/actions.js | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/mascara/src/app/first-time/index.css b/mascara/src/app/first-time/index.css index e8a50d988..9f4ad0c83 100644 --- a/mascara/src/app/first-time/index.css +++ b/mascara/src/app/first-time/index.css @@ -14,6 +14,7 @@ justify-content: center; flex: 1 0 auto; font-weight: 400; + font-family: Roboto; } .alpha-warning { @@ -592,6 +593,7 @@ button.backup-phrase__confirm-seed-option:hover { color: #FFFFFF; font-size: 20px; font-weight: 500; + font-family: Roboto; line-height: 26px; text-align: center; text-transform: uppercase; diff --git a/ui/app/actions.js b/ui/app/actions.js index 8b1480a79..664667e6c 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -749,7 +749,7 @@ function updateTransaction (txData) { function updateAndApproveTx (txData) { log.info('actions: updateAndApproveTx: ' + JSON.stringify(txData)) return (dispatch) => { - log.debug(`actions calling background.updateAndApproveTx`) + log.debug(`actions calling background.updateAndApproveTx.`) background.updateAndApproveTransaction(txData, (err) => { dispatch(actions.hideLoadingIndication()) dispatch(actions.updateTransactionParams(txData.id, txData.txParams)) From 91c890041c685db8ff7f7ac87009225fa31b3042 Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 8 Mar 2018 14:01:21 -0330 Subject: [PATCH 04/16] Add welcome screen to new-ui browser first time flow. --- .../app/first-time/create-password-screen.js | 17 ++++-- mascara/src/app/first-time/index.css | 18 +++++- ui/app/actions.js | 8 +++ ui/app/app.js | 21 ++++++- ui/app/css/itcss/components/index.scss | 3 + .../css/itcss/components/welcome-screen.scss | 47 +++++++++++++++ ui/app/reducers/metamask.js | 6 ++ ui/app/welcome-screen.js | 57 +++++++++++++++++++ 8 files changed, 165 insertions(+), 12 deletions(-) create mode 100644 ui/app/css/itcss/components/welcome-screen.scss create mode 100644 ui/app/welcome-screen.js diff --git a/mascara/src/app/first-time/create-password-screen.js b/mascara/src/app/first-time/create-password-screen.js index ff56542d7..b56c183e6 100644 --- a/mascara/src/app/first-time/create-password-screen.js +++ b/mascara/src/app/first-time/create-password-screen.js @@ -2,6 +2,7 @@ import EventEmitter from 'events' import React, { Component } from 'react' import PropTypes from 'prop-types' import {connect} from 'react-redux' +import classnames from 'classnames' import {createNewVaultAndKeychain} from '../../../../ui/app/actions' import LoadingScreen from './loading-screen' import Breadcrumbs from './breadcrumbs' @@ -14,6 +15,7 @@ class CreatePasswordScreen extends Component { goToImportWithSeedPhrase: PropTypes.func.isRequired, goToImportAccount: PropTypes.func.isRequired, next: PropTypes.func.isRequired, + isMascara: PropTypes.bool.isRequired, } state = { @@ -53,14 +55,17 @@ class CreatePasswordScreen extends Component { } render () { - const { isLoading, goToImportWithSeedPhrase } = this.props - + const { isLoading, goToImportWithSeedPhrase, isMascara } = this.props + // return isLoading ? : (
-
-
+
+ {isMascara &&
It allows you to hold ether & tokens, and interact with decentralized applications.
-
+
}
Create Password @@ -127,7 +132,7 @@ class CreatePasswordScreen extends Component { } export default connect( - ({ appState: { isLoading } }) => ({ isLoading }), + ({ appState: { isLoading }, metamask: { isMascara } }) => ({ isLoading, isMascara }), dispatch => ({ createAccount: password => dispatch(createNewVaultAndKeychain(password)), }) diff --git a/mascara/src/app/first-time/index.css b/mascara/src/app/first-time/index.css index a1e1a8200..9cc9faeb3 100644 --- a/mascara/src/app/first-time/index.css +++ b/mascara/src/app/first-time/index.css @@ -8,16 +8,27 @@ flex: 1 0 auto; } -.alpha-warning { +.alpha-warning, +.alpha-warning-welcome-screen { background: #f7861c; color: #fff; line-height: 2em; padding-left: 10vw; } -.first-view-main { +.alpha-warning-welcome-screen { + padding-left: 0; + text-align: center; +} + +.first-view-main, +.first-view-main__mascara { display: flex; flex-direction: row-reverse; + justify-content: center; +} + +.first-view-main__mascara { justify-content: space-between; } @@ -99,7 +110,8 @@ width: initial !important; } - .alpha-warning { + .alpha-warning, + .alpha-warning-welcome-screen { line-height: 1em; padding: 8px 12px; } diff --git a/ui/app/actions.js b/ui/app/actions.js index 8b1480a79..e1d000f72 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -75,6 +75,8 @@ var actions = { resetAccount, showNewVaultSeed: showNewVaultSeed, showInfoPage: showInfoPage, + CLOSE_WELCOME_SCREEN: 'CLOSE_WELCOME_SCREEN', + closeWelcomeScreen, // seed recovery actions REVEAL_SEED_CONFIRMATION: 'REVEAL_SEED_CONFIRMATION', revealSeedConfirmation: revealSeedConfirmation, @@ -905,6 +907,12 @@ function showNewVaultSeed (seed) { } } +function closeWelcomeScreen () { + return { + type: actions.CLOSE_WELCOME_SCREEN, + } +} + function backToUnlockView () { return { type: actions.BACK_TO_UNLOCK_VIEW, diff --git a/ui/app/app.js b/ui/app/app.js index 4e6da24c3..11b761639 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -12,6 +12,8 @@ const MascaraBuyEtherScreen = require('../../mascara/src/app/first-time/buy-ethe const OldUIInitializeMenuScreen = require('./first-time/init-menu') const InitializeMenuScreen = MascaraFirstTime const NewKeyChainScreen = require('./new-keychain') +const WelcomeScreen = require('./welcome-screen').default + // accounts const MainContainer = require('./main-container') const SendTransactionScreen2 = require('./components/send/send-v2-container') @@ -91,6 +93,7 @@ function mapStateToProps (state) { betaUI: state.metamask.featureFlags.betaUI, isRevealingSeedWords: state.metamask.isRevealingSeedWords, Qr: state.appState.Qr, + welcomeScreenSeen: state.metamask.welcomeScreenSeen, // state needed to get account dropdown temporarily rendering from app bar identities, @@ -244,6 +247,7 @@ App.prototype.renderAppBar = function () { isInitialized, betaUI, isPopup, + welcomeScreenSeen, } = this.props if (window.METAMASK_UI_TYPE === 'notification') { @@ -269,7 +273,7 @@ App.prototype.renderAppBar = function () { style: {}, }, [ - h('.app-header.flex-row.flex-space-between', { + (isInitialized || welcomeScreenSeen || isPopup || !betaUI) && h('.app-header.flex-row.flex-space-between', { className: classnames({ 'app-header--initialized': !isOnboarding, }), @@ -324,8 +328,12 @@ App.prototype.renderAppBar = function () { ]), ]), - !isInitialized && !isPopup && betaUI && h('h2.alpha-warning', - 'Please be aware that this version is still under development'), + !isInitialized && !isPopup && betaUI && h('h2', { + className: classnames({ + 'alpha-warning': welcomeScreenSeen, + 'alpha-warning-welcome-screen': !welcomeScreenSeen, + }), + }, 'Please be aware that this version is still under development'), ]) ) @@ -369,11 +377,18 @@ App.prototype.renderPrimary = function () { isOnboarding, betaUI, isRevealingSeedWords, + welcomeScreenSeen, Qr, + isInitialized, + isUnlocked, } = props const isMascaraOnboarding = isMascara && isOnboarding const isBetaUIOnboarding = betaUI && isOnboarding && !props.isPopup && !isRevealingSeedWords + if (!welcomeScreenSeen && isBetaUIOnboarding && !isInitialized && !isUnlocked) { + return h(WelcomeScreen) + } + if (isMascaraOnboarding || isBetaUIOnboarding) { return h(MascaraFirstTime) } diff --git a/ui/app/css/itcss/components/index.scss b/ui/app/css/itcss/components/index.scss index 0219f9fb2..f107b7aca 100644 --- a/ui/app/css/itcss/components/index.scss +++ b/ui/app/css/itcss/components/index.scss @@ -55,3 +55,6 @@ @import './new-account.scss'; @import './tooltip.scss'; + +@import './welcome-screen.scss'; + diff --git a/ui/app/css/itcss/components/welcome-screen.scss b/ui/app/css/itcss/components/welcome-screen.scss new file mode 100644 index 000000000..dc8b38399 --- /dev/null +++ b/ui/app/css/itcss/components/welcome-screen.scss @@ -0,0 +1,47 @@ +.welcome-screen { + display: flex; + flex-flow: column; + justify-content: center; + align-items: center; + font-family: Roboto; + font-weight: 400; + width: 100%; + height: 100%; + padding: 70px 0; + background: $white; + + &__info { + display: flex; + flex-flow: column; + width: 100%; + height: 100%; + align-items: center; + + &__header { + font-size: 1.65em; + margin-bottom: 14px; + } + + &__copy { + font-size: 1em; + width: 400px; + max-width: 90vw; + text-align: center; + } + } + + &__button { + height: 54px; + width: 198px; + box-shadow: 0 2px 4px 0 rgba(0,0,0,0.14); + color: #FFFFFF; + font-size: 20px; + font-weight: 500; + line-height: 26px; + text-align: center; + text-transform: uppercase; + margin: 35px 0 14px; + transition: 200ms ease-in-out; + background-color: rgba(247, 134, 28, 0.9); + } +} \ No newline at end of file diff --git a/ui/app/reducers/metamask.js b/ui/app/reducers/metamask.js index cddcd0c1f..246d8839b 100644 --- a/ui/app/reducers/metamask.js +++ b/ui/app/reducers/metamask.js @@ -44,6 +44,7 @@ function reduceMetamask (state, action) { featureFlags: {}, networkEndpointType: OLD_UI_NETWORK_TYPE, isRevealingSeedWords: false, + welcomeScreenSeen: false, }, state.metamask) switch (action.type) { @@ -349,6 +350,11 @@ function reduceMetamask (state, action) { networkEndpointType: action.value, }) + case actions.CLOSE_WELCOME_SCREEN: + return extend(metamaskState, { + welcomeScreenSeen: true, + }) + default: return metamaskState diff --git a/ui/app/welcome-screen.js b/ui/app/welcome-screen.js new file mode 100644 index 000000000..0c1aced8c --- /dev/null +++ b/ui/app/welcome-screen.js @@ -0,0 +1,57 @@ +import EventEmitter from 'events' +import h from 'react-hyperscript' +import { Component } from 'react' +import PropTypes from 'prop-types' +import {connect} from 'react-redux' +import {closeWelcomeScreen} from './actions' +import Mascot from './components/mascot' + +class WelcomeScreen extends Component { + static propTypes = { + closeWelcomeScreen: PropTypes.func.isRequired, + } + + constructor () { + super() + this.animationEventEmitter = new EventEmitter() + } + + initiateAccountCreation = () => { + this.props.closeWelcomeScreen() + } + + render () { + // t + return h('div.welcome-screen', [ + + h('div.welcome-screen__info', [ + + h(Mascot, { + animationEventEmitter: this.animationEventEmitter, + width: '225', + height: '225', + }), + + h('div.welcome-screen__info__header', 'Welcome to MetaMask Beta.'), + + h('div.welcome-screen__info__copy', 'MetaMask is a secure identity vault for Ethereum.'), + + h('div.welcome-screen__info__copy', `It allows you to hold ether & tokens, + and serves as your bridge to decentralized applications.`), + + h('button.welcome-screen__button', { + onClick: this.initiateAccountCreation, + }, 'Continue'), + + ]), + + ]) + } +} + +export default connect( + null, + dispatch => ({ + closeWelcomeScreen: () => dispatch(closeWelcomeScreen()), + }) +)(WelcomeScreen) From a07550d2abff0916af500eda6767cf32e0849335 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Fri, 9 Mar 2018 18:50:00 +0100 Subject: [PATCH 05/16] Increase tap areas for menu buttons on mobile --- ui/app/components/tx-view.js | 10 +- ui/app/css/itcss/components/hero-balance.scss | 3 - .../css/itcss/components/newui-sections.scss | 22 ++- ui/app/main-container.js | 14 +- ui/app/unlock.js | 143 ++++++++---------- 5 files changed, 93 insertions(+), 99 deletions(-) diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index b25d8e0f9..ad9f9c5c0 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -100,9 +100,10 @@ TxView.prototype.render = function () { h('div.flex-row.phone-visible', { style: { - margin: '1.5em 1.2em 0', justifyContent: 'space-between', alignItems: 'center', + flex: '0 0 auto', + margin: '10px', }, }, [ @@ -110,11 +111,10 @@ TxView.prototype.render = function () { style: { fontSize: '1.3em', cursor: 'pointer', + padding: '10px', }, - onClick: () => { - this.props.sidebarOpen ? this.props.hideSidebar() : this.props.showSidebar() - }, - }, []), + onClick: () => this.props.sidebarOpen ? this.props.hideSidebar() : this.props.showSidebar(), + }), h('.identicon-wrapper.select-none', { style: { diff --git a/ui/app/css/itcss/components/hero-balance.scss b/ui/app/css/itcss/components/hero-balance.scss index 4af0c2c55..a3f051361 100644 --- a/ui/app/css/itcss/components/hero-balance.scss +++ b/ui/app/css/itcss/components/hero-balance.scss @@ -5,9 +5,6 @@ flex-direction: column; justify-content: flex-start; align-items: center; - margin: .3em .9em 0; - // height: 80vh; - // max-height: 225px; flex: 0 0 auto; } diff --git a/ui/app/css/itcss/components/newui-sections.scss b/ui/app/css/itcss/components/newui-sections.scss index ecf5e1036..a6d03a6c7 100644 --- a/ui/app/css/itcss/components/newui-sections.scss +++ b/ui/app/css/itcss/components/newui-sections.scss @@ -51,6 +51,7 @@ $wallet-view-bg: $alabaster; cursor: pointer; display: flex; justify-content: center; + padding: 10px; } // wallet view and sidebar @@ -313,4 +314,23 @@ $wallet-view-bg: $alabaster; @media screen and (min-width: 1281px) { width: 62vw; } -} \ No newline at end of file +} + +.unlock-screen-container { + z-index: $main-container-z-index; + font-family: Roboto; + display: flex; + justify-content: center; + align-items: center; + flex: 1 0 auto; + background: #f7f7f7; + width: 100%; +} + +.unlock-screen { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + flex: 1 0 auto; +} diff --git a/ui/app/main-container.js b/ui/app/main-container.js index 292abcc3d..eed4bd164 100644 --- a/ui/app/main-container.js +++ b/ui/app/main-container.js @@ -32,19 +32,7 @@ MainContainer.prototype.render = function () { return h(Settings, {key: 'config'}) default: log.debug('rendering locked screen') - contents = { - component: UnlockScreen, - style: { - boxShadow: 'none', - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - background: '#F7F7F7', - // must force 100%, because lock screen is full-width - width: '100%', - }, - key: 'locked', - } + return h('.unlock-screen-container', {}, h(UnlockScreen, { key: 'locked' })) } } diff --git a/ui/app/unlock.js b/ui/app/unlock.js index cafe3a859..39da699a6 100644 --- a/ui/app/unlock.js +++ b/ui/app/unlock.js @@ -28,83 +28,72 @@ UnlockScreen.prototype.render = function () { const state = this.props const warning = state.warning return ( - h('.flex-column', { - style: { - width: 'inherit', - }, - }, [ - h('.unlock-screen.flex-column.flex-center.flex-grow', [ - - h(Mascot, { - animationEventEmitter: this.animationEventEmitter, - }), - - h('h1', { - style: { - fontSize: '1.4em', - textTransform: 'uppercase', - color: '#7F8082', - }, - }, 'MetaMask'), - - h('input.large-input', { - type: 'password', - id: 'password-box', - placeholder: 'enter password', - style: { - background: 'white', - }, - onKeyPress: this.onKeyPress.bind(this), - onInput: this.inputChanged.bind(this), - }), - - h('.error', { - style: { - display: warning ? 'block' : 'none', - padding: '0 20px', - textAlign: 'center', - }, - }, warning), - - h('button.primary.cursor-pointer', { - onClick: this.onSubmit.bind(this), - style: { - margin: 10, - }, - }, 'Log In'), - ]), - - h('.flex-row.flex-center.flex-grow', [ - h('p.pointer', { - onClick: () => { - this.props.dispatch(actions.markPasswordForgotten()) - if (environmentType() === 'popup') { - global.platform.openExtensionInBrowser() - } - }, - style: { - fontSize: '0.8em', - color: 'rgb(247, 134, 28)', - textDecoration: 'underline', - }, - }, 'Restore from seed phrase'), - ]), - - h('.flex-row.flex-center.flex-grow', [ - h('p.pointer', { - onClick: () => { - this.props.dispatch(actions.setFeatureFlag('betaUI', false, 'OLD_UI_NOTIFICATION_MODAL')) - .then(() => this.props.dispatch(actions.setNetworkEndpoints(OLD_UI_NETWORK_TYPE))) - }, - style: { - fontSize: '0.8em', - color: '#aeaeae', - textDecoration: 'underline', - marginTop: '32px', - }, - }, 'Use classic interface'), - ]), - + h('.unlock-screen', [ + + h(Mascot, { + animationEventEmitter: this.animationEventEmitter, + }), + + h('h1', { + style: { + fontSize: '1.4em', + textTransform: 'uppercase', + color: '#7F8082', + }, + }, 'MetaMask'), + + h('input.large-input', { + type: 'password', + id: 'password-box', + placeholder: 'enter password', + style: { + background: 'white', + }, + onKeyPress: this.onKeyPress.bind(this), + onInput: this.inputChanged.bind(this), + }), + + h('.error', { + style: { + display: warning ? 'block' : 'none', + padding: '0 20px', + textAlign: 'center', + }, + }, warning), + + h('button.primary.cursor-pointer', { + onClick: this.onSubmit.bind(this), + style: { + margin: 10, + }, + }, 'Log In'), + + h('p.pointer', { + onClick: () => { + this.props.dispatch(actions.markPasswordForgotten()) + if (environmentType() === 'popup') { + global.platform.openExtensionInBrowser() + } + }, + style: { + fontSize: '0.8em', + color: 'rgb(247, 134, 28)', + textDecoration: 'underline', + }, + }, 'Restore from seed phrase'), + + h('p.pointer', { + onClick: () => { + this.props.dispatch(actions.setFeatureFlag('betaUI', false, 'OLD_UI_NOTIFICATION_MODAL')) + .then(() => this.props.dispatch(actions.setNetworkEndpoints(OLD_UI_NETWORK_TYPE))) + }, + style: { + fontSize: '0.8em', + color: '#aeaeae', + textDecoration: 'underline', + marginTop: '32px', + }, + }, 'Use classic interface'), ]) ) } From 74502296ed22edd5300ea74fd7b483fab0736729 Mon Sep 17 00:00:00 2001 From: kumavis Date: Sat, 10 Mar 2018 11:09:45 -0800 Subject: [PATCH 06/16] ci - split integration tests into parallel firefox and chrome runs --- .circleci/config.yml | 58 +++++++++++++++++++++++++++++++++++++++++--- test/base.conf.js | 4 ++- 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 9cd0a24ec..df3e0ed19 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -15,12 +15,20 @@ workflows: - test-unit: requires: - prep-deps-npm - - test-integration-mascara: + - test-integration-mascara-chrome: + requires: + - prep-deps-npm + - prep-scss + - test-integration-mascara-firefox: requires: - prep-deps-npm - prep-deps-firefox - prep-scss - - test-integration-flat: + - test-integration-flat-chrome: + requires: + - prep-deps-npm + - prep-scss + - test-integration-flat-firefox: requires: - prep-deps-npm - prep-deps-firefox @@ -99,7 +107,9 @@ jobs: name: test:coverage command: npm run test:coverage - test-integration-flat: + test-integration-flat-firefox: + environment: + browsers: ["Firefox"] docker: - image: circleci/node:8-browsers steps: @@ -125,7 +135,28 @@ jobs: name: test:integration:flat command: npm run test:flat - test-integration-mascara: + test-integration-flat-chrome: + environment: + browsers: ["Chrome"] + docker: + - image: circleci/node:8-browsers + steps: + - checkout + - restore_cache: + key: dependency-cache-{{ checksum "package-lock.json" }} + - run: + name: Get Scss Cache key + # this allows us to checksum against a whole directory + command: find ui/app/css -type f -exec md5sum {} \; | sort -k 2 > scss_checksum + - restore_cache: + key: scss-cache-{{ checksum "scss_checksum" }} + - run: + name: test:integration:flat + command: npm run test:flat + + test-integration-mascara-firefox: + environment: + browsers: ["Firefox"] docker: - image: circleci/node:8-browsers steps: @@ -150,3 +181,22 @@ jobs: - run: name: test:integration:mascara command: npm run test:mascara + + test-integration-mascara-chrome: + environment: + browsers: ["Chrome"] + docker: + - image: circleci/node:8-browsers + steps: + - checkout + - restore_cache: + key: dependency-cache-{{ checksum "package-lock.json" }} + - run: + name: Get Scss Cache key + # this allows us to checksum against a whole directory + command: find ui/app/css -type f -exec md5sum {} \; | sort -k 2 > scss_checksum + - restore_cache: + key: scss-cache-{{ checksum "scss_checksum" }} + - run: + name: test:integration:mascara + command: npm run test:mascara diff --git a/test/base.conf.js b/test/base.conf.js index 82b9d8eec..adb5357e8 100644 --- a/test/base.conf.js +++ b/test/base.conf.js @@ -46,7 +46,9 @@ module.exports = function(config) { // start these browsers // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher - browsers: ['Chrome', 'Firefox'], + browsers: process.env.browsers ? + JSON.parse(process.env.browsers) + : ['Chrome', 'Firefox'], // Continuous Integration mode // if true, Karma captures browsers, runs the tests and exits From 2c3e6552d203181bca1c69622a78e5faa633ce76 Mon Sep 17 00:00:00 2001 From: kumavis Date: Sat, 10 Mar 2018 11:13:27 -0800 Subject: [PATCH 07/16] ci - wrap env var in quotes --- .circleci/config.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index df3e0ed19..c14909783 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -109,7 +109,7 @@ jobs: test-integration-flat-firefox: environment: - browsers: ["Firefox"] + browsers: '["Firefox"]' docker: - image: circleci/node:8-browsers steps: @@ -137,7 +137,7 @@ jobs: test-integration-flat-chrome: environment: - browsers: ["Chrome"] + browsers: '["Chrome"]' docker: - image: circleci/node:8-browsers steps: @@ -156,7 +156,7 @@ jobs: test-integration-mascara-firefox: environment: - browsers: ["Firefox"] + browsers: '["Firefox"]' docker: - image: circleci/node:8-browsers steps: @@ -184,7 +184,7 @@ jobs: test-integration-mascara-chrome: environment: - browsers: ["Chrome"] + browsers: '["Chrome"]' docker: - image: circleci/node:8-browsers steps: From 7e56c6b6fa92453559f2510e390fce451de2dead Mon Sep 17 00:00:00 2001 From: kumavis Date: Sun, 11 Mar 2018 14:51:54 -0700 Subject: [PATCH 08/16] test - genStates - use async api --- development/genStates.js | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/development/genStates.js b/development/genStates.js index 39a672ee0..325ef71f3 100644 --- a/development/genStates.js +++ b/development/genStates.js @@ -1,18 +1,21 @@ const fs = require('fs') const path = require('path') +const { promisify } = require('util') -const statesPath = path.join(__dirname, 'states') -const stateNames = fs.readdirSync(statesPath) +start().catch(console.error) -const states = stateNames.reduce((result, stateFileName) => { - const statePath = path.join(__dirname, 'states', stateFileName) - const stateFile = fs.readFileSync(statePath).toString() - const state = JSON.parse(stateFile) - result[stateFileName.split('.')[0].replace(/-/g, ' ', 'g')] = state - return result -}, {}) - -const result = `module.exports = ${JSON.stringify(states)}` - -const statesJsonPath = path.join(__dirname, 'states.js') -fs.writeFileSync(statesJsonPath, result) +async function start () { + const statesPath = path.join(__dirname, 'states') + const stateFilesNames = await promisify(fs.readdirSync)(statesPath) + const states = {} + await Promise.all(stateFilesNames.map(async (stateFileName) => { + const stateFilePath = path.join(__dirname, 'states', stateFileName) + const stateFileContent = await promisify(fs.readFileSync)(stateFilePath, 'utf8') + const state = JSON.parse(stateFileContent) + const stateName = stateFileName.split('.')[0].replace(/-/g, ' ', 'g') + states[stateName] = state + })) + const generatedFileContent = `module.exports = ${JSON.stringify(states)}` + const generatedFilePath = path.join(__dirname, 'states.js') + await promisify(fs.writeFile)(generatedFilePath, generatedFileContent) +} From 0419276958a168f2d7b75c11cfe8d14cf5f39514 Mon Sep 17 00:00:00 2001 From: kumavis Date: Sun, 11 Mar 2018 14:52:29 -0700 Subject: [PATCH 09/16] test - poll for element instead of manual timeouts --- test/integration/lib/add-token.js | 73 +++++----------- test/integration/lib/first-time.js | 80 ++++++------------ test/integration/lib/send-new-ui.js | 127 +++++++++------------------- test/lib/util.js | 53 ++++++++++++ 4 files changed, 144 insertions(+), 189 deletions(-) create mode 100644 test/lib/util.js diff --git a/test/integration/lib/add-token.js b/test/integration/lib/add-token.js index dd4251cc4..42ed28dca 100644 --- a/test/integration/lib/add-token.js +++ b/test/integration/lib/add-token.js @@ -1,4 +1,9 @@ const reactTriggerChange = require('react-trigger-change') +const { + timeout, + queryAsync, + findAsync, +} = require('../../lib/util') QUnit.module('Add token flow') @@ -13,74 +18,60 @@ QUnit.test('successful add token flow', (assert) => { }) async function runAddTokenFlowTest (assert, done) { - const selectState = $('select') + const selectState = await queryAsync($, 'select') selectState.val('add token') reactTriggerChange(selectState[0]) - await timeout(2000) - // Check that no tokens have been added assert.ok($('.token-list-item').length === 0, 'no tokens added') // Go to Add Token screen - let addTokenButton = $('button.btn-clear.wallet-view__add-token-button') + let addTokenButton = await queryAsync($, 'button.btn-clear.wallet-view__add-token-button') assert.ok(addTokenButton[0], 'add token button present') addTokenButton[0].click() - await timeout(1000) - // Verify Add Token screen - let addTokenWrapper = $('.add-token__wrapper') + let addTokenWrapper = await queryAsync($, '.add-token__wrapper') assert.ok(addTokenWrapper[0], 'add token wrapper renders') - let addTokenTitle = $('.add-token__title') + let addTokenTitle = await queryAsync($, '.add-token__title') assert.equal(addTokenTitle[0].textContent, 'Add Token', 'add token title is correct') // Cancel Add Token - const cancelAddTokenButton = $('button.btn-cancel.add-token__button') + const cancelAddTokenButton = await queryAsync($, 'button.btn-cancel.add-token__button') assert.ok(cancelAddTokenButton[0], 'cancel add token button present') cancelAddTokenButton.click() - await timeout(1000) - assert.ok($('.wallet-view')[0], 'cancelled and returned to account detail wallet view') // Return to Add Token Screen - addTokenButton = $('button.btn-clear.wallet-view__add-token-button') + addTokenButton = await queryAsync($, 'button.btn-clear.wallet-view__add-token-button') assert.ok(addTokenButton[0], 'add token button present') addTokenButton[0].click() - await timeout(1000) - // Verify Add Token Screen - addTokenWrapper = $('.add-token__wrapper') - addTokenTitle = $('.add-token__title') + addTokenWrapper = await queryAsync($, '.add-token__wrapper') + addTokenTitle = await queryAsync($, '.add-token__title') assert.ok(addTokenWrapper[0], 'add token wrapper renders') assert.equal(addTokenTitle[0].textContent, 'Add Token', 'add token title is correct') // Search for token - const searchInput = $('input.add-token__input') + const searchInput = await queryAsync($, 'input.add-token__input') searchInput.val('a') reactTriggerChange(searchInput[0]) - await timeout() - // Click token to add - const tokenWrapper = $('div.add-token__token-wrapper') + const tokenWrapper = await queryAsync($, 'div.add-token__token-wrapper') assert.ok(tokenWrapper[0], 'token found') const tokenImageProp = tokenWrapper.find('.add-token__token-icon').css('background-image') const tokenImageUrl = tokenImageProp.slice(5, -2) tokenWrapper[0].click() - await timeout() - // Click Next button - let nextButton = $('button.btn-clear.add-token__button') + let nextButton = await queryAsync($, 'button.btn-clear.add-token__button') assert.equal(nextButton[0].textContent, 'Next', 'next button rendered') nextButton[0].click() - await timeout() - // Confirm Add token assert.equal( $('.add-token__description')[0].textContent, @@ -90,47 +81,35 @@ async function runAddTokenFlowTest (assert, done) { assert.ok($('button.btn-clear.add-token__button')[0], 'confirm add token button found') $('button.btn-clear.add-token__button')[0].click() - await timeout(2000) - // Verify added token image - let heroBalance = $('.hero-balance') + let heroBalance = await queryAsync($, '.hero-balance') assert.ok(heroBalance, 'rendered hero balance') assert.ok(tokenImageUrl.indexOf(heroBalance.find('img').attr('src')) > -1, 'token added') // Return to Add Token Screen - addTokenButton = $('button.btn-clear.wallet-view__add-token-button') + addTokenButton = await queryAsync($, 'button.btn-clear.wallet-view__add-token-button') assert.ok(addTokenButton[0], 'add token button present') addTokenButton[0].click() - await timeout(1000) - - const addCustom = $('.add-token__add-custom') + const addCustom = await queryAsync($, '.add-token__add-custom') assert.ok(addCustom[0], 'add custom token button present') addCustom[0].click() - await timeout() - // Input token contract address - const customInput = $('input.add-token__add-custom-input') + const customInput = await queryAsync($, 'input.add-token__add-custom-input') customInput.val('0x177af043D3A1Aed7cc5f2397C70248Fc6cDC056c') reactTriggerChange(customInput[0]) - await timeout(1000) - // Click Next button - nextButton = $('button.btn-clear.add-token__button') + nextButton = await queryAsync($, 'button.btn-clear.add-token__button') assert.equal(nextButton[0].textContent, 'Next', 'next button rendered') nextButton[0].click() - await timeout(1000) - // Verify symbol length error since contract address won't return symbol - const errorMessage = $('.add-token__add-custom-error-message') + const errorMessage = await queryAsync($, '.add-token__add-custom-error-message') assert.ok(errorMessage[0], 'error rendered') $('button.btn-cancel.add-token__button')[0].click() - await timeout(2000) - // // Confirm Add token // assert.equal( // $('.add-token__description')[0].textContent, @@ -141,13 +120,7 @@ async function runAddTokenFlowTest (assert, done) { // $('button.btn-clear.add-token__button')[0].click() // // Verify added token image - // heroBalance = $('.hero-balance') + // heroBalance = await queryAsync($, '.hero-balance') // assert.ok(heroBalance, 'rendered hero balance') // assert.ok(heroBalance.find('.identicon')[0], 'token added') } - -function timeout (time) { - return new Promise((resolve, reject) => { - setTimeout(resolve, time || 1500) - }) -} diff --git a/test/integration/lib/first-time.js b/test/integration/lib/first-time.js index 764eae47c..052d89518 100644 --- a/test/integration/lib/first-time.js +++ b/test/integration/lib/first-time.js @@ -1,6 +1,10 @@ const reactTriggerChange = require('react-trigger-change') const PASSWORD = 'password123' const runMascaraFirstTimeTest = require('./mascara-first-time') +const { + timeout, + findAsync, +} = require('../../lib/util') QUnit.module('first time usage') @@ -21,20 +25,19 @@ async function runFirstTimeUsageTest(assert, done) { selectState.val('first time') reactTriggerChange(selectState[0]) - await timeout(2000) const app = $('#app-content') // recurse notices while (true) { - const button = app.find('button') + const button = await findAsync(app, 'button') if (button.html() === 'Accept') { // still notices to accept - const termsPage = app.find('.markdown')[0] + const termsPageRaw = await findAsync(app, '.markdown') + const termsPage = (await findAsync(app, '.markdown'))[0] + console.log('termsPageRaw', termsPageRaw) termsPage.scrollTop = termsPage.scrollHeight - await timeout() console.log('Clearing notice') button.click() - await timeout() } else { // exit loop console.log('No more notices...') @@ -42,97 +45,68 @@ async function runFirstTimeUsageTest(assert, done) { } } - await timeout() - // Scroll through terms - const title = app.find('h1')[0] + const title = (await findAsync(app, 'h1'))[0] assert.equal(title.textContent, 'MetaMask', 'title screen') // enter password - const pwBox = app.find('#password-box')[0] - const confBox = app.find('#password-box-confirm')[0] + const pwBox = (await findAsync(app, '#password-box'))[0] + const confBox = (await findAsync(app, '#password-box-confirm'))[0] pwBox.value = PASSWORD confBox.value = PASSWORD - await timeout() - // create vault - const createButton = app.find('button.primary')[0] + const createButton = (await findAsync(app, 'button.primary'))[0] createButton.click() - await timeout(3000) - - const created = app.find('h3')[0] + await timeout() + const created = (await findAsync(app, 'h3'))[0] assert.equal(created.textContent, 'Vault Created', 'Vault created screen') // Agree button - const button = app.find('button')[0] + const button = (await findAsync(app, 'button'))[0] assert.ok(button, 'button present') button.click() - await timeout(1000) - - const detail = app.find('.account-detail-section')[0] + const detail = (await findAsync(app, '.account-detail-section'))[0] assert.ok(detail, 'Account detail section loaded.') - const sandwich = app.find('.sandwich-expando')[0] + const sandwich = (await findAsync(app, '.sandwich-expando'))[0] sandwich.click() - await timeout() - - const menu = app.find('.menu-droppo')[0] + const menu = (await findAsync(app, '.menu-droppo'))[0] const children = menu.children const logout = children[2] assert.ok(logout, 'Lock menu item found') logout.click() - await timeout(1000) - - const pwBox2 = app.find('#password-box')[0] + const pwBox2 = (await findAsync(app, '#password-box'))[0] pwBox2.value = PASSWORD - const createButton2 = app.find('button.primary')[0] + const createButton2 = (await findAsync(app, 'button.primary'))[0] createButton2.click() - await timeout(1000) - - const detail2 = app.find('.account-detail-section')[0] + const detail2 = (await findAsync(app, '.account-detail-section'))[0] assert.ok(detail2, 'Account detail section loaded again.') - await timeout() - // open account settings dropdown - const qrButton = app.find('.fa.fa-ellipsis-h')[0] + const qrButton = (await findAsync(app, '.fa.fa-ellipsis-h'))[0] qrButton.click() - await timeout(1000) - // qr code item - const qrButton2 = app.find('.dropdown-menu-item')[1] + const qrButton2 = (await findAsync(app, '.dropdown-menu-item'))[1] qrButton2.click() - await timeout(1000) - - const qrHeader = app.find('.qr-header')[0] - const qrContainer = app.find('#qr-container')[0] + const qrHeader = (await findAsync(app, '.qr-header'))[0] + const qrContainer = (await findAsync(app, '#qr-container'))[0] assert.equal(qrHeader.textContent, 'Account 1', 'Should show account label.') assert.ok(qrContainer, 'QR Container found') - await timeout() - - const networkMenu = app.find('.network-indicator')[0] + const networkMenu = (await findAsync(app, '.network-indicator'))[0] networkMenu.click() - await timeout() - - const networkMenu2 = app.find('.network-indicator')[0] + const networkMenu2 = (await findAsync(app, '.network-indicator'))[0] const children2 = networkMenu2.children children2.length[3] assert.ok(children2, 'All network options present') } - -function timeout (time) { - return new Promise((resolve, reject) => { - setTimeout(resolve, time || 1500) - }) -} \ No newline at end of file diff --git a/test/integration/lib/send-new-ui.js b/test/integration/lib/send-new-ui.js index 3456f2367..07be63a36 100644 --- a/test/integration/lib/send-new-ui.js +++ b/test/integration/lib/send-new-ui.js @@ -1,4 +1,9 @@ const reactTriggerChange = require('react-trigger-change') +const { + timeout, + queryAsync, + findAsync, +} = require('../../lib/util') const PASSWORD = 'password123' @@ -18,83 +23,67 @@ global.ethQuery = { async function runSendFlowTest(assert, done) { console.log('*** start runSendFlowTest') - const selectState = $('select') + const selectState = await queryAsync($, 'select') selectState.val('send new ui') reactTriggerChange(selectState[0]) - await timeout(2000) - - const sendScreenButton = $('button.btn-clear.hero-balance-button') + const sendScreenButton = await queryAsync($, 'button.btn-clear.hero-balance-button') assert.ok(sendScreenButton[1], 'send screen button present') sendScreenButton[1].click() - await timeout(1000) - - const sendTitle = $('.page-container__title') + const sendTitle = await queryAsync($, '.page-container__title') assert.equal(sendTitle[0].textContent, 'Send ETH', 'Send screen title is correct') - const sendCopy = $('.page-container__subtitle') + const sendCopy = await queryAsync($, '.page-container__subtitle') assert.equal(sendCopy[0].textContent, 'Only send ETH to an Ethereum address.', 'Send screen has copy') - const sendFromField = $('.send-v2__form-field') + const sendFromField = await queryAsync($, '.send-v2__form-field') assert.ok(sendFromField[0], 'send screen has a from field') - let sendFromFieldItemAddress = $('.account-list-item__account-name') + let sendFromFieldItemAddress = await queryAsync($, '.account-list-item__account-name') assert.equal(sendFromFieldItemAddress[0].textContent, 'Send Account 4', 'send from field shows correct account name') - const sendFromFieldItem = $('.account-list-item') - sendFromFieldItem[0].click() - await timeout() + const sendFromFieldItem = await queryAsync($, '.account-list-item') + sendFromFieldItem[0].click() - const sendFromDropdownList = $('.send-v2__from-dropdown__list') + const sendFromDropdownList = await queryAsync($, '.send-v2__from-dropdown__list') assert.equal(sendFromDropdownList.children().length, 4, 'send from dropdown shows all accounts') console.log(`!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! sendFromDropdownList.children()[1]`, sendFromDropdownList.children()[1]); sendFromDropdownList.children()[1].click() - await timeout() - - sendFromFieldItemAddress = $('.account-list-item__account-name') + sendFromFieldItemAddress = await queryAsync($, '.account-list-item__account-name') console.log(`!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! sendFromFieldItemAddress[0]`, sendFromFieldItemAddress[0]); assert.equal(sendFromFieldItemAddress[0].textContent, 'Send Account 2', 'send from field dropdown changes account name') - let sendToFieldInput = $('.send-v2__to-autocomplete__input') + let sendToFieldInput = await queryAsync($, '.send-v2__to-autocomplete__input') sendToFieldInput[0].focus() - await timeout() - - const sendToDropdownList = $('.send-v2__from-dropdown__list') + const sendToDropdownList = await queryAsync($, '.send-v2__from-dropdown__list') assert.equal(sendToDropdownList.children().length, 5, 'send to dropdown shows all accounts and address book accounts') sendToDropdownList.children()[2].click() - await timeout() - const sendToAccountAddress = sendToFieldInput.val() assert.equal(sendToAccountAddress, '0x2f8d4a878cfa04a6e60d46362f5644deab66572d', 'send to dropdown selects the correct address') - const sendAmountField = $('.send-v2__form-row:eq(2)') + const sendAmountField = await queryAsync($, '.send-v2__form-row:eq(2)') sendAmountField.find('.currency-display')[0].click() - await timeout() - - const sendAmountFieldInput = sendAmountField.find('input:text') + const sendAmountFieldInput = await findAsync(sendAmountField, 'input:text') sendAmountFieldInput.val('5.1') reactTriggerChange(sendAmountField.find('input')[0]) - await timeout() - - let errorMessage = $('.send-v2__error') + let errorMessage = await queryAsync($, '.send-v2__error') assert.equal(errorMessage[0].textContent, 'Insufficient funds.', 'send should render an insufficient fund error message') sendAmountFieldInput.val('2.0') reactTriggerChange(sendAmountFieldInput[0]) - await timeout() errorMessage = $('.send-v2__error') assert.equal(errorMessage.length, 0, 'send should stop rendering amount error message after amount is corrected') - const sendGasField = $('.send-v2__gas-fee-display') + const sendGasField = await queryAsync($, '.send-v2__gas-fee-display') assert.equal( sendGasField.find('.currency-display__input-wrapper > input').val(), '0.000198', @@ -106,120 +95,86 @@ async function runSendFlowTest(assert, done) { 'send gas field should show estimated gas total converted to USD' ) - const sendGasOpenCustomizeModalButton = $('.send-v2__sliders-icon-container' - ) + const sendGasOpenCustomizeModalButton = await queryAsync($, '.send-v2__sliders-icon-container') sendGasOpenCustomizeModalButton[0].click() - await timeout(1000) - - const customizeGasModal = $('.send-v2__customize-gas') + const customizeGasModal = await queryAsync($, '.send-v2__customize-gas') assert.ok(customizeGasModal[0], 'should render the customize gas modal') - const customizeGasPriceInput = $('.send-v2__gas-modal-card').first().find('input') + const customizeGasPriceInput = (await queryAsync($, '.send-v2__gas-modal-card')).first().find('input') customizeGasPriceInput.val(50) reactTriggerChange(customizeGasPriceInput[0]) - const customizeGasLimitInput = $('.send-v2__gas-modal-card').last().find('input') + const customizeGasLimitInput = (await queryAsync($, '.send-v2__gas-modal-card')).last().find('input') customizeGasLimitInput.val(60000) reactTriggerChange(customizeGasLimitInput[0]) - await timeout() - - const customizeGasSaveButton = $('.send-v2__customize-gas__save') + const customizeGasSaveButton = await queryAsync($, '.send-v2__customize-gas__save') customizeGasSaveButton[0].click() - await timeout() - assert.equal( - sendGasField.find('.currency-display__input-wrapper > input').val(), + (await findAsync(sendGasField, '.currency-display__input-wrapper > input')).val(), '0.003', 'send gas field should show customized gas total' ) assert.equal( - sendGasField.find('.currency-display__converted-value')[0].textContent, + (await findAsync(sendGasField, '.currency-display__converted-value'))[0].textContent, '3.60 USD', 'send gas field should show customized gas total converted to USD' ) - const sendButton = $('button.btn-clear.page-container__footer-button') + const sendButton = await queryAsync($, 'button.btn-clear.page-container__footer-button') assert.equal(sendButton[0].textContent, 'Next', 'next button rendered') sendButton[0].click() - - await timeout(2000) + await timeout() selectState.val('send edit') reactTriggerChange(selectState[0]) - await timeout(2000) - - const confirmFromName = $('.confirm-screen-account-name').first() + const confirmFromName = (await queryAsync($, '.confirm-screen-account-name')).first() assert.equal(confirmFromName[0].textContent, 'Send Account 2', 'confirm screen should show correct from name') - const confirmToName = $('.confirm-screen-account-name').last() + const confirmToName = (await queryAsync($, '.confirm-screen-account-name')).last() assert.equal(confirmToName[0].textContent, 'Send Account 3', 'confirm screen should show correct to name') - const confirmScreenRows = $('.confirm-screen-rows') + const confirmScreenRows = await queryAsync($, '.confirm-screen-rows') const confirmScreenGas = confirmScreenRows.find('.confirm-screen-row-info')[2] assert.equal(confirmScreenGas.textContent, '3.6 USD', 'confirm screen should show correct gas') const confirmScreenTotal = confirmScreenRows.find('.confirm-screen-row-info')[3] assert.equal(confirmScreenTotal.textContent, '2405.36 USD', 'confirm screen should show correct total') - const confirmScreenBackButton = $('.confirm-screen-back-button') + const confirmScreenBackButton = await queryAsync($, '.confirm-screen-back-button') confirmScreenBackButton[0].click() - await timeout(1000) - - const sendFromFieldItemInEdit = $('.account-list-item') + const sendFromFieldItemInEdit = await queryAsync($, '.account-list-item') sendFromFieldItemInEdit[0].click() - await timeout() - - const sendFromDropdownListInEdit = $('.send-v2__from-dropdown__list') + const sendFromDropdownListInEdit = await queryAsync($, '.send-v2__from-dropdown__list') sendFromDropdownListInEdit.children()[2].click() - await timeout() - - const sendToFieldInputInEdit = $('.send-v2__to-autocomplete__input') + const sendToFieldInputInEdit = await queryAsync($, '.send-v2__to-autocomplete__input') sendToFieldInputInEdit[0].focus() sendToFieldInputInEdit.val('0xd85a4b6a394794842887b8284293d69163007bbb') - await timeout() - - const sendAmountFieldInEdit = $('.send-v2__form-row:eq(2)') + const sendAmountFieldInEdit = await queryAsync($, '.send-v2__form-row:eq(2)') sendAmountFieldInEdit.find('.currency-display')[0].click() - await timeout() - const sendAmountFieldInputInEdit = sendAmountFieldInEdit.find('input:text') sendAmountFieldInputInEdit.val('1.0') reactTriggerChange(sendAmountFieldInputInEdit[0]) - await timeout() - - const sendButtonInEdit = $('.btn-clear.page-container__footer-button') + const sendButtonInEdit = await queryAsync($, '.btn-clear.page-container__footer-button') assert.equal(sendButtonInEdit[0].textContent, 'Next', 'next button in edit rendered') sendButtonInEdit[0].click() - await timeout() - // TODO: Need a way to mock background so that we can test correct transition from editing to confirm selectState.val('confirm new ui') reactTriggerChange(selectState[0]) - - await timeout(2000) - const confirmScreenConfirmButton = $('.confirm-screen-confirm-button') + const confirmScreenConfirmButton = await queryAsync($, '.confirm-screen-confirm-button') console.log(`+++++++++++++++++++++++++++++++= confirmScreenConfirmButton[0]`, confirmScreenConfirmButton[0]); confirmScreenConfirmButton[0].click() - await timeout(2000) - - const txView = $('.tx-view') + const txView = await queryAsync($, '.tx-view') console.log(`++++++++++++++++++++++++++++++++ txView[0]`, txView[0]); assert.ok(txView[0], 'Should return to the account details screen after confirming') } - -function timeout (time) { - return new Promise((resolve, reject) => { - setTimeout(resolve, time || 1500) - }) -} \ No newline at end of file diff --git a/test/lib/util.js b/test/lib/util.js new file mode 100644 index 000000000..626280745 --- /dev/null +++ b/test/lib/util.js @@ -0,0 +1,53 @@ +module.exports = { + timeout, + queryAsync, + findAsync, + pollUntilTruthy, +} + +function timeout (time) { + return new Promise((resolve, reject) => { + setTimeout(resolve, time || 1500) + }) +} + +async function findAsync(container, selector, opts) { + try { + return await pollUntilTruthy(() => { + const result = container.find(selector) + if (result.length > 0) return result + }, opts) + } catch (err) { + throw new Error(`Failed to find element within interval: "${selector}"`) + } +} + +async function queryAsync(jQuery, selector, opts) { + try { + return await pollUntilTruthy(() => { + const result = jQuery(selector) + if (result.length > 0) return result + }, opts) + } catch (err) { + throw new Error(`Failed to find element within interval: "${selector}"`) + } +} + +async function pollUntilTruthy(fn, opts = {}){ + const pollingInterval = opts.pollingInterval || 100 + const timeoutInterval = opts.timeoutInterval || 5000 + const start = Date.now() + let result + while (!result) { + // check if timedout + const now = Date.now() + if ((now - start) > timeoutInterval) { + throw new Error(`pollUntilTruthy - failed to return truthy within interval`) + } + // check for result + result = fn() + // run again after timeout + await timeout(pollingInterval, timeoutInterval) + } + return result +} From 07fa26d1f094a7a405107c5f31674e65c94cea8d Mon Sep 17 00:00:00 2001 From: kumavis Date: Sun, 11 Mar 2018 18:52:27 -0700 Subject: [PATCH 10/16] test - add comment about test behavior oddity --- test/integration/index.js | 2 +- test/integration/lib/send-new-ui.js | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/test/integration/index.js b/test/integration/index.js index 144303dbb..b266ddf37 100644 --- a/test/integration/index.js +++ b/test/integration/index.js @@ -23,4 +23,4 @@ pump( console.log(`Integration test build completed: "${bundlePath}"`) process.exit(0) } -) \ No newline at end of file +) diff --git a/test/integration/lib/send-new-ui.js b/test/integration/lib/send-new-ui.js index 07be63a36..faab10fdf 100644 --- a/test/integration/lib/send-new-ui.js +++ b/test/integration/lib/send-new-ui.js @@ -43,17 +43,15 @@ async function runSendFlowTest(assert, done) { let sendFromFieldItemAddress = await queryAsync($, '.account-list-item__account-name') assert.equal(sendFromFieldItemAddress[0].textContent, 'Send Account 4', 'send from field shows correct account name') - await timeout() const sendFromFieldItem = await queryAsync($, '.account-list-item') sendFromFieldItem[0].click() + // this seems to fail if the firefox window is not in focus... const sendFromDropdownList = await queryAsync($, '.send-v2__from-dropdown__list') assert.equal(sendFromDropdownList.children().length, 4, 'send from dropdown shows all accounts') - console.log(`!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! sendFromDropdownList.children()[1]`, sendFromDropdownList.children()[1]); sendFromDropdownList.children()[1].click() sendFromFieldItemAddress = await queryAsync($, '.account-list-item__account-name') - console.log(`!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! sendFromFieldItemAddress[0]`, sendFromFieldItemAddress[0]); assert.equal(sendFromFieldItemAddress[0].textContent, 'Send Account 2', 'send from field dropdown changes account name') let sendToFieldInput = await queryAsync($, '.send-v2__to-autocomplete__input') From ecb792ae502dcacf168fb288ef0f2623e599eb78 Mon Sep 17 00:00:00 2001 From: kumavis Date: Sun, 11 Mar 2018 19:06:14 -0700 Subject: [PATCH 11/16] genStates - fix fs api calls --- development/genStates.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/development/genStates.js b/development/genStates.js index 325ef71f3..d92e2bc2e 100644 --- a/development/genStates.js +++ b/development/genStates.js @@ -6,11 +6,11 @@ start().catch(console.error) async function start () { const statesPath = path.join(__dirname, 'states') - const stateFilesNames = await promisify(fs.readdirSync)(statesPath) + const stateFilesNames = await promisify(fs.readdir)(statesPath) const states = {} await Promise.all(stateFilesNames.map(async (stateFileName) => { const stateFilePath = path.join(__dirname, 'states', stateFileName) - const stateFileContent = await promisify(fs.readFileSync)(stateFilePath, 'utf8') + const stateFileContent = await promisify(fs.readFile)(stateFilePath, 'utf8') const state = JSON.parse(stateFileContent) const stateName = stateFileName.split('.')[0].replace(/-/g, ' ', 'g') states[stateName] = state From 3537c391db30bdec1d3fabb361dffc2e4a3931da Mon Sep 17 00:00:00 2001 From: kumavis Date: Sun, 11 Mar 2018 19:29:35 -0700 Subject: [PATCH 12/16] test - use new async selectors for faster testing --- test/integration/lib/confirm-sig-requests.js | 44 ++++----- test/integration/lib/mascara-first-time.js | 94 +++++++------------- 2 files changed, 49 insertions(+), 89 deletions(-) diff --git a/test/integration/lib/confirm-sig-requests.js b/test/integration/lib/confirm-sig-requests.js index e49424c37..9737a2283 100644 --- a/test/integration/lib/confirm-sig-requests.js +++ b/test/integration/lib/confirm-sig-requests.js @@ -1,5 +1,9 @@ const reactTriggerChange = require('react-trigger-change') - +const { + timeout, + queryAsync, + findAsync, +} = require('../../lib/util') const PASSWORD = 'password123' QUnit.module('confirm sig requests') @@ -13,55 +17,41 @@ QUnit.test('successful confirmation of sig requests', (assert) => { }) async function runConfirmSigRequestsTest(assert, done) { - let selectState = $('select') + let selectState = await queryAsync($, 'select') selectState.val('confirm sig requests') reactTriggerChange(selectState[0]) - await timeout(2000) - - let confirmSigHeadline = $('.request-signature__headline') + let confirmSigHeadline = await queryAsync($, '.request-signature__headline') assert.equal(confirmSigHeadline[0].textContent, 'Your signature is being requested') - let confirmSigRowValue = $('.request-signature__row-value') + let confirmSigRowValue = await queryAsync($, '.request-signature__row-value') assert.ok(confirmSigRowValue[0].textContent.match(/^\#\sTerms\sof\sUse/)) - let confirmSigSignButton = $('.request-signature__footer__sign-button') + let confirmSigSignButton = await queryAsync($, '.request-signature__footer__sign-button') confirmSigSignButton[0].click() - await timeout(2000) - - confirmSigHeadline = $('.request-signature__headline') + confirmSigHeadline = await queryAsync($, '.request-signature__headline') assert.equal(confirmSigHeadline[0].textContent, 'Your signature is being requested') - let confirmSigMessage = $('.request-signature__notice') + let confirmSigMessage = await queryAsync($, '.request-signature__notice') assert.ok(confirmSigMessage[0].textContent.match(/^Signing\sthis\smessage/)) - confirmSigRowValue = $('.request-signature__row-value') + confirmSigRowValue = await queryAsync($, '.request-signature__row-value') assert.equal(confirmSigRowValue[0].textContent, '0x879a053d4800c6354e76c7985a865d2922c82fb5b3f4577b2fe08b998954f2e0') - confirmSigSignButton = $('.request-signature__footer__sign-button') + confirmSigSignButton = await queryAsync($, '.request-signature__footer__sign-button') confirmSigSignButton[0].click() - await timeout(2000) - - confirmSigHeadline = $('.request-signature__headline') + confirmSigHeadline = await queryAsync($, '.request-signature__headline') assert.equal(confirmSigHeadline[0].textContent, 'Your signature is being requested') - confirmSigRowValue = $('.request-signature__row-value') + confirmSigRowValue = await queryAsync($, '.request-signature__row-value') assert.equal(confirmSigRowValue[0].textContent, 'Hi, Alice!') assert.equal(confirmSigRowValue[1].textContent, '1337') - confirmSigSignButton = $('.request-signature__footer__sign-button') + confirmSigSignButton = await queryAsync($, '.request-signature__footer__sign-button') confirmSigSignButton[0].click() - await timeout(2000) - - const txView = $('.tx-view') + const txView = await queryAsync($, '.tx-view') assert.ok(txView[0], 'Should return to the account details screen after confirming') } - -function timeout (time) { - return new Promise((resolve, reject) => { - setTimeout(resolve, time || 1500) - }) -} \ No newline at end of file diff --git a/test/integration/lib/mascara-first-time.js b/test/integration/lib/mascara-first-time.js index 515c7f383..d1afe12a0 100644 --- a/test/integration/lib/mascara-first-time.js +++ b/test/integration/lib/mascara-first-time.js @@ -1,119 +1,95 @@ const PASSWORD = 'password123' const reactTriggerChange = require('react-trigger-change') +const { + timeout, + findAsync, + queryAsync, +} = require('../../lib/util') async function runFirstTimeUsageTest (assert, done) { await timeout(4000) - const app = $('#app-content') + const app = await queryAsync($, '#app-content') await skipNotices(app) - await timeout() - // Scroll through terms - const title = app.find('.create-password__title').text() + const title = await findAsync(app, '.create-password__title').text() assert.equal(title, 'Create Password', 'create password screen') // enter password - const pwBox = app.find('.first-time-flow__input')[0] - const confBox = app.find('.first-time-flow__input')[1] + const pwBox = (await findAsync(app, '.first-time-flow__input'))[0] + const confBox = (await findAsync(app, '.first-time-flow__input'))[1] pwBox.value = PASSWORD confBox.value = PASSWORD reactTriggerChange(pwBox) reactTriggerChange(confBox) - - await timeout() - // Create Password - const createButton = app.find('button.first-time-flow__button')[0] + const createButton = (await findAsync(app, 'button.first-time-flow__button'))[0] createButton.click() - await timeout(3000) - - const created = app.find('.unique-image__title')[0] + const created = (await findAsync(app, '.unique-image__title'))[0] assert.equal(created.textContent, 'Your unique account image', 'unique image screen') // Agree button - let button = app.find('button')[0] + let button = (await findAsync(app, 'button'))[0] assert.ok(button, 'button present') button.click() - await timeout(1000) - await skipNotices(app) // secret backup phrase - const seedTitle = app.find('.backup-phrase__title')[0] + const seedTitle = (await findAsync(app, '.backup-phrase__title'))[0] assert.equal(seedTitle.textContent, 'Secret Backup Phrase', 'seed phrase screen') - app.find('.backup-phrase__reveal-button').click() - - await timeout(1000) - const seedPhrase = app.find('.backup-phrase__secret-words').text().split(' ') - app.find('.first-time-flow__button').click() + ;(await findAsync(app, '.backup-phrase__reveal-button')).click() + const seedPhrase = (await findAsync(app, '.backup-phrase__secret-words')).text().split(' ') + ;(await findAsync(app, '.first-time-flow__button')).click() + await timeout() const selectPhrase = text => { const option = $('.backup-phrase__confirm-seed-option') .filter((i, d) => d.textContent === text)[0] - $(option).click() } - await timeout(1000) - seedPhrase.forEach(sp => selectPhrase(sp)) - app.find('.first-time-flow__button').click() - await timeout(1000) + ;(await findAsync(app, '.first-time-flow__button')).click() // Deposit Ether Screen - const buyEthTitle = app.find('.buy-ether__title')[0] + const buyEthTitle = (await findAsync(app, '.buy-ether__title'))[0] assert.equal(buyEthTitle.textContent, 'Deposit Ether', 'deposit ether screen') - app.find('.buy-ether__do-it-later').click() - await timeout(1000) + ;(await findAsync(app, '.buy-ether__do-it-later')).click() - const menu = app.find('.account-menu__icon')[0] + const menu = (await findAsync(app, '.account-menu__icon'))[0] menu.click() - await timeout() - - const lock = app.find('.account-menu__logout-button')[0] + const lock = (await findAsync(app, '.account-menu__logout-button'))[0] assert.ok(lock, 'Lock menu item found') lock.click() - await timeout(1000) - - const pwBox2 = app.find('#password-box')[0] + const pwBox2 = (await findAsync(app, '#password-box'))[0] pwBox2.value = PASSWORD - const createButton2 = app.find('button.primary')[0] + const createButton2 = (await findAsync(app, 'button.primary'))[0] createButton2.click() - await timeout(1000) - - const detail2 = app.find('.wallet-view')[0] + const detail2 = (await findAsync(app, '.wallet-view'))[0] assert.ok(detail2, 'Account detail section loaded again.') - await timeout() - // open account settings dropdown - const qrButton = app.find('.wallet-view__details-button')[0] + const qrButton = (await findAsync(app, '.wallet-view__details-button'))[0] qrButton.click() - await timeout(1000) - - const qrHeader = app.find('.editable-label__value')[0] - const qrContainer = app.find('.qr-wrapper')[0] + const qrHeader = (await findAsync(app, '.editable-label__value'))[0] + const qrContainer = (await findAsync(app, '.qr-wrapper'))[0] assert.equal(qrHeader.textContent, 'Account 1', 'Should show account label.') assert.ok(qrContainer, 'QR Container found') - await timeout() - - const networkMenu = app.find('.network-component')[0] + const networkMenu = (await findAsync(app, '.network-component'))[0] networkMenu.click() - await timeout() - - const networkMenu2 = app.find('.network-indicator')[0] + const networkMenu2 = (await findAsync(app, '.network-indicator'))[0] const children2 = networkMenu2.children children2.length[3] assert.ok(children2, 'All network options present') @@ -121,18 +97,12 @@ async function runFirstTimeUsageTest (assert, done) { module.exports = runFirstTimeUsageTest -function timeout (time) { - return new Promise((resolve, reject) => { - setTimeout(resolve, time || 1500) - }) -} - async function skipNotices (app) { while (true) { - const button = app.find('button') + const button = await findAsync(app, 'button') if (button && button.html() === 'Accept') { // still notices to accept - const termsPage = app.find('.markdown')[0] + const termsPage = (await findAsync(app, '.markdown'))[0] if (!termsPage) { break } From 4bc69f72c3033cc9ea3e732f48da22d15c41a972 Mon Sep 17 00:00:00 2001 From: kumavis Date: Sun, 11 Mar 2018 21:39:46 -0700 Subject: [PATCH 13/16] test - mascara - fix async wrap --- test/integration/lib/mascara-first-time.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/lib/mascara-first-time.js b/test/integration/lib/mascara-first-time.js index d1afe12a0..bcbc94ff6 100644 --- a/test/integration/lib/mascara-first-time.js +++ b/test/integration/lib/mascara-first-time.js @@ -14,7 +14,7 @@ async function runFirstTimeUsageTest (assert, done) { await skipNotices(app) // Scroll through terms - const title = await findAsync(app, '.create-password__title').text() + const title = (await findAsync(app, '.create-password__title')).text() assert.equal(title, 'Create Password', 'create password screen') // enter password From 0dad6db9736f2b90000c489b0b452c8d2fa02bb3 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 12 Mar 2018 14:29:26 -0230 Subject: [PATCH 14/16] Styling fixes to welcome; hide network component on create password; shown welcoem in popup. --- mascara/src/app/first-time/create-password-screen.js | 2 +- ui/app/app.js | 4 ++-- ui/app/css/itcss/components/welcome-screen.scss | 4 ++-- ui/app/welcome-screen.js | 7 +++---- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/mascara/src/app/first-time/create-password-screen.js b/mascara/src/app/first-time/create-password-screen.js index b56c183e6..37294b9b5 100644 --- a/mascara/src/app/first-time/create-password-screen.js +++ b/mascara/src/app/first-time/create-password-screen.js @@ -56,7 +56,7 @@ class CreatePasswordScreen extends Component { render () { const { isLoading, goToImportWithSeedPhrase, isMascara } = this.props - // + return isLoading ? : ( diff --git a/ui/app/app.js b/ui/app/app.js index 11b761639..50514bd3b 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -298,7 +298,7 @@ App.prototype.renderAppBar = function () { ]), ]), - h('div.header__right-actions', [ + betaUI && isInitialized && h('div.header__right-actions', [ h('div.network-component-wrapper', { style: {}, }, [ @@ -385,7 +385,7 @@ App.prototype.renderPrimary = function () { const isMascaraOnboarding = isMascara && isOnboarding const isBetaUIOnboarding = betaUI && isOnboarding && !props.isPopup && !isRevealingSeedWords - if (!welcomeScreenSeen && isBetaUIOnboarding && !isInitialized && !isUnlocked) { + if (!welcomeScreenSeen && betaUI && !isInitialized && !isUnlocked) { return h(WelcomeScreen) } diff --git a/ui/app/css/itcss/components/welcome-screen.scss b/ui/app/css/itcss/components/welcome-screen.scss index dc8b38399..86fc7d04d 100644 --- a/ui/app/css/itcss/components/welcome-screen.scss +++ b/ui/app/css/itcss/components/welcome-screen.scss @@ -6,7 +6,7 @@ font-family: Roboto; font-weight: 400; width: 100%; - height: 100%; + flex: 1 0 auto; padding: 70px 0; background: $white; @@ -44,4 +44,4 @@ transition: 200ms ease-in-out; background-color: rgba(247, 134, 28, 0.9); } -} \ No newline at end of file +} diff --git a/ui/app/welcome-screen.js b/ui/app/welcome-screen.js index 0c1aced8c..cdbb6dba8 100644 --- a/ui/app/welcome-screen.js +++ b/ui/app/welcome-screen.js @@ -11,8 +11,8 @@ class WelcomeScreen extends Component { closeWelcomeScreen: PropTypes.func.isRequired, } - constructor () { - super() + constructor(props) { + super(props) this.animationEventEmitter = new EventEmitter() } @@ -21,7 +21,6 @@ class WelcomeScreen extends Component { } render () { - // t return h('div.welcome-screen', [ h('div.welcome-screen__info', [ @@ -32,7 +31,7 @@ class WelcomeScreen extends Component { height: '225', }), - h('div.welcome-screen__info__header', 'Welcome to MetaMask Beta.'), + h('div.welcome-screen__info__header', 'Welcome to MetaMask Beta'), h('div.welcome-screen__info__copy', 'MetaMask is a secure identity vault for Ethereum.'), From 70f33d47472863e3fce41eff60c1fe078efef7de Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 12 Mar 2018 20:17:44 -0230 Subject: [PATCH 15/16] Left align create password. --- .../app/first-time/create-password-screen.js | 2 +- mascara/src/app/first-time/index.css | 18 +++++++++--------- .../css/itcss/components/welcome-screen.scss | 12 ++++++++++++ 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/mascara/src/app/first-time/create-password-screen.js b/mascara/src/app/first-time/create-password-screen.js index 37294b9b5..192da3399 100644 --- a/mascara/src/app/first-time/create-password-screen.js +++ b/mascara/src/app/first-time/create-password-screen.js @@ -60,7 +60,7 @@ class CreatePasswordScreen extends Component { return isLoading ? : ( -
+
Date: Wed, 14 Mar 2018 00:15:19 +1100 Subject: [PATCH 16/16] Moved mock-dev.js and ui-dev.js to development folder. --- mock-dev.js => development/mock-dev.js | 22 +++++++++++----------- ui-dev.js => development/ui-dev.js | 10 +++++----- package.json | 6 +++--- 3 files changed, 19 insertions(+), 19 deletions(-) rename mock-dev.js => development/mock-dev.js (82%) rename ui-dev.js => development/ui-dev.js (89%) diff --git a/mock-dev.js b/development/mock-dev.js similarity index 82% rename from mock-dev.js rename to development/mock-dev.js index 6627c1153..a1fb3a86d 100644 --- a/mock-dev.js +++ b/development/mock-dev.js @@ -15,16 +15,16 @@ const extend = require('xtend') const render = require('react-dom').render const h = require('react-hyperscript') -const Root = require('./ui/app/root') -const configureStore = require('./ui/app/store') -const actions = require('./ui/app/actions') -const states = require('./development/states') -const backGroundConnectionModifiers = require('./development/backGroundConnectionModifiers') -const Selector = require('./development/selector') -const MetamaskController = require('./app/scripts/metamask-controller') -const firstTimeState = require('./app/scripts/first-time-state') -const ExtensionPlatform = require('./app/scripts/platforms/extension') -const extension = require('./development/mockExtension') +const Root = require('../ui/app/root') +const configureStore = require('../ui/app/store') +const actions = require('../ui/app/actions') +const states = require('./states') +const backGroundConnectionModifiers = require('./backGroundConnectionModifiers') +const Selector = require('./selector') +const MetamaskController = require('../app/scripts/metamask-controller') +const firstTimeState = require('../app/scripts/first-time-state') +const ExtensionPlatform = require('../app/scripts/platforms/extension') +const extension = require('./mockExtension') const noop = function () {} const log = require('loglevel') @@ -51,7 +51,7 @@ function updateQueryParams(newView) { // CSS // -const MetaMaskUiCss = require('./ui/css') +const MetaMaskUiCss = require('../ui/css') const injectCss = require('inject-css') // diff --git a/ui-dev.js b/development/ui-dev.js similarity index 89% rename from ui-dev.js rename to development/ui-dev.js index 620d81667..cac433909 100644 --- a/ui-dev.js +++ b/development/ui-dev.js @@ -17,10 +17,10 @@ const render = require('react-dom').render const h = require('react-hyperscript') -const Root = require('./ui/app/root') -const configureStore = require('./development/uiStore') -const states = require('./development/states') -const Selector = require('./development/selector') +const Root = require('../ui/app/root') +const configureStore = require('./uiStore') +const states = require('./states') +const Selector = require('./selector') // logger const log = require('loglevel') @@ -35,7 +35,7 @@ const firstState = states[selectedView] updateQueryParams(selectedView) // CSS -const MetaMaskUiCss = require('./ui/css') +const MetaMaskUiCss = require('../ui/css') const injectCss = require('inject-css') diff --git a/package.json b/package.json index c5d9d3c45..8921cc1b4 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,8 @@ "scripts": { "start": "npm run dev", "dev": "gulp dev --debug", - "ui": "npm run test:flat:build:states && beefy ui-dev.js:bundle.js --live --open --index=./development/index.html --cwd ./", - "mock": "beefy mock-dev.js:bundle.js --live --open --index=./development/index.html --cwd ./", + "ui": "npm run test:flat:build:states && beefy development/ui-dev.js:bundle.js --live --open --index=./development/index.html --cwd ./", + "mock": "beefy development/mock-dev.js:bundle.js --live --open --index=./development/index.html --cwd ./", "watch": "mocha watch --recursive \"test/unit/**/*.js\"", "mascara": "gulp build && METAMASK_DEBUG=true node ./mascara/example/server", "dist": "npm run dist:clear && npm install && gulp dist", @@ -23,7 +23,7 @@ "test:flat:build": "npm run test:flat:build:ui && npm run test:flat:build:tests", "test:flat:build:tests": "node test/integration/index.js", "test:flat:build:states": "node development/genStates.js", - "test:flat:build:ui": "npm run test:flat:build:states && browserify ./mock-dev.js -o ./development/bundle.js", + "test:flat:build:ui": "npm run test:flat:build:states && browserify ./development/mock-dev.js -o ./development/bundle.js", "test:mascara": "npm run test:mascara:build && karma start test/mascara.conf.js", "test:mascara:build": "mkdir -p dist/mascara && npm run test:mascara:build:ui && npm run test:mascara:build:background && npm run test:mascara:build:tests", "test:mascara:build:ui": "browserify mascara/test/test-ui.js -o dist/mascara/ui.js",