diff --git a/test/e2e/beta/metamask-beta-ui.spec.js b/test/e2e/beta/metamask-beta-ui.spec.js index 25e25dac4..8ad24e5ea 100644 --- a/test/e2e/beta/metamask-beta-ui.spec.js +++ b/test/e2e/beta/metamask-beta-ui.spec.js @@ -225,19 +225,9 @@ describe('MetaMask', function () { await delay(regularDelayMs) } - await clickWordAndWait(words[0]) - await clickWordAndWait(words[1]) - await clickWordAndWait(words[2]) - await clickWordAndWait(words[3]) - await clickWordAndWait(words[4]) - await clickWordAndWait(words[5]) - await clickWordAndWait(words[6]) - await clickWordAndWait(words[7]) - await clickWordAndWait(words[8]) - await clickWordAndWait(words[9]) - await clickWordAndWait(words[10]) - await clickWordAndWait(words[11]) - + for (let i = 0; i < 12; i++) { + await clickWordAndWait(words[i]) + } } catch (e) { if (count > 2) { throw e @@ -484,7 +474,7 @@ describe('MetaMask', function () { await driver.switchTo().window(extension) await delay(regularDelayMs) - const txListItem = await findElement(driver, By.xpath(`//span[contains(text(), 'Contract Deployment')]`)) + const txListItem = await findElement(driver, By.xpath(`//div[contains(text(), 'Contract Deployment')]`)) await txListItem.click() await delay(regularDelayMs) }) @@ -508,13 +498,15 @@ describe('MetaMask', function () { it('confirms a deploy contract transaction', async () => { const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) await confirmButton.click() - await delay(regularDelayMs) + await delay(largeDelayMs) - const txStatuses = await findElements(driver, By.css('.tx-list-status')) - await driver.wait(until.elementTextMatches(txStatuses[0], /Confirmed/)) + driver.wait(async () => { + const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item')) + return confirmedTxes.length === 3 + }, 10000) - const txAccounts = await findElements(driver, By.css('.tx-list-account')) - assert.equal(await txAccounts[0].getText(), 'Contract Deployment') + const txAction = await findElements(driver, By.css('.transaction-list-item__action')) + await driver.wait(until.elementTextMatches(txAction[0], /Contract\sDeployment/), 10000) await delay(regularDelayMs) }) @@ -535,9 +527,9 @@ describe('MetaMask', function () { await driver.switchTo().window(extension) await delay(largeDelayMs) - await findElements(driver, By.css('.tx-list-pending-item-container')) - const [txListValue] = await findElements(driver, By.css('.tx-list-value')) - await driver.wait(until.elementTextMatches(txListValue, /4\sETH/), 10000) + await findElements(driver, By.css('.transaction-list-item')) + const [txListValue] = await findElements(driver, By.css('.transaction-list-item__amount--secondary')) + await driver.wait(until.elementTextMatches(txListValue, /-4\sETH/), 10000) await txListValue.click() await delay(regularDelayMs) @@ -565,15 +557,20 @@ describe('MetaMask', function () { await confirmButton.click() await delay(regularDelayMs) - const txStatuses = await findElements(driver, By.css('.tx-list-status')) - await driver.wait(until.elementTextMatches(txStatuses[0], /Confirmed/)) + // const txStatuses = await findElements(driver, By.css('.transaction-list-item__status')) + // await driver.wait(until.elementTextMatches(txStatuses[0], /Confirmed/)) + let confirmedTxes + driver.wait(async () => { + confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item')) + return confirmedTxes.length === 4 + }, 10000) - const txValues = await findElement(driver, By.css('.tx-list-value')) - await driver.wait(until.elementTextMatches(txValues, /4\sETH/), 10000) + const txValues = await findElement(driver, By.css('.transaction-list-item__amount--secondary')) + await driver.wait(until.elementTextMatches(txValues, /-4\sETH/), 10000) - const txAccounts = await findElements(driver, By.css('.tx-list-account')) - const firstTxAddress = await txAccounts[0].getText() - assert(firstTxAddress.match(/^0x\w{8}\.{3}\w{4}$/)) + // const txAccounts = await findElements(driver, By.css('.tx-list-account')) + // const firstTxAddress = await txAccounts[0].getText() + // assert(firstTxAddress.match(/^0x\w{8}\.{3}\w{4}$/)) }) it('calls and confirms a contract method where ETH is received', async () => { @@ -595,18 +592,23 @@ describe('MetaMask', function () { await confirmButton.click() await delay(regularDelayMs) - const txStatuses = await findElements(driver, By.css('.tx-list-status')) - await driver.wait(until.elementTextMatches(txStatuses[0], /Confirmed/)) + // const txStatuses = await findElements(driver, By.css('.tx-list-status')) + // await driver.wait(until.elementTextMatches(txStatuses[0], /Confirmed/)) + let confirmedTxes + driver.wait(async () => { + confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item')) + return confirmedTxes.length === 5 + }, 10000) - const txValues = await findElement(driver, By.css('.tx-list-value')) - await driver.wait(until.elementTextMatches(txValues, /0\sETH/), 10000) + const txValues = await findElement(driver, By.css('.transaction-list-item__amount--secondary')) + await driver.wait(until.elementTextMatches(txValues, /-0\sETH/), 10000) await closeAllWindowHandlesExcept(driver, [extension, dapp]) await driver.switchTo().window(extension) }) it('renders the correct ETH balance', async () => { - const balance = await findElement(driver, By.css('.tx-view .balance-display .token-amount')) + const balance = await findElement(driver, By.css('.token-view-balance__primary-balance')) await delay(regularDelayMs) if (process.env.SELENIUM_BROWSER !== 'firefox') { await driver.wait(until.elementTextMatches(balance, /^92.*ETH.*$/), 10000) @@ -651,12 +653,11 @@ describe('MetaMask', function () { await closeAllWindowHandlesExcept(driver, [extension, dapp]) await delay(regularDelayMs) await driver.switchTo().window(extension) - await delay(regularDelayMs) - + await delay(largeDelayMs) }) it('clicks on the Add Token button', async () => { - const addToken = await findElement(driver, By.xpath(`//button[contains(text(), 'Add Token')]`)) + const addToken = await driver.findElement(By.css('.wallet-view__add-token-button')) await addToken.click() await delay(regularDelayMs) }) @@ -680,7 +681,7 @@ describe('MetaMask', function () { }) it('renders the balance for the new token', async () => { - const balance = await findElement(driver, By.css('.tx-view .balance-display .token-amount')) + const balance = await findElement(driver, By.css('.token-view-balance .token-view-balance__token-balance')) await driver.wait(until.elementTextMatches(balance, /^100\s*TST\s*$/)) const tokenAmount = await balance.getText() assert.ok(/^100\s*TST\s*$/.test(tokenAmount)) @@ -761,7 +762,11 @@ describe('MetaMask', function () { await driver.wait(until.elementTextMatches(txValues[0], /-50\sTST/), 10000) } - const txStatuses = await findElements(driver, By.css('.transaction-list-item__status')) + driver.wait(async () => { + const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item')) + return confirmedTxes.length === 1 + }, 10000) + const txStatuses = await findElements(driver, By.css('.transaction-list-item__action')) const tx = await driver.wait(until.elementTextMatches(txStatuses[0], /Outgoing|Failed/), 10000) assert.equal(await tx.getText(), 'Outgoing') }) @@ -786,9 +791,9 @@ describe('MetaMask', function () { await driver.switchTo().window(extension) await delay(largeDelayMs) - await findElements(driver, By.css('.tx-list-pending-item-container')) - const [txListValue] = await findElements(driver, By.css('.tx-list-value')) - await driver.wait(until.elementTextMatches(txListValue, /7\sTST/), 10000) + await findElements(driver, By.css('.transaction-list__pending-transactions')) + const [txListValue] = await findElements(driver, By.css('.transaction-list-item__amount--primary')) + await driver.wait(until.elementTextMatches(txListValue, /-7\sTST/), 10000) await txListValue.click() await delay(regularDelayMs) @@ -835,25 +840,30 @@ describe('MetaMask', function () { }) it('finds the transaction in the transactions list', async function () { - const transactions = await findElements(driver, By.css('.tx-list-item')) - assert.equal(transactions.length, 2) + driver.wait(async () => { + const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item')) + return confirmedTxes.length === 2 + }, 10000) + // const transactions = await findElements(driver, By.css('.transaction-list-item')) + // assert.equal(transactions.length, 2) - const txValues = await findElements(driver, By.css('.tx-list-value')) - await driver.wait(until.elementTextMatches(txValues[0], /7\sTST/)) - const txStatuses = await findElements(driver, By.css('.tx-list-status')) - await driver.wait(until.elementTextMatches(txStatuses[0], /Confirmed/)) + const txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary')) + await driver.wait(until.elementTextMatches(txValues[0], /-7\sTST/)) + const txStatuses = await findElements(driver, By.css('.transaction-list-item__action')) + await driver.wait(until.elementTextMatches(txStatuses[0], /Outgoing/)) const walletBalance = await findElement(driver, By.css('.wallet-balance')) await walletBalance.click() const tokenListItems = await findElements(driver, By.css('.token-list-item')) await tokenListItems[0].click() + await delay(regularDelayMs) // test cancelled on firefox until https://github.com/mozilla/geckodriver/issues/906 is resolved, // or possibly until we use latest version of firefox in the tests if (process.env.SELENIUM_BROWSER !== 'firefox') { - const tokenBalanceAmount = await findElement(driver, By.css('.token-balance__amount')) - assert.equal(await tokenBalanceAmount.getText(), '43') + const tokenBalanceAmount = await findElement(driver, By.css('.token-view-balance__token-balance')) + assert.equal(await tokenBalanceAmount.getText(), '43 TST') } }) }) @@ -877,9 +887,14 @@ describe('MetaMask', function () { await driver.switchTo().window(extension) await delay(regularDelayMs) - const [txListItem] = await findElements(driver, By.css('.tx-list-item')) - const [txListValue] = await findElements(driver, By.css('.tx-list-value')) - await driver.wait(until.elementTextMatches(txListValue, /0\sETH/)) + driver.wait(async () => { + const pendingTxes = await findElements(driver, By.css('.transaction-list__pending-transactions .transaction-list-item')) + return pendingTxes.length === 1 + }, 10000) + + const [txListItem] = await findElements(driver, By.css('.transaction-list-item')) + const [txListValue] = await findElements(driver, By.css('.transaction-list-item__amount--primary')) + await driver.wait(until.elementTextMatches(txListValue, /-7\sTST/)) await txListItem.click() await delay(regularDelayMs) }) @@ -950,10 +965,15 @@ describe('MetaMask', function () { }) it('finds the transaction in the transactions list', async function () { - const txValues = await findElements(driver, By.css('.tx-list-value')) - await driver.wait(until.elementTextMatches(txValues[0], /0\sETH/)) - const txStatuses = await findElements(driver, By.css('.tx-list-status')) - await driver.wait(until.elementTextMatches(txStatuses[0], /Confirmed/)) + driver.wait(async () => { + const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item')) + return confirmedTxes.length === 3 + }, 10000) + + const txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary')) + await driver.wait(until.elementTextMatches(txValues[0], /-7\sTST/)) + const txStatuses = await findElements(driver, By.css('.transaction-list-item__action')) + await driver.wait(until.elementTextMatches(txStatuses[0], /Approve/)) }) }) @@ -1003,7 +1023,7 @@ describe('MetaMask', function () { }) it('renders the balance for the chosen token', async () => { - const balance = await findElement(driver, By.css('.tx-view .balance-display .token-amount')) + const balance = await findElement(driver, By.css('.balance-display .token-amount')) await driver.wait(until.elementTextMatches(balance, /0\sBAT/)) await delay(regularDelayMs) }) diff --git a/ui/app/components/transaction-action/transaction-action.component.js b/ui/app/components/transaction-action/transaction-action.component.js index b608615d0..9f447fe5c 100644 --- a/ui/app/components/transaction-action/transaction-action.component.js +++ b/ui/app/components/transaction-action/transaction-action.component.js @@ -28,9 +28,9 @@ export default class TransactionAction extends PureComponent { getTransactionAction () { const { transactionAction } = this.state const { transaction, methodData } = this.props - const { data, isFetching } = methodData + const { data, done } = methodData - if (isFetching || transactionAction) { + if (!done || transactionAction) { return } @@ -40,12 +40,12 @@ export default class TransactionAction extends PureComponent { } render () { - const { className } = this.props + const { className, methodData: { isFetching } } = this.props const { transactionAction } = this.state return (
- { transactionAction || '--' } + { (!isFetching && transactionAction) || '--' }
) } diff --git a/ui/app/components/transaction-list-item/transaction-list-item.component.js b/ui/app/components/transaction-list-item/transaction-list-item.component.js index 6e1abd0e4..a47f29023 100644 --- a/ui/app/components/transaction-list-item/transaction-list-item.component.js +++ b/ui/app/components/transaction-list-item/transaction-list-item.component.js @@ -3,11 +3,9 @@ import PropTypes from 'prop-types' import Identicon from '../identicon' import TransactionStatus from '../transaction-status' import TransactionAction from '../transaction-action' -import { formatDate } from '../../util' import prefixForNetwork from '../../../lib/etherscan-prefix-for-network' import { CONFIRM_TRANSACTION_ROUTE } from '../../routes' import { UNAPPROVED_STATUS, TOKEN_METHOD_TRANSFER } from '../../constants/transactions' -import { hexToDecimal } from '../../helpers/conversions.util' export default class TransactionListItem extends PureComponent { static propTypes = { @@ -19,6 +17,7 @@ export default class TransactionListItem extends PureComponent { showRetry: PropTypes.bool, retryTransaction: PropTypes.func, setSelectedToken: PropTypes.func, + nonceAndDate: PropTypes.string, } handleClick = () => { @@ -63,14 +62,9 @@ export default class TransactionListItem extends PureComponent { fiatDisplayValue, methodData, showRetry, + nonceAndDate, } = this.props const { txParams = {} } = transaction - const nonce = hexToDecimal(txParams.nonce) - - const nonceAndDateText = nonce - ? `#${nonce} - ${formatDate(transaction.time)}` - : formatDate(transaction.time) - const fiatDisplayText = `-${fiatDisplayValue}` const ethDisplayText = ethTransactionAmount && `-${ethTransactionAmount} ETH` @@ -92,9 +86,9 @@ export default class TransactionListItem extends PureComponent { />
- { nonceAndDateText } + { nonceAndDate }
{ const { metamask } = state const { currentCurrency, conversionRate } = metamask - const { transaction: { txParams: { value, data } = {} } = {}, token } = ownProps + const { transaction: { txParams: { value, data, nonce } = {}, time } = {}, token } = ownProps let ethTransactionAmount, fiatDisplayValue @@ -22,13 +22,9 @@ const mapStateToProps = (state, ownProps) => { const tokenData = getTokenData(data) if (tokenData.params && tokenData.params.length === 2) { - const tokenDataName = tokenData.name || '' const tokenValue = tokenData.params[1].value - const tokenAmount = tokenDataName.toLowerCase() === TOKEN_METHOD_TRANSFER - ? calcTokenAmount(tokenValue, decimals) - : tokenValue - - fiatDisplayValue = `${tokenAmount} ${symbol}` + const tokenAmount = calcTokenAmount(tokenValue, decimals) + fiatDisplayValue = `${tokenAmount} ${symbol}` } } else { ethTransactionAmount = getEthFromWeiHex({ value, conversionRate }) @@ -39,9 +35,12 @@ const mapStateToProps = (state, ownProps) => { fiatDisplayValue = `${fiatFormattedAmount} ${currentCurrency.toUpperCase()}` } + const nonceAndDate = nonce ? `#${hexToDecimal(nonce)} - ${formatDate(time)}` : formatDate(time) + return { ethTransactionAmount, fiatDisplayValue, + nonceAndDate, } } diff --git a/ui/app/constants/transactions.js b/ui/app/constants/transactions.js index 1dc8944d3..da1d2e590 100644 --- a/ui/app/constants/transactions.js +++ b/ui/app/constants/transactions.js @@ -17,5 +17,6 @@ export const APPROVE_ACTION_KEY = 'approve' export const SEND_TOKEN_ACTION_KEY = 'outgoing' export const TRANSFER_FROM_ACTION_KEY = 'transferFrom' export const SIGNATURE_REQUEST_KEY = 'signatureRequest' +export const UNKNOWN_FUNCTION_KEY = 'unknownFunction' export const TRANSACTION_TYPE_SHAPESHIFT = 'shapeshift' diff --git a/ui/app/helpers/transactions.util.js b/ui/app/helpers/transactions.util.js index 8ded31bca..e890a0852 100644 --- a/ui/app/helpers/transactions.util.js +++ b/ui/app/helpers/transactions.util.js @@ -14,6 +14,7 @@ import { SEND_TOKEN_ACTION_KEY, TRANSFER_FROM_ACTION_KEY, SIGNATURE_REQUEST_KEY, + UNKNOWN_FUNCTION_KEY, } from '../constants/transactions' abiDecoder.addABI(abi) @@ -56,6 +57,10 @@ export function getTransactionActionKey (transaction, methodData) { const { name } = methodData const methodName = name && name.toLowerCase() + if (!methodName) { + return UNKNOWN_FUNCTION_KEY + } + switch (methodName) { case TOKEN_METHOD_TRANSFER: return SEND_TOKEN_ACTION_KEY diff --git a/ui/app/higher-order-components/with-method-data/with-method-data.component.js b/ui/app/higher-order-components/with-method-data/with-method-data.component.js index c05d33c20..fed7d9865 100644 --- a/ui/app/higher-order-components/with-method-data/with-method-data.component.js +++ b/ui/app/higher-order-components/with-method-data/with-method-data.component.js @@ -13,10 +13,8 @@ export default function withMethodData (WrappedComponent) { } state = { - methodData: { - data: {}, - }, - isFetching: false, + methodData: {}, + done: false, error: null, } @@ -29,24 +27,24 @@ export default function withMethodData (WrappedComponent) { const { txParams: { data = '' } = {} } = transaction if (data) { - this.setState({ isFetching: true }) - try { const methodData = await getMethodData(data) - this.setState({ methodData, isFetching: false }) + this.setState({ methodData, done: true }) } catch (error) { - this.setState({ isFetching: false, error }) + this.setState({ done: true, error }) } + } else { + this.setState({ done: true }) } } render () { - const { methodData, isFetching, error } = this.state + const { methodData, done, error } = this.state return ( ) }