Fix e2e tests

feature/default_network_editable
Alexander Tseung 6 years ago
parent 9adf0c4b60
commit 5dcd8ceb7b
  1. 136
      test/e2e/beta/metamask-beta-ui.spec.js
  2. 8
      ui/app/components/transaction-action/transaction-action.component.js
  3. 14
      ui/app/components/transaction-list-item/transaction-list-item.component.js
  4. 15
      ui/app/components/transaction-list-item/transaction-list-item.container.js
  5. 1
      ui/app/constants/transactions.js
  6. 5
      ui/app/helpers/transactions.util.js
  7. 18
      ui/app/higher-order-components/with-method-data/with-method-data.component.js

@ -225,19 +225,9 @@ describe('MetaMask', function () {
await delay(regularDelayMs) await delay(regularDelayMs)
} }
await clickWordAndWait(words[0]) for (let i = 0; i < 12; i++) {
await clickWordAndWait(words[1]) await clickWordAndWait(words[i])
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])
} catch (e) { } catch (e) {
if (count > 2) { if (count > 2) {
throw e throw e
@ -484,7 +474,7 @@ describe('MetaMask', function () {
await driver.switchTo().window(extension) await driver.switchTo().window(extension)
await delay(regularDelayMs) 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 txListItem.click()
await delay(regularDelayMs) await delay(regularDelayMs)
}) })
@ -508,13 +498,15 @@ describe('MetaMask', function () {
it('confirms a deploy contract transaction', async () => { it('confirms a deploy contract transaction', async () => {
const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`)) const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`))
await confirmButton.click() await confirmButton.click()
await delay(regularDelayMs) await delay(largeDelayMs)
const txStatuses = await findElements(driver, By.css('.tx-list-status')) driver.wait(async () => {
await driver.wait(until.elementTextMatches(txStatuses[0], /Confirmed/)) 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')) const txAction = await findElements(driver, By.css('.transaction-list-item__action'))
assert.equal(await txAccounts[0].getText(), 'Contract Deployment') await driver.wait(until.elementTextMatches(txAction[0], /Contract\sDeployment/), 10000)
await delay(regularDelayMs) await delay(regularDelayMs)
}) })
@ -535,9 +527,9 @@ describe('MetaMask', function () {
await driver.switchTo().window(extension) await driver.switchTo().window(extension)
await delay(largeDelayMs) await delay(largeDelayMs)
await findElements(driver, By.css('.tx-list-pending-item-container')) await findElements(driver, By.css('.transaction-list-item'))
const [txListValue] = await findElements(driver, By.css('.tx-list-value')) const [txListValue] = await findElements(driver, By.css('.transaction-list-item__amount--secondary'))
await driver.wait(until.elementTextMatches(txListValue, /4\sETH/), 10000) await driver.wait(until.elementTextMatches(txListValue, /-4\sETH/), 10000)
await txListValue.click() await txListValue.click()
await delay(regularDelayMs) await delay(regularDelayMs)
@ -565,15 +557,20 @@ describe('MetaMask', function () {
await confirmButton.click() await confirmButton.click()
await delay(regularDelayMs) await delay(regularDelayMs)
const txStatuses = await findElements(driver, By.css('.tx-list-status')) // const txStatuses = await findElements(driver, By.css('.transaction-list-item__status'))
await driver.wait(until.elementTextMatches(txStatuses[0], /Confirmed/)) // 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')) const txValues = await findElement(driver, By.css('.transaction-list-item__amount--secondary'))
await driver.wait(until.elementTextMatches(txValues, /4\sETH/), 10000) await driver.wait(until.elementTextMatches(txValues, /-4\sETH/), 10000)
const txAccounts = await findElements(driver, By.css('.tx-list-account')) // const txAccounts = await findElements(driver, By.css('.tx-list-account'))
const firstTxAddress = await txAccounts[0].getText() // const firstTxAddress = await txAccounts[0].getText()
assert(firstTxAddress.match(/^0x\w{8}\.{3}\w{4}$/)) // assert(firstTxAddress.match(/^0x\w{8}\.{3}\w{4}$/))
}) })
it('calls and confirms a contract method where ETH is received', async () => { it('calls and confirms a contract method where ETH is received', async () => {
@ -595,18 +592,23 @@ describe('MetaMask', function () {
await confirmButton.click() await confirmButton.click()
await delay(regularDelayMs) await delay(regularDelayMs)
const txStatuses = await findElements(driver, By.css('.tx-list-status')) // const txStatuses = await findElements(driver, By.css('.tx-list-status'))
await driver.wait(until.elementTextMatches(txStatuses[0], /Confirmed/)) // 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')) const txValues = await findElement(driver, By.css('.transaction-list-item__amount--secondary'))
await driver.wait(until.elementTextMatches(txValues, /0\sETH/), 10000) await driver.wait(until.elementTextMatches(txValues, /-0\sETH/), 10000)
await closeAllWindowHandlesExcept(driver, [extension, dapp]) await closeAllWindowHandlesExcept(driver, [extension, dapp])
await driver.switchTo().window(extension) await driver.switchTo().window(extension)
}) })
it('renders the correct ETH balance', async () => { 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) await delay(regularDelayMs)
if (process.env.SELENIUM_BROWSER !== 'firefox') { if (process.env.SELENIUM_BROWSER !== 'firefox') {
await driver.wait(until.elementTextMatches(balance, /^92.*ETH.*$/), 10000) await driver.wait(until.elementTextMatches(balance, /^92.*ETH.*$/), 10000)
@ -651,12 +653,11 @@ describe('MetaMask', function () {
await closeAllWindowHandlesExcept(driver, [extension, dapp]) await closeAllWindowHandlesExcept(driver, [extension, dapp])
await delay(regularDelayMs) await delay(regularDelayMs)
await driver.switchTo().window(extension) await driver.switchTo().window(extension)
await delay(regularDelayMs) await delay(largeDelayMs)
}) })
it('clicks on the Add Token button', async () => { 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 addToken.click()
await delay(regularDelayMs) await delay(regularDelayMs)
}) })
@ -680,7 +681,7 @@ describe('MetaMask', function () {
}) })
it('renders the balance for the new token', async () => { 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*$/)) await driver.wait(until.elementTextMatches(balance, /^100\s*TST\s*$/))
const tokenAmount = await balance.getText() const tokenAmount = await balance.getText()
assert.ok(/^100\s*TST\s*$/.test(tokenAmount)) 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) 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) const tx = await driver.wait(until.elementTextMatches(txStatuses[0], /Outgoing|Failed/), 10000)
assert.equal(await tx.getText(), 'Outgoing') assert.equal(await tx.getText(), 'Outgoing')
}) })
@ -786,9 +791,9 @@ describe('MetaMask', function () {
await driver.switchTo().window(extension) await driver.switchTo().window(extension)
await delay(largeDelayMs) await delay(largeDelayMs)
await findElements(driver, By.css('.tx-list-pending-item-container')) await findElements(driver, By.css('.transaction-list__pending-transactions'))
const [txListValue] = await findElements(driver, By.css('.tx-list-value')) const [txListValue] = await findElements(driver, By.css('.transaction-list-item__amount--primary'))
await driver.wait(until.elementTextMatches(txListValue, /7\sTST/), 10000) await driver.wait(until.elementTextMatches(txListValue, /-7\sTST/), 10000)
await txListValue.click() await txListValue.click()
await delay(regularDelayMs) await delay(regularDelayMs)
@ -835,25 +840,30 @@ describe('MetaMask', function () {
}) })
it('finds the transaction in the transactions list', async function () { it('finds the transaction in the transactions list', async function () {
const transactions = await findElements(driver, By.css('.tx-list-item')) driver.wait(async () => {
assert.equal(transactions.length, 2) 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')) const txValues = await findElements(driver, By.css('.transaction-list-item__amount--primary'))
await driver.wait(until.elementTextMatches(txValues[0], /7\sTST/)) await driver.wait(until.elementTextMatches(txValues[0], /-7\sTST/))
const txStatuses = await findElements(driver, By.css('.tx-list-status')) const txStatuses = await findElements(driver, By.css('.transaction-list-item__action'))
await driver.wait(until.elementTextMatches(txStatuses[0], /Confirmed/)) await driver.wait(until.elementTextMatches(txStatuses[0], /Outgoing/))
const walletBalance = await findElement(driver, By.css('.wallet-balance')) const walletBalance = await findElement(driver, By.css('.wallet-balance'))
await walletBalance.click() await walletBalance.click()
const tokenListItems = await findElements(driver, By.css('.token-list-item')) const tokenListItems = await findElements(driver, By.css('.token-list-item'))
await tokenListItems[0].click() await tokenListItems[0].click()
await delay(regularDelayMs)
// test cancelled on firefox until https://github.com/mozilla/geckodriver/issues/906 is resolved, // 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 // or possibly until we use latest version of firefox in the tests
if (process.env.SELENIUM_BROWSER !== 'firefox') { if (process.env.SELENIUM_BROWSER !== 'firefox') {
const tokenBalanceAmount = await findElement(driver, By.css('.token-balance__amount')) const tokenBalanceAmount = await findElement(driver, By.css('.token-view-balance__token-balance'))
assert.equal(await tokenBalanceAmount.getText(), '43') assert.equal(await tokenBalanceAmount.getText(), '43 TST')
} }
}) })
}) })
@ -877,9 +887,14 @@ describe('MetaMask', function () {
await driver.switchTo().window(extension) await driver.switchTo().window(extension)
await delay(regularDelayMs) await delay(regularDelayMs)
const [txListItem] = await findElements(driver, By.css('.tx-list-item')) driver.wait(async () => {
const [txListValue] = await findElements(driver, By.css('.tx-list-value')) const pendingTxes = await findElements(driver, By.css('.transaction-list__pending-transactions .transaction-list-item'))
await driver.wait(until.elementTextMatches(txListValue, /0\sETH/)) 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 txListItem.click()
await delay(regularDelayMs) await delay(regularDelayMs)
}) })
@ -950,10 +965,15 @@ describe('MetaMask', function () {
}) })
it('finds the transaction in the transactions list', async function () { it('finds the transaction in the transactions list', async function () {
const txValues = await findElements(driver, By.css('.tx-list-value')) driver.wait(async () => {
await driver.wait(until.elementTextMatches(txValues[0], /0\sETH/)) const confirmedTxes = await findElements(driver, By.css('.transaction-list__completed-transactions .transaction-list-item'))
const txStatuses = await findElements(driver, By.css('.tx-list-status')) return confirmedTxes.length === 3
await driver.wait(until.elementTextMatches(txStatuses[0], /Confirmed/)) }, 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 () => { 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 driver.wait(until.elementTextMatches(balance, /0\sBAT/))
await delay(regularDelayMs) await delay(regularDelayMs)
}) })

@ -28,9 +28,9 @@ export default class TransactionAction extends PureComponent {
getTransactionAction () { getTransactionAction () {
const { transactionAction } = this.state const { transactionAction } = this.state
const { transaction, methodData } = this.props const { transaction, methodData } = this.props
const { data, isFetching } = methodData const { data, done } = methodData
if (isFetching || transactionAction) { if (!done || transactionAction) {
return return
} }
@ -40,12 +40,12 @@ export default class TransactionAction extends PureComponent {
} }
render () { render () {
const { className } = this.props const { className, methodData: { isFetching } } = this.props
const { transactionAction } = this.state const { transactionAction } = this.state
return ( return (
<div className={className}> <div className={className}>
{ transactionAction || '--' } { (!isFetching && transactionAction) || '--' }
</div> </div>
) )
} }

@ -3,11 +3,9 @@ import PropTypes from 'prop-types'
import Identicon from '../identicon' import Identicon from '../identicon'
import TransactionStatus from '../transaction-status' import TransactionStatus from '../transaction-status'
import TransactionAction from '../transaction-action' import TransactionAction from '../transaction-action'
import { formatDate } from '../../util'
import prefixForNetwork from '../../../lib/etherscan-prefix-for-network' import prefixForNetwork from '../../../lib/etherscan-prefix-for-network'
import { CONFIRM_TRANSACTION_ROUTE } from '../../routes' import { CONFIRM_TRANSACTION_ROUTE } from '../../routes'
import { UNAPPROVED_STATUS, TOKEN_METHOD_TRANSFER } from '../../constants/transactions' import { UNAPPROVED_STATUS, TOKEN_METHOD_TRANSFER } from '../../constants/transactions'
import { hexToDecimal } from '../../helpers/conversions.util'
export default class TransactionListItem extends PureComponent { export default class TransactionListItem extends PureComponent {
static propTypes = { static propTypes = {
@ -19,6 +17,7 @@ export default class TransactionListItem extends PureComponent {
showRetry: PropTypes.bool, showRetry: PropTypes.bool,
retryTransaction: PropTypes.func, retryTransaction: PropTypes.func,
setSelectedToken: PropTypes.func, setSelectedToken: PropTypes.func,
nonceAndDate: PropTypes.string,
} }
handleClick = () => { handleClick = () => {
@ -63,14 +62,9 @@ export default class TransactionListItem extends PureComponent {
fiatDisplayValue, fiatDisplayValue,
methodData, methodData,
showRetry, showRetry,
nonceAndDate,
} = this.props } = this.props
const { txParams = {} } = transaction const { txParams = {} } = transaction
const nonce = hexToDecimal(txParams.nonce)
const nonceAndDateText = nonce
? `#${nonce} - ${formatDate(transaction.time)}`
: formatDate(transaction.time)
const fiatDisplayText = `-${fiatDisplayValue}` const fiatDisplayText = `-${fiatDisplayValue}`
const ethDisplayText = ethTransactionAmount && `-${ethTransactionAmount} ETH` const ethDisplayText = ethTransactionAmount && `-${ethTransactionAmount} ETH`
@ -92,9 +86,9 @@ export default class TransactionListItem extends PureComponent {
/> />
<div <div
className="transaction-list-item__nonce" className="transaction-list-item__nonce"
title={nonceAndDateText} title={nonceAndDate}
> >
{ nonceAndDateText } { nonceAndDate }
</div> </div>
<TransactionStatus <TransactionStatus
className="transaction-list-item__status" className="transaction-list-item__status"

@ -4,16 +4,16 @@ import { compose } from 'recompose'
import withMethodData from '../../higher-order-components/with-method-data' import withMethodData from '../../higher-order-components/with-method-data'
import TransactionListItem from './transaction-list-item.component' import TransactionListItem from './transaction-list-item.component'
import { setSelectedToken, retryTransaction } from '../../actions' import { setSelectedToken, retryTransaction } from '../../actions'
import { getEthFromWeiHex, getValueFromWeiHex } from '../../helpers/conversions.util' import { getEthFromWeiHex, getValueFromWeiHex, hexToDecimal } from '../../helpers/conversions.util'
import { getTokenData } from '../../helpers/transactions.util' import { getTokenData } from '../../helpers/transactions.util'
import { formatCurrency } from '../../helpers/confirm-transaction/util' import { formatCurrency } from '../../helpers/confirm-transaction/util'
import { calcTokenAmount } from '../../token-util' import { calcTokenAmount } from '../../token-util'
import { TOKEN_METHOD_TRANSFER } from '../../constants/transactions' import { formatDate } from '../../util'
const mapStateToProps = (state, ownProps) => { const mapStateToProps = (state, ownProps) => {
const { metamask } = state const { metamask } = state
const { currentCurrency, conversionRate } = metamask const { currentCurrency, conversionRate } = metamask
const { transaction: { txParams: { value, data } = {} } = {}, token } = ownProps const { transaction: { txParams: { value, data, nonce } = {}, time } = {}, token } = ownProps
let ethTransactionAmount, fiatDisplayValue let ethTransactionAmount, fiatDisplayValue
@ -22,12 +22,8 @@ const mapStateToProps = (state, ownProps) => {
const tokenData = getTokenData(data) const tokenData = getTokenData(data)
if (tokenData.params && tokenData.params.length === 2) { if (tokenData.params && tokenData.params.length === 2) {
const tokenDataName = tokenData.name || ''
const tokenValue = tokenData.params[1].value const tokenValue = tokenData.params[1].value
const tokenAmount = tokenDataName.toLowerCase() === TOKEN_METHOD_TRANSFER const tokenAmount = calcTokenAmount(tokenValue, decimals)
? calcTokenAmount(tokenValue, decimals)
: tokenValue
fiatDisplayValue = `${tokenAmount} ${symbol}` fiatDisplayValue = `${tokenAmount} ${symbol}`
} }
} else { } else {
@ -39,9 +35,12 @@ const mapStateToProps = (state, ownProps) => {
fiatDisplayValue = `${fiatFormattedAmount} ${currentCurrency.toUpperCase()}` fiatDisplayValue = `${fiatFormattedAmount} ${currentCurrency.toUpperCase()}`
} }
const nonceAndDate = nonce ? `#${hexToDecimal(nonce)} - ${formatDate(time)}` : formatDate(time)
return { return {
ethTransactionAmount, ethTransactionAmount,
fiatDisplayValue, fiatDisplayValue,
nonceAndDate,
} }
} }

@ -17,5 +17,6 @@ export const APPROVE_ACTION_KEY = 'approve'
export const SEND_TOKEN_ACTION_KEY = 'outgoing' export const SEND_TOKEN_ACTION_KEY = 'outgoing'
export const TRANSFER_FROM_ACTION_KEY = 'transferFrom' export const TRANSFER_FROM_ACTION_KEY = 'transferFrom'
export const SIGNATURE_REQUEST_KEY = 'signatureRequest' export const SIGNATURE_REQUEST_KEY = 'signatureRequest'
export const UNKNOWN_FUNCTION_KEY = 'unknownFunction'
export const TRANSACTION_TYPE_SHAPESHIFT = 'shapeshift' export const TRANSACTION_TYPE_SHAPESHIFT = 'shapeshift'

@ -14,6 +14,7 @@ import {
SEND_TOKEN_ACTION_KEY, SEND_TOKEN_ACTION_KEY,
TRANSFER_FROM_ACTION_KEY, TRANSFER_FROM_ACTION_KEY,
SIGNATURE_REQUEST_KEY, SIGNATURE_REQUEST_KEY,
UNKNOWN_FUNCTION_KEY,
} from '../constants/transactions' } from '../constants/transactions'
abiDecoder.addABI(abi) abiDecoder.addABI(abi)
@ -56,6 +57,10 @@ export function getTransactionActionKey (transaction, methodData) {
const { name } = methodData const { name } = methodData
const methodName = name && name.toLowerCase() const methodName = name && name.toLowerCase()
if (!methodName) {
return UNKNOWN_FUNCTION_KEY
}
switch (methodName) { switch (methodName) {
case TOKEN_METHOD_TRANSFER: case TOKEN_METHOD_TRANSFER:
return SEND_TOKEN_ACTION_KEY return SEND_TOKEN_ACTION_KEY

@ -13,10 +13,8 @@ export default function withMethodData (WrappedComponent) {
} }
state = { state = {
methodData: { methodData: {},
data: {}, done: false,
},
isFetching: false,
error: null, error: null,
} }
@ -29,24 +27,24 @@ export default function withMethodData (WrappedComponent) {
const { txParams: { data = '' } = {} } = transaction const { txParams: { data = '' } = {} } = transaction
if (data) { if (data) {
this.setState({ isFetching: true })
try { try {
const methodData = await getMethodData(data) const methodData = await getMethodData(data)
this.setState({ methodData, isFetching: false }) this.setState({ methodData, done: true })
} catch (error) { } catch (error) {
this.setState({ isFetching: false, error }) this.setState({ done: true, error })
} }
} else {
this.setState({ done: true })
} }
} }
render () { render () {
const { methodData, isFetching, error } = this.state const { methodData, done, error } = this.state
return ( return (
<WrappedComponent <WrappedComponent
{ ...this.props } { ...this.props }
methodData={{ data: methodData, isFetching, error }} methodData={{ data: methodData, done, error }}
/> />
) )
} }

Loading…
Cancel
Save