From 2c410f534d2b8ed9685210528fbe455b8692e9c4 Mon Sep 17 00:00:00 2001 From: igorms-cons <89637087+igorms-cons@users.noreply.github.com> Date: Tue, 9 Nov 2021 11:58:21 +0100 Subject: [PATCH 01/62] Fix/ux papercuts account details issue #12292 (#12399) * account details - updating ui * account details - updating ui - version 2 * update qr-code scss in details account view * account detail screen - create local eng label * account detail update copy state --- app/_locales/en/messages.json | 3 ++ .../account-details-modal.component.js | 4 +-- .../modals/account-details-modal/index.scss | 4 +-- ui/components/app/modals/modal.js | 2 +- ui/components/ui/qr-code/index.scss | 35 +++++++++++++++++-- ui/components/ui/qr-code/qr-code.js | 24 ++++++++++++- ui/css/design-system/colors.scss | 2 ++ 7 files changed, 65 insertions(+), 9 deletions(-) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index f97b24f9b..15fb036c8 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -901,6 +901,9 @@ "etherscanView": { "message": "View account on Etherscan" }, + "etherscanViewOn": { + "message": "View on Etherscan" + }, "expandView": { "message": "Expand view" }, diff --git a/ui/components/app/modals/account-details-modal/account-details-modal.component.js b/ui/components/app/modals/account-details-modal/account-details-modal.component.js index 858fc5999..1df675a01 100644 --- a/ui/components/app/modals/account-details-modal/account-details-modal.component.js +++ b/ui/components/app/modals/account-details-modal/account-details-modal.component.js @@ -84,9 +84,7 @@ export default class AccountDetailsModal extends Component { ? this.context.t('blockExplorerView', [ getURLHostName(rpcPrefs.blockExplorerUrl), ]) - : this.context.t('viewOnEtherscan', [ - this.context.t('blockExplorerAccountAction'), - ])} + : this.context.t('etherscanViewOn')} {exportPrivateKeyFeatureEnabled ? ( diff --git a/ui/components/app/modals/account-details-modal/index.scss b/ui/components/app/modals/account-details-modal/index.scss index ecab51311..3eedab80c 100644 --- a/ui/components/app/modals/account-details-modal/index.scss +++ b/ui/components/app/modals/account-details-modal/index.scss @@ -8,13 +8,13 @@ & &__button { margin-top: 17px; padding: 10px 22px; - width: 286px; + width: 284px; } &__divider { width: 100%; height: 1px; - margin: 19px 0 8px 0; + margin: 16px 0 8px 0; background-color: $alto; } diff --git a/ui/components/app/modals/modal.js b/ui/components/app/modals/modal.js index 16a5d4807..c31cba238 100644 --- a/ui/components/app/modals/modal.js +++ b/ui/components/app/modals/modal.js @@ -64,7 +64,7 @@ const accountModalStyle = { margin: '0 auto', }, laptopModalStyle: { - width: '360px', + width: '335px', // top: 'calc(33% + 45px)', boxShadow: 'rgba(0, 0, 0, 0.15) 0px 2px 2px 2px', borderRadius: '4px', diff --git a/ui/components/ui/qr-code/index.scss b/ui/components/ui/qr-code/index.scss index c228ffeda..03ba8fc08 100644 --- a/ui/components/ui/qr-code/index.scss +++ b/ui/components/ui/qr-code/index.scss @@ -25,10 +25,41 @@ margin-bottom: 9px; } + &__address-container { + display: flex; + justify-content: center; + + &__tooltip-wrapper { + width: 100%; + } + + &:hover { + cursor: pointer; + + .qr-code__copy-icon__svg { + fill: $primary-1; + } + } + } + &__address { @include H7; - background-color: $ui-1; - padding: 12px; + background-color: $Grey-000; + width: 76%; + padding: 8px 12px; + word-break: break-all; + text-align: center; + } + + &__copy-icon { + height: 13px; + padding: 17px 0; + position: absolute; + right: 24px; + + &__svg { + fill: $ui-5; + } } } diff --git a/ui/components/ui/qr-code/qr-code.js b/ui/components/ui/qr-code/qr-code.js index 89ce505ab..69921e260 100644 --- a/ui/components/ui/qr-code/qr-code.js +++ b/ui/components/ui/qr-code/qr-code.js @@ -3,7 +3,11 @@ import React from 'react'; import qrCode from 'qrcode-generator'; import { connect } from 'react-redux'; import { isHexPrefixed } from 'ethereumjs-util'; +import { useCopyToClipboard } from '../../../hooks/useCopyToClipboard'; import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; +import Tooltip from '../tooltip'; +import CopyIcon from '../icon/copy-icon.component'; +import { useI18nContext } from '../../../hooks/useI18nContext'; export default connect(mapStateToProps)(QrCodeView); @@ -22,6 +26,8 @@ function QrCodeView(props) { const address = `${ isHexPrefixed(data) ? 'ethereum:' : '' }${toChecksumHexAddress(data)}`; + const [copied, handleCopy] = useCopyToClipboard(); + const t = useI18nContext(); const qrImage = qrCode(4, 'M'); qrImage.addData(address); qrImage.make(); @@ -50,7 +56,23 @@ function QrCodeView(props) { __html: qrImage.createTableTag(4), }} /> -
{toChecksumHexAddress(data)}
+ +
{ + handleCopy(toChecksumHexAddress(data)); + }} + > +
{toChecksumHexAddress(data)}
+
+ +
+
+
); } diff --git a/ui/css/design-system/colors.scss b/ui/css/design-system/colors.scss index bda23ce09..d76de5ef6 100644 --- a/ui/css/design-system/colors.scss +++ b/ui/css/design-system/colors.scss @@ -103,6 +103,7 @@ $ui-1: #f2f3f4; $ui-2: #d6d9dc; $ui-3: #bbc0c5; $ui-4: #6a737d; +$ui-5: #c4c4c4; $mainnet: #29b6af; $ropsten: #ff4a8d; @@ -116,6 +117,7 @@ $color-map: ( 'ui-2': $ui-2, 'ui-3': $ui-3, 'ui-4': $ui-4, + 'ui-5': $ui-5, 'white': $ui-white, 'black': $ui-black, 'grey': $ui-grey, From a49a40fbbb695e01c8bbbeb7d3330090209a5ed2 Mon Sep 17 00:00:00 2001 From: Jyoti Puri Date: Wed, 10 Nov 2021 07:37:10 +0530 Subject: [PATCH 02/62] Adding GasFee context (#12530) Adding GasFee context --- .../confirm-page-container-container.test.js | 10 + .../confirm-page-container.component.js | 185 +++++++++--------- ui/contexts/gasFee.js | 37 ++++ ui/hooks/gasFeeInput/useGasFeeErrors.js | 7 +- ui/hooks/gasFeeInput/useGasFeeInputs.js | 3 +- 5 files changed, 148 insertions(+), 94 deletions(-) create mode 100644 ui/contexts/gasFee.js diff --git a/ui/components/app/confirm-page-container/confirm-page-container-container.test.js b/ui/components/app/confirm-page-container/confirm-page-container-container.test.js index 9ddf77de8..fc0a5f669 100644 --- a/ui/components/app/confirm-page-container/confirm-page-container-container.test.js +++ b/ui/components/app/confirm-page-container/confirm-page-container-container.test.js @@ -10,6 +10,14 @@ import ConfirmPageContainer, { ConfirmPageContainerNavigation, } from '.'; +jest.mock('../../../store/actions', () => ({ + disconnectGasFeeEstimatePoller: jest.fn(), + getGasFeeEstimatesAndStartPolling: jest + .fn() + .mockImplementation(() => Promise.resolve()), + addPollingTokenToAppState: jest.fn(), +})); + describe('Confirm Page Container Container Test', () => { let wrapper; @@ -31,6 +39,8 @@ describe('Confirm Page Container Container Test', () => { selectedAddress: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5', addressBook: [], chainId: 'test', + identities: [], + featureFlags: {}, }, }; diff --git a/ui/components/app/confirm-page-container/confirm-page-container.component.js b/ui/components/app/confirm-page-container/confirm-page-container.component.js index 7a4eb0e10..117318e3d 100644 --- a/ui/components/app/confirm-page-container/confirm-page-container.component.js +++ b/ui/components/app/confirm-page-container/confirm-page-container.component.js @@ -4,6 +4,7 @@ import SenderToRecipient from '../../ui/sender-to-recipient'; import { PageContainerFooter } from '../../ui/page-container'; import EditGasPopover from '../edit-gas-popover'; import { EDIT_GAS_MODES } from '../../../../shared/constants/gas'; +import { GasFeeContextProvider } from '../../../contexts/gasFee'; import ErrorMessage from '../../ui/error-message'; import { TRANSACTION_TYPES } from '../../../../shared/constants/transaction'; import Dialog from '../../ui/dialog'; @@ -135,102 +136,104 @@ export default class ConfirmPageContainer extends Component { currentTransaction.txParams?.value === '0x0'; return ( -
- onNextTx(txId)} - firstTx={firstTx} - lastTx={lastTx} - ofText={ofText} - requestsWaitingText={requestsWaitingText} - /> - onEdit()} - showAccountInHeader={showAccountInHeader} - accountAddress={fromAddress} - > - {hideSenderToRecipient ? null : ( - +
+ onNextTx(txId)} + firstTx={firstTx} + lastTx={lastTx} + ofText={ofText} + requestsWaitingText={requestsWaitingText} + /> + onEdit()} + showAccountInHeader={showAccountInHeader} + accountAddress={fromAddress} + > + {hideSenderToRecipient ? null : ( + + )} + +
+ {showAddToAddressDialog && ( + showAddToAddressBookModal()} + > + {this.context.t('newAccountDetectedDialogMessage')} + + )} +
+ {contentComponent || ( + )} - -
- {showAddToAddressDialog && ( - showAddToAddressBookModal()} + {shouldDisplayWarning && ( +
+ +
+ )} + {contentComponent && ( + - {this.context.t('newAccountDetectedDialogMessage')} -
+ {unapprovedTxCount > 1 && ( + + {this.context.t('rejectTxsN', [unapprovedTxCount])} + + )} + + )} + {editingGas && ( + )}
- {contentComponent || ( - - )} - {shouldDisplayWarning && ( -
- -
- )} - {contentComponent && ( - - {unapprovedTxCount > 1 && ( - - {this.context.t('rejectTxsN', [unapprovedTxCount])} - - )} - - )} - {editingGas && ( - - )} -
+ ); } } diff --git a/ui/contexts/gasFee.js b/ui/contexts/gasFee.js new file mode 100644 index 000000000..c7fe7f092 --- /dev/null +++ b/ui/contexts/gasFee.js @@ -0,0 +1,37 @@ +import React, { createContext, useContext } from 'react'; +import PropTypes from 'prop-types'; +import { useGasFeeInputs } from '../hooks/gasFeeInput/useGasFeeInputs'; + +export const GasFeeContext = createContext({}); + +export const GasFeeContextProvider = ({ + children, + defaultEstimateToUse, + transaction, + minimumGasLimit, + editGasMode, +}) => { + const gasFeeDetails = useGasFeeInputs( + defaultEstimateToUse, + transaction, + minimumGasLimit, + editGasMode, + ); + return ( + + {children} + + ); +}; + +export function useGasFeeContext() { + return useContext(GasFeeContext); +} + +GasFeeContextProvider.propTypes = { + children: PropTypes.node.isRequired, + defaultEstimateToUse: PropTypes.string, + transaction: PropTypes.object.isRequired, + minimumGasLimit: PropTypes.string, + editGasMode: PropTypes.string, +}; diff --git a/ui/hooks/gasFeeInput/useGasFeeErrors.js b/ui/hooks/gasFeeInput/useGasFeeErrors.js index d477087d0..0300feec0 100644 --- a/ui/hooks/gasFeeInput/useGasFeeErrors.js +++ b/ui/hooks/gasFeeInput/useGasFeeErrors.js @@ -130,7 +130,10 @@ const getMaxFeeWarning = ( return undefined; }; -const getBalanceError = (minimumCostInHexWei, transaction, ethBalance) => { +const hasBalanceError = (minimumCostInHexWei, transaction, ethBalance) => { + if (minimumCostInHexWei === undefined || ethBalance === undefined) { + return false; + } const minimumTxCostInHexWei = addHexes( minimumCostInHexWei, transaction?.txParams?.value || '0x0', @@ -247,7 +250,7 @@ export function useGasFeeErrors({ ); const { balance: ethBalance } = useSelector(getSelectedAccount); - const balanceError = getBalanceError( + const balanceError = hasBalanceError( minimumCostInHexWei, transaction, ethBalance, diff --git a/ui/hooks/gasFeeInput/useGasFeeInputs.js b/ui/hooks/gasFeeInput/useGasFeeInputs.js index e67bd031f..80d18df98 100644 --- a/ui/hooks/gasFeeInput/useGasFeeInputs.js +++ b/ui/hooks/gasFeeInput/useGasFeeInputs.js @@ -3,6 +3,7 @@ import { useSelector } from 'react-redux'; import { getAdvancedInlineGasShown } from '../../selectors'; import { hexToDecimal } from '../../helpers/utils/conversions.util'; +import { EDIT_GAS_MODES } from '../../../shared/constants/gas'; import { GAS_FORM_ERRORS } from '../../helpers/constants/gas'; import { GAS_RECOMMENDATIONS, @@ -65,7 +66,7 @@ export function useGasFeeInputs( defaultEstimateToUse = GAS_RECOMMENDATIONS.MEDIUM, transaction, minimumGasLimit = '0x5208', - editGasMode, + editGasMode = EDIT_GAS_MODES.MODIFY_IN_PLACE, ) { // We need the gas estimates from the GasFeeController in the background. // Calling this hooks initiates polling for new gas estimates and returns the From a13d8583a091299c09f8b06eb72372857119248c Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Wed, 10 Nov 2021 06:30:42 -0330 Subject: [PATCH 03/62] Fix flaky account removal e2e test (#12607) * Add delay to fix flaky account removal e2e test * Await for element to update instead of awaiting an arbitrary delay * Update test/e2e/tests/from-import-ui.spec.js Co-authored-by: Mark Stacey * code formatting * Remove redundant code Co-authored-by: Mark Stacey Co-authored-by: PeterYinusa --- test/e2e/tests/from-import-ui.spec.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/test/e2e/tests/from-import-ui.spec.js b/test/e2e/tests/from-import-ui.spec.js index 0bd3b683a..5c0e0c8ee 100644 --- a/test/e2e/tests/from-import-ui.spec.js +++ b/test/e2e/tests/from-import-ui.spec.js @@ -233,10 +233,15 @@ describe('Metamask Import UI', function () { // should remove the account await driver.clickElement({ text: 'Remove', tag: 'button' }); - const currentActiveAccountName = await driver.findElement( - '.selected-account__name', + // Wait until selected account switches away from removed account to first account + await driver.waitForSelector( + { + css: '.selected-account__name', + text: 'Account 1', + }, + { timeout: 10000 }, ); - assert.equal(await currentActiveAccountName.getText(), 'Account 1'); + await driver.delay(regularDelayMs); await driver.clickElement('.account-menu__icon'); From ab2aca2c0802a1223e976add7a4e3cf0997b96ec Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Wed, 10 Nov 2021 10:54:17 -0330 Subject: [PATCH 04/62] Fix lint errors (#12645) These lint errors were accidentally introduced recently as a result of merging #12530 and #12461 --- ui/hooks/gasFeeInput/useGasFeeInputs.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ui/hooks/gasFeeInput/useGasFeeInputs.js b/ui/hooks/gasFeeInput/useGasFeeInputs.js index 80d18df98..96ad40f73 100644 --- a/ui/hooks/gasFeeInput/useGasFeeInputs.js +++ b/ui/hooks/gasFeeInput/useGasFeeInputs.js @@ -3,12 +3,13 @@ import { useSelector } from 'react-redux'; import { getAdvancedInlineGasShown } from '../../selectors'; import { hexToDecimal } from '../../helpers/utils/conversions.util'; -import { EDIT_GAS_MODES } from '../../../shared/constants/gas'; -import { GAS_FORM_ERRORS } from '../../helpers/constants/gas'; import { + EDIT_GAS_MODES, GAS_RECOMMENDATIONS, CUSTOM_GAS_ESTIMATE, } from '../../../shared/constants/gas'; +import { GAS_FORM_ERRORS } from '../../helpers/constants/gas'; + import { useGasFeeEstimates } from '../useGasFeeEstimates'; import { useGasFeeErrors } from './useGasFeeErrors'; From dc19e1d5f63bf17442eddc59ae2ee65d1c442c6a Mon Sep 17 00:00:00 2001 From: PeterYinusa <53189696+PeterYinusa@users.noreply.github.com> Date: Wed, 10 Nov 2021 17:27:10 +0000 Subject: [PATCH 05/62] Onboarding v2 e2e test (#12628) * add data-testid's * import wallet test * create wallet test * fix lint issues --- test/e2e/tests/from-import-ui.spec.js | 84 +++++--- test/e2e/tests/metamask-responsive-ui.spec.js | 180 ++++++++++++------ ui/components/ui/chip/chip-with-input.js | 3 + ui/components/ui/chip/chip.js | 3 + ui/components/ui/form-field/form-field.js | 3 + .../create-password/create-password.js | 8 + .../creation-successful.js | 8 +- .../onboarding-flow/import-srp/import-srp.js | 2 + .../metametrics/metametrics.js | 12 +- .../pin-extension/pin-extension.js | 3 + .../confirm-recovery-phrase.js | 1 + .../recovery-phrase/recovery-phrase-chips.js | 8 +- .../recovery-phrase/review-recovery-phrase.js | 2 + .../secure-your-wallet/secure-your-wallet.js | 9 +- .../skip-srp-backup-popover.js | 1 + ui/pages/onboarding-flow/welcome/welcome.js | 12 +- 16 files changed, 245 insertions(+), 94 deletions(-) diff --git a/test/e2e/tests/from-import-ui.spec.js b/test/e2e/tests/from-import-ui.spec.js index 5c0e0c8ee..a83a9bbbb 100644 --- a/test/e2e/tests/from-import-ui.spec.js +++ b/test/e2e/tests/from-import-ui.spec.js @@ -27,38 +27,72 @@ describe('Metamask Import UI', function () { async ({ driver }) => { await driver.navigate(); - // clicks the continue button on the welcome screen - await driver.findElement('.welcome-page__header'); - await driver.clickElement({ - text: enLocaleMessages.getStarted.message, - tag: 'button', - }); + if (process.env.ONBOARDING_V2 === '1') { + // welcome + await driver.clickElement('[data-testid="onboarding-import-wallet"]'); - // clicks the "Import Wallet" option - await driver.clickElement({ text: 'Import wallet', tag: 'button' }); + // metrics + await driver.clickElement('[data-testid="metametrics-no-thanks"]'); - // clicks the "No thanks" option on the metametrics opt-in screen - await driver.clickElement('.btn-secondary'); + // import with recovery phrase + await driver.fill('[data-testid="import-srp-text"]', testSeedPhrase); + await driver.clickElement('[data-testid="import-srp-confirm"]'); - // Import Secret Recovery Phrase - await driver.fill( - 'input[placeholder="Paste Secret Recovery Phrase from clipboard"]', - testSeedPhrase, - ); + // create password + await driver.fill( + '[data-testid="create-password-new"]', + 'correct horse battery staple', + ); + await driver.fill( + '[data-testid="create-password-confirm"]', + 'correct horse battery staple', + ); + await driver.clickElement('[data-testid="create-password-terms"]'); + await driver.clickElement('[data-testid="create-password-import"]'); - await driver.fill('#password', 'correct horse battery staple'); - await driver.fill('#confirm-password', 'correct horse battery staple'); + // complete + await driver.clickElement('[data-testid="onboarding-complete-done"]'); - await driver.clickElement('.first-time-flow__terms'); + // pin extension + await driver.clickElement('[data-testid="pin-extension-next"]'); + await driver.clickElement('[data-testid="pin-extension-done"]'); + } else { + // clicks the continue button on the welcome screen + await driver.findElement('.welcome-page__header'); + await driver.clickElement({ + text: enLocaleMessages.getStarted.message, + tag: 'button', + }); - await driver.clickElement({ text: 'Import', tag: 'button' }); + // clicks the "Import Wallet" option + await driver.clickElement({ text: 'Import wallet', tag: 'button' }); - // clicks through the success screen - await driver.findElement({ text: 'Congratulations', tag: 'div' }); - await driver.clickElement({ - text: enLocaleMessages.endOfFlowMessage10.message, - tag: 'button', - }); + // clicks the "No thanks" option on the metametrics opt-in screen + await driver.clickElement('.btn-secondary'); + + // Import Secret Recovery Phrase + await driver.fill( + 'input[placeholder="Paste Secret Recovery Phrase from clipboard"]', + testSeedPhrase, + ); + + await driver.fill('#password', 'correct horse battery staple'); + await driver.fill( + '#confirm-password', + 'correct horse battery staple', + ); + + await driver.clickElement('.first-time-flow__terms'); + + await driver.clickElement({ text: 'Import', tag: 'button' }); + + // clicks through the success screen + await driver.findElement({ text: 'Congratulations', tag: 'div' }); + await driver.clickElement({ + text: enLocaleMessages.endOfFlowMessage10.message, + tag: 'button', + }); + } // Show account information await driver.clickElement( diff --git a/test/e2e/tests/metamask-responsive-ui.spec.js b/test/e2e/tests/metamask-responsive-ui.spec.js index e512ce9f4..adb5ad644 100644 --- a/test/e2e/tests/metamask-responsive-ui.spec.js +++ b/test/e2e/tests/metamask-responsive-ui.spec.js @@ -16,50 +16,6 @@ describe('Metamask Responsive UI', function () { async ({ driver }) => { await driver.navigate(); - // clicks the continue button on the welcome screen - await driver.findElement('.welcome-page__header'); - await driver.clickElement({ - text: enLocaleMessages.getStarted.message, - tag: 'button', - }); - await driver.delay(tinyDelayMs); - - // clicks the "Create New Wallet" option - await driver.clickElement({ text: 'Create a Wallet', tag: 'button' }); - - // clicks the "I Agree" option on the metametrics opt-in screen - await driver.clickElement('.btn-primary'); - - // accepts a secure password - await driver.fill( - '.first-time-flow__form #create-password', - 'correct horse battery staple', - ); - await driver.fill( - '.first-time-flow__form #confirm-password', - 'correct horse battery staple', - ); - await driver.clickElement('.first-time-flow__checkbox'); - await driver.clickElement('.first-time-flow__form button'); - - // renders the Secret Recovery Phrase intro screen - await driver.clickElement('.seed-phrase-intro__left button'); - - // reveals the Secret Recovery Phrase - await driver.clickElement( - '.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button', - ); - const revealedSeedPhrase = await driver.findElement( - '.reveal-seed-phrase__secret-words', - ); - const seedPhrase = await revealedSeedPhrase.getText(); - assert.equal(seedPhrase.split(' ').length, 12); - - await driver.clickElement({ - text: enLocaleMessages.next.message, - tag: 'button', - }); - async function clickWordAndWait(word) { await driver.clickElement( `[data-testid="seed-phrase-sorted"] [data-testid="draggable-seed-${word}"]`, @@ -67,26 +23,126 @@ describe('Metamask Responsive UI', function () { await driver.delay(tinyDelayMs); } - // can retype the Secret Recovery Phrase - const words = seedPhrase.split(' '); - for (const word of words) { - await clickWordAndWait(word); + if (process.env.ONBOARDING_V2 === '1') { + // welcome + await driver.clickElement('[data-testid="onboarding-create-wallet"]'); + + // metrics + await driver.clickElement('[data-testid="metametrics-no-thanks"]'); + + // create password + await driver.fill( + '[data-testid="create-password-new"]', + 'correct horse battery staple', + ); + await driver.fill( + '[data-testid="create-password-confirm"]', + 'correct horse battery staple', + ); + await driver.clickElement('[data-testid="create-password-terms"]'); + await driver.clickElement('[data-testid="create-password-wallet"]'); + + // secure wallet + await driver.clickElement( + '[data-testid="secure-wallet-recommended"]', + ); + + // review + await driver.clickElement('[data-testid="recovery-phrase-reveal"]'); + const chipTwo = await ( + await driver.findElement('[data-testid="recovery-phrase-chip-2"]') + ).getText(); + const chipThree = await ( + await driver.findElement('[data-testid="recovery-phrase-chip-3"]') + ).getText(); + const chipSeven = await ( + await driver.findElement('[data-testid="recovery-phrase-chip-7"]') + ).getText(); + await driver.clickElement('[data-testid="recovery-phrase-next"]'); + + // confirm + await driver.fill('[data-testid="recovery-phrase-input-2"]', chipTwo); + await driver.fill( + '[data-testid="recovery-phrase-input-3"]', + chipThree, + ); + await driver.fill( + '[data-testid="recovery-phrase-input-7"]', + chipSeven, + ); + await driver.clickElement('[data-testid="recovery-phrase-confirm"]'); + + // complete + await driver.clickElement('[data-testid="onboarding-complete-done"]'); + + // pin extension + await driver.clickElement('[data-testid="pin-extension-next"]'); + await driver.clickElement('[data-testid="pin-extension-done"]'); + } else { + // clicks the continue button on the welcome screen + await driver.findElement('.welcome-page__header'); + await driver.clickElement({ + text: enLocaleMessages.getStarted.message, + tag: 'button', + }); + await driver.delay(tinyDelayMs); + + // clicks the "Create New Wallet" option + await driver.clickElement({ text: 'Create a Wallet', tag: 'button' }); + + // clicks the "I Agree" option on the metametrics opt-in screen + await driver.clickElement('.btn-primary'); + + // accepts a secure password + await driver.fill( + '.first-time-flow__form #create-password', + 'correct horse battery staple', + ); + await driver.fill( + '.first-time-flow__form #confirm-password', + 'correct horse battery staple', + ); + await driver.clickElement('.first-time-flow__checkbox'); + await driver.clickElement('.first-time-flow__form button'); + + // renders the Secret Recovery Phrase intro screen + await driver.clickElement('.seed-phrase-intro__left button'); + + // reveals the Secret Recovery Phrase + await driver.clickElement( + '.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button', + ); + const revealedSeedPhrase = await driver.findElement( + '.reveal-seed-phrase__secret-words', + ); + const seedPhrase = await revealedSeedPhrase.getText(); + assert.equal(seedPhrase.split(' ').length, 12); + + await driver.clickElement({ + text: enLocaleMessages.next.message, + tag: 'button', + }); + + // can retype the Secret Recovery Phrase + const words = seedPhrase.split(' '); + for (const word of words) { + await clickWordAndWait(word); + } + await driver.clickElement({ text: 'Confirm', tag: 'button' }); + + // clicks through the success screen + await driver.findElement({ text: 'Congratulations', tag: 'div' }); + await driver.clickElement({ + text: enLocaleMessages.endOfFlowMessage10.message, + tag: 'button', + }); } - await driver.clickElement({ text: 'Confirm', tag: 'button' }); - // clicks through the success screen - await driver.findElement({ text: 'Congratulations', tag: 'div' }); - await driver.clickElement({ - text: enLocaleMessages.endOfFlowMessage10.message, - tag: 'button', - }); - - // Show account information - // balance renders - await driver.waitForSelector({ - css: '[data-testid="eth-overview__primary-currency"]', - text: '0 ETH', - }); + // assert balance + const balance = await driver.findElement( + '[data-testid="wallet-balance"]', + ); + assert.ok(/^0\sETH$/u.test(await balance.getText())); }, ); }); diff --git a/ui/components/ui/chip/chip-with-input.js b/ui/components/ui/chip/chip-with-input.js index c6fad92d9..8a5e30cc9 100644 --- a/ui/components/ui/chip/chip-with-input.js +++ b/ui/components/ui/chip/chip-with-input.js @@ -5,6 +5,7 @@ import { COLORS } from '../../../helpers/constants/design-system'; import Chip from '.'; export function ChipWithInput({ + dataTestId, className, borderColor = COLORS.UI1, inputValue, @@ -17,6 +18,7 @@ export function ChipWithInput({ > {setInputValue && ( { @@ -30,6 +32,7 @@ export function ChipWithInput({ } ChipWithInput.propTypes = { + dataTestId: PropTypes.string, borderColor: PropTypes.oneOf(Object.values(COLORS)), className: PropTypes.string, inputValue: PropTypes.string, diff --git a/ui/components/ui/chip/chip.js b/ui/components/ui/chip/chip.js index 6311ea72e..45157fd51 100644 --- a/ui/components/ui/chip/chip.js +++ b/ui/components/ui/chip/chip.js @@ -6,6 +6,7 @@ import Typography from '../typography'; import { COLORS, TYPOGRAPHY } from '../../../helpers/constants/design-system'; export default function Chip({ + dataTestId, className, children, borderColor = COLORS.UI1, @@ -25,6 +26,7 @@ export default function Chip({ return (
)} {error && ( @@ -111,6 +113,7 @@ export default function FormField({ } FormField.propTypes = { + dataTestId: PropTypes.string, titleText: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), titleUnit: PropTypes.string, tooltipText: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), diff --git a/ui/pages/onboarding-flow/create-password/create-password.js b/ui/pages/onboarding-flow/create-password/create-password.js index 66471c67f..fcdbca69a 100644 --- a/ui/pages/onboarding-flow/create-password/create-password.js +++ b/ui/pages/onboarding-flow/create-password/create-password.js @@ -131,6 +131,7 @@ export default function CreatePassword({ >
setTermsChecked(!termsChecked)} checked={termsChecked} /> @@ -190,6 +193,11 @@ export default function CreatePassword({ - diff --git a/ui/pages/onboarding-flow/import-srp/import-srp.js b/ui/pages/onboarding-flow/import-srp/import-srp.js index 7707b5f9b..797aacef4 100644 --- a/ui/pages/onboarding-flow/import-srp/import-srp.js +++ b/ui/pages/onboarding-flow/import-srp/import-srp.js @@ -78,6 +78,7 @@ export default function ImportSRP({ submitSecretRecoveryPhrase }) { />