aboutsummaryrefslogblamecommitdiffstats
path: root/ui/app/ducks/tests/confirm-transaction.duck.test.js
blob: 1bab0add05c6d476242dba613d1b3672ff34c86a (plain) (tree)
1
2
3
4


                                                 
                         


















                                                                                    

                         













                                                                                            


                                                                                        


























                                                                                          

                               













































































































































































































                                                                                                       
                                                                                       

                                              

                                         


                                          
                                



         
                                                                                          
                       

                                              

           

                                          



         











                                                                                         




































































































































































                                                                       
                                                                     
                              
                               


                       
                                      



                      
                                                                      
                              
                             


                       
                                       
















                                                                     











                                                                                              









                                                                                         
                              










































































                                                                                                
                              




















































































                                                                                                
 





                                                                                                    
import assert from 'assert'
import configureMockStore from 'redux-mock-store'
import thunk from 'redux-thunk'
import sinon from 'sinon'

import ConfirmTransactionReducer, * as actions from '../confirm-transaction.duck.js'

const initialState = {
  txData: {},
  tokenData: {},
  methodData: {},
  tokenProps: {
    tokenDecimals: '',
    tokenSymbol: '',
  },
  fiatTransactionAmount: '',
  fiatTransactionFee: '',
  fiatTransactionTotal: '',
  ethTransactionAmount: '',
  ethTransactionFee: '',
  ethTransactionTotal: '',
  hexGasTotal: '',
  nonce: '',
  toSmartContract: false,
  fetchingData: false,
}

const UPDATE_TX_DATA = 'metamask/confirm-transaction/UPDATE_TX_DATA'
const CLEAR_TX_DATA = 'metamask/confirm-transaction/CLEAR_TX_DATA'
const UPDATE_TOKEN_DATA = 'metamask/confirm-transaction/UPDATE_TOKEN_DATA'
const CLEAR_TOKEN_DATA = 'metamask/confirm-transaction/CLEAR_TOKEN_DATA'
const UPDATE_METHOD_DATA = 'metamask/confirm-transaction/UPDATE_METHOD_DATA'
const CLEAR_METHOD_DATA = 'metamask/confirm-transaction/CLEAR_METHOD_DATA'
const UPDATE_TRANSACTION_AMOUNTS = 'metamask/confirm-transaction/UPDATE_TRANSACTION_AMOUNTS'
const UPDATE_TRANSACTION_FEES = 'metamask/confirm-transaction/UPDATE_TRANSACTION_FEES'
const UPDATE_TRANSACTION_TOTALS = 'metamask/confirm-transaction/UPDATE_TRANSACTION_TOTALS'
const UPDATE_HEX_GAS_TOTAL = 'metamask/confirm-transaction/UPDATE_HEX_GAS_TOTAL'
const UPDATE_TOKEN_PROPS = 'metamask/confirm-transaction/UPDATE_TOKEN_PROPS'
const UPDATE_NONCE = 'metamask/confirm-transaction/UPDATE_NONCE'
const UPDATE_TO_SMART_CONTRACT = 'metamask/confirm-transaction/UPDATE_TO_SMART_CONTRACT'
const FETCH_DATA_START = 'metamask/confirm-transaction/FETCH_DATA_START'
const FETCH_DATA_END = 'metamask/confirm-transaction/FETCH_DATA_END'
const CLEAR_CONFIRM_TRANSACTION = 'metamask/confirm-transaction/CLEAR_CONFIRM_TRANSACTION'

describe('Confirm Transaction Duck', () => {
  describe('State changes', () => {
    const mockState = {
      confirmTransaction: {
        txData: {
          id: 1,
        },
        tokenData: {
          name: 'abcToken',
        },
        methodData: {
          name: 'approve',
        },
        tokenProps: {
          tokenDecimals: '3',
          tokenSymbol: 'ABC',
        },
        fiatTransactionAmount: '469.26',
        fiatTransactionFee: '0.01',
        fiatTransactionTotal: '1.000021',
        ethTransactionAmount: '1',
        ethTransactionFee: '0.000021',
        ethTransactionTotal: '469.27',
        hexGasTotal: '0x1319718a5000',
        nonce: '0x0',
        toSmartContract: false,
        fetchingData: false,
      },
    }

    it('should initialize state', () => {
      assert.deepEqual(
        ConfirmTransactionReducer({}),
        initialState
      )
    })

    it('should return state unchanged if it does not match a dispatched actions type', () => {
      assert.deepEqual(
        ConfirmTransactionReducer(mockState, {
          type: 'someOtherAction',
          value: 'someValue',
        }),
        { ...mockState.confirmTransaction },
      )
    })

    it('should set txData when receiving a UPDATE_TX_DATA action', () => {
      assert.deepEqual(
        ConfirmTransactionReducer(mockState, {
          type: UPDATE_TX_DATA,
          payload: {
            id: 2,
          },
        }),
        {
          ...mockState.confirmTransaction,
          txData: {
            ...mockState.confirmTransaction.txData,
            id: 2,
          },
        }
      )
    })

    it('should clear txData when receiving a CLEAR_TX_DATA action', () => {
      assert.deepEqual(
        ConfirmTransactionReducer(mockState, {
          type: CLEAR_TX_DATA,
        }),
        {
          ...mockState.confirmTransaction,
          txData: {},
        }
      )
    })

    it('should set tokenData when receiving a UPDATE_TOKEN_DATA action', () => {
      assert.deepEqual(
        ConfirmTransactionReducer(mockState, {
          type: UPDATE_TOKEN_DATA,
          payload: {
            name: 'defToken',
          },
        }),
        {
          ...mockState.confirmTransaction,
          tokenData: {
            ...mockState.confirmTransaction.tokenData,
            name: 'defToken',
          },
        }
      )
    })

    it('should clear tokenData when receiving a CLEAR_TOKEN_DATA action', () => {
      assert.deepEqual(
        ConfirmTransactionReducer(mockState, {
          type: CLEAR_TOKEN_DATA,
        }),
        {
          ...mockState.confirmTransaction,
          tokenData: {},
        }
      )
    })

    it('should set methodData when receiving a UPDATE_METHOD_DATA action', () => {
      assert.deepEqual(
        ConfirmTransactionReducer(mockState, {
          type: UPDATE_METHOD_DATA,
          payload: {
            name: 'transferFrom',
          },
        }),
        {
          ...mockState.confirmTransaction,
          methodData: {
            ...mockState.confirmTransaction.methodData,
            name: 'transferFrom',
          },
        }
      )
    })

    it('should clear methodData when receiving a CLEAR_METHOD_DATA action', () => {
      assert.deepEqual(
        ConfirmTransactionReducer(mockState, {
          type: CLEAR_METHOD_DATA,
        }),
        {
          ...mockState.confirmTransaction,
          methodData: {},
        }
      )
    })

    it('should update transaction amounts when receiving an UPDATE_TRANSACTION_AMOUNTS action', () => {
      assert.deepEqual(
        ConfirmTransactionReducer(mockState, {
          type: UPDATE_TRANSACTION_AMOUNTS,
          payload: {
            fiatTransactionAmount: '123.45',
            ethTransactionAmount: '.5',
          },
        }),
        {
          ...mockState.confirmTransaction,
          fiatTransactionAmount: '123.45',
          ethTransactionAmount: '.5',
        }
      )
    })

    it('should update transaction fees when receiving an UPDATE_TRANSACTION_FEES action', () => {
      assert.deepEqual(
        ConfirmTransactionReducer(mockState, {
          type: UPDATE_TRANSACTION_FEES,
          payload: {
            fiatTransactionFee: '123.45',
            ethTransactionFee: '.5',
          },
        }),
        {
          ...mockState.confirmTransaction,
          fiatTransactionFee: '123.45',
          ethTransactionFee: '.5',
        }
      )
    })

    it('should update transaction totals when receiving an UPDATE_TRANSACTION_TOTALS action', () => {
      assert.deepEqual(
        ConfirmTransactionReducer(mockState, {
          type: UPDATE_TRANSACTION_TOTALS,
          payload: {
            fiatTransactionTotal: '123.45',
            ethTransactionTotal: '.5',
          },
        }),
        {
          ...mockState.confirmTransaction,
          fiatTransactionTotal: '123.45',
          ethTransactionTotal: '.5',
        }
      )
    })

    it('should update hexGasTotal when receiving an UPDATE_HEX_GAS_TOTAL action', () => {
      assert.deepEqual(
        ConfirmTransactionReducer(mockState, {
          type: UPDATE_HEX_GAS_TOTAL,
          payload: '0x0',
        }),
        {
          ...mockState.confirmTransaction,
          hexGasTotal: '0x0',
        }
      )
    })

    it('should update tokenProps when receiving an UPDATE_TOKEN_PROPS action', () => {
      assert.deepEqual(
        ConfirmTransactionReducer(mockState, {
          type: UPDATE_TOKEN_PROPS,
          payload: {
            tokenSymbol: 'DEF',
            tokenDecimals: '1',
          },
        }),
        {
          ...mockState.confirmTransaction,
          tokenProps: {
            tokenSymbol: 'DEF',
            tokenDecimals: '1',
          },
        }
      )
    })

    it('should update nonce when receiving an UPDATE_NONCE action', () => {
      assert.deepEqual(
        ConfirmTransactionReducer(mockState, {
          type: UPDATE_NONCE,
          payload: '0x1',
        }),
        {
          ...mockState.confirmTransaction,
          nonce: '0x1',
        }
      )
    })

    it('should update nonce when receiving an UPDATE_TO_SMART_CONTRACT action', () => {
      assert.deepEqual(
        ConfirmTransactionReducer(mockState, {
          type: UPDATE_TO_SMART_CONTRACT,
          payload: true,
        }),
        {
          ...mockState.confirmTransaction,
          toSmartContract: true,
        }
      )
    })

    it('should set fetchingData to true when receiving a FETCH_DATA_START action', () => {
      assert.deepEqual(
        ConfirmTransactionReducer(mockState, {
          type: FETCH_DATA_START,
        }),
        {
          ...mockState.confirmTransaction,
          fetchingData: true,
        }
      )
    })

    it('should set fetchingData to false when receiving a FETCH_DATA_END action', () => {
      assert.deepEqual(
        ConfirmTransactionReducer({ confirmTransaction: { fetchingData: true } }, {
          type: FETCH_DATA_END,
        }),
        {
          fetchingData: false,
        }
      )
    })

    it('should clear confirmTransaction when receiving a FETCH_DATA_END action', () => {
      assert.deepEqual(
        ConfirmTransactionReducer(mockState, {
          type: CLEAR_CONFIRM_TRANSACTION,
        }),
        {
          ...initialState,
        }
      )
    })
  })

  describe('Single actions', () => {
    it('should create an action to update txData', () => {
      const txData = { test: 123 }
      const expectedAction = {
        type: UPDATE_TX_DATA,
        payload: txData,
      }

      assert.deepEqual(
        actions.updateTxData(txData),
        expectedAction
      )
    })

    it('should create an action to clear txData', () => {
      const expectedAction = {
        type: CLEAR_TX_DATA,
      }

      assert.deepEqual(
        actions.clearTxData(),
        expectedAction
      )
    })

    it('should create an action to update tokenData', () => {
      const tokenData = { test: 123 }
      const expectedAction = {
        type: UPDATE_TOKEN_DATA,
        payload: tokenData,
      }

      assert.deepEqual(
        actions.updateTokenData(tokenData),
        expectedAction
      )
    })

    it('should create an action to clear tokenData', () => {
      const expectedAction = {
        type: CLEAR_TOKEN_DATA,
      }

      assert.deepEqual(
        actions.clearTokenData(),
        expectedAction
      )
    })

    it('should create an action to update methodData', () => {
      const methodData = { test: 123 }
      const expectedAction = {
        type: UPDATE_METHOD_DATA,
        payload: methodData,
      }

      assert.deepEqual(
        actions.updateMethodData(methodData),
        expectedAction
      )
    })

    it('should create an action to clear methodData', () => {
      const expectedAction = {
        type: CLEAR_METHOD_DATA,
      }

      assert.deepEqual(
        actions.clearMethodData(),
        expectedAction
      )
    })

    it('should create an action to update transaction amounts', () => {
      const transactionAmounts = { test: 123 }
      const expectedAction = {
        type: UPDATE_TRANSACTION_AMOUNTS,
        payload: transactionAmounts,
      }

      assert.deepEqual(
        actions.updateTransactionAmounts(transactionAmounts),
        expectedAction
      )
    })

    it('should create an action to update transaction fees', () => {
      const transactionFees = { test: 123 }
      const expectedAction = {
        type: UPDATE_TRANSACTION_FEES,
        payload: transactionFees,
      }

      assert.deepEqual(
        actions.updateTransactionFees(transactionFees),
        expectedAction
      )
    })

    it('should create an action to update transaction totals', () => {
      const transactionTotals = { test: 123 }
      const expectedAction = {
        type: UPDATE_TRANSACTION_TOTALS,
        payload: transactionTotals,
      }

      assert.deepEqual(
        actions.updateTransactionTotals(transactionTotals),
        expectedAction
      )
    })

    it('should create an action to update hexGasTotal', () => {
      const hexGasTotal = '0x0'
      const expectedAction = {
        type: UPDATE_HEX_GAS_TOTAL,
        payload: hexGasTotal,
      }

      assert.deepEqual(
        actions.updateHexGasTotal(hexGasTotal),
        expectedAction
      )
    })

    it('should create an action to update tokenProps', () => {
      const tokenProps = {
        tokenDecimals: '1',
        tokenSymbol: 'abc',
      }
      const expectedAction = {
        type: UPDATE_TOKEN_PROPS,
        payload: tokenProps,
      }

      assert.deepEqual(
        actions.updateTokenProps(tokenProps),
        expectedAction
      )
    })

    it('should create an action to update nonce', () => {
      const nonce = '0x1'
      const expectedAction = {
        type: UPDATE_NONCE,
        payload: nonce,
      }

      assert.deepEqual(
        actions.updateNonce(nonce),
        expectedAction
      )
    })

    it('should create an action to set fetchingData to true', () => {
      const expectedAction = {
        type: FETCH_DATA_START,
      }

      assert.deepEqual(
        actions.setFetchingData(true),
        expectedAction
      )
    })

    it('should create an action to set fetchingData to false', () => {
      const expectedAction = {
        type: FETCH_DATA_END,
      }

      assert.deepEqual(
        actions.setFetchingData(false),
        expectedAction
      )
    })

    it('should create an action to clear confirmTransaction', () => {
      const expectedAction = {
        type: CLEAR_CONFIRM_TRANSACTION,
      }

      assert.deepEqual(
        actions.clearConfirmTransaction(),
        expectedAction
      )
    })
  })

  describe('Thunk actions', done => {
    beforeEach(() => {
      global.eth = {
        getCode: sinon.stub().callsFake(
          address => Promise.resolve(address && address.match(/isContract/) ? 'not-0x' : '0x')
        ),
      }
    })

    afterEach(() => {
      global.eth.getCode.resetHistory()
    })

    it('updates txData and gas on an existing transaction in confirmTransaction', () => {
      const mockState = {
        metamask: {
          conversionRate: 468.58,
          currentCurrency: 'usd',
        },
        confirmTransaction: {
          ethTransactionAmount: '1',
          ethTransactionFee: '0.000021',
          ethTransactionTotal: '1.000021',
          fetchingData: false,
          fiatTransactionAmount: '469.26',
          fiatTransactionFee: '0.01',
          fiatTransactionTotal: '469.27',
          hexGasTotal: '0x1319718a5000',
          methodData: {},
          nonce: '',
          tokenData: {},
          tokenProps: {
            tokenDecimals: '',
            tokenSymbol: '',
          },
          txData: {
            estimatedGas: '0x5208',
            gasLimitSpecified: false,
            gasPriceSpecified: false,
            history: [],
            id: 2603411941761054,
            loadingDefaults: false,
            metamaskNetworkId: '3',
            origin: 'faucet.metamask.io',
            simpleSend: true,
            status: 'unapproved',
            time: 1530838113716,
          },
        },
      }

      const middlewares = [thunk]
      const mockStore = configureMockStore(middlewares)
      const store = mockStore(mockState)
      const expectedActions = [
        'metamask/confirm-transaction/UPDATE_TX_DATA',
        'metamask/confirm-transaction/UPDATE_TRANSACTION_AMOUNTS',
        'metamask/confirm-transaction/UPDATE_HEX_GAS_TOTAL',
        'metamask/confirm-transaction/UPDATE_TRANSACTION_FEES',
        'metamask/confirm-transaction/UPDATE_TRANSACTION_TOTALS',
      ]

      store.dispatch(actions.updateGasAndCalculate({ gasLimit: '0x2', gasPrice: '0x25' }))

      const storeActions = store.getActions()
      assert.equal(storeActions.length, expectedActions.length)
      storeActions.forEach((action, index) => assert.equal(action.type, expectedActions[index]))
    })

    it('updates txData and updates gas values in confirmTransaction', () => {
      const txData = {
        estimatedGas: '0x5208',
        gasLimitSpecified: false,
        gasPriceSpecified: false,
        history: [],
        id: 2603411941761054,
        loadingDefaults: false,
        metamaskNetworkId: '3',
        origin: 'faucet.metamask.io',
        simpleSend: true,
        status: 'unapproved',
        time: 1530838113716,
        txParams: {
          from: '0xc5ae6383e126f901dcb06131d97a88745bfa88d6',
          gas: '0x33450',
          gasPrice: '0x2540be400',
          to: '0x81b7e08f65bdf5648606c89998a9cc8164397647',
          value: '0xde0b6b3a7640000',
        },
      }
      const mockState = {
        metamask: {
          conversionRate: 468.58,
          currentCurrency: 'usd',
        },
        confirmTransaction: {
          ethTransactionAmount: '1',
          ethTransactionFee: '0.000021',
          ethTransactionTotal: '1.000021',
          fetchingData: false,
          fiatTransactionAmount: '469.26',
          fiatTransactionFee: '0.01',
          fiatTransactionTotal: '469.27',
          hexGasTotal: '0x1319718a5000',
          methodData: {},
          nonce: '',
          tokenData: {},
          tokenProps: {
            tokenDecimals: '',
            tokenSymbol: '',
          },
          txData: {
            ...txData,
            txParams: {
              ...txData.txParams,
            },
          },
        },
      }

      const middlewares = [thunk]
      const mockStore = configureMockStore(middlewares)
      const store = mockStore(mockState)
      const expectedActions = [
        'metamask/confirm-transaction/UPDATE_TX_DATA',
        'metamask/confirm-transaction/UPDATE_TRANSACTION_AMOUNTS',
        'metamask/confirm-transaction/UPDATE_HEX_GAS_TOTAL',
        'metamask/confirm-transaction/UPDATE_TRANSACTION_FEES',
        'metamask/confirm-transaction/UPDATE_TRANSACTION_TOTALS',
      ]

      store.dispatch(actions.updateTxDataAndCalculate(txData))

      const storeActions = store.getActions()
      assert.equal(storeActions.length, expectedActions.length)
      storeActions.forEach((action, index) => assert.equal(action.type, expectedActions[index]))
    })

    it('updates confirmTransaction transaction', done => {
      const mockState = {
        metamask: {
          conversionRate: 468.58,
          currentCurrency: 'usd',
          network: '3',
          unapprovedTxs: {
            2603411941761054: {
              estimatedGas: '0x5208',
              gasLimitSpecified: false,
              gasPriceSpecified: false,
              history: [],
              id: 2603411941761054,
              loadingDefaults: false,
              metamaskNetworkId: '3',
              origin: 'faucet.metamask.io',
              simpleSend: true,
              status: 'unapproved',
              time: 1530838113716,
              txParams: {
                from: '0xc5ae6383e126f901dcb06131d97a88745bfa88d6',
                gas: '0x33450',
                gasPrice: '0x2540be400',
                to: '0x81b7e08f65bdf5648606c89998a9cc8164397647',
                value: '0xde0b6b3a7640000',
              },
            },
          },
        },
        confirmTransaction: {},
      }

      const middlewares = [thunk]
      const mockStore = configureMockStore(middlewares)
      const store = mockStore(mockState)
      const expectedActions = [
        'metamask/confirm-transaction/UPDATE_TX_DATA',
        'metamask/confirm-transaction/UPDATE_TRANSACTION_AMOUNTS',
        'metamask/confirm-transaction/UPDATE_HEX_GAS_TOTAL',
        'metamask/confirm-transaction/UPDATE_TRANSACTION_FEES',
        'metamask/confirm-transaction/UPDATE_TRANSACTION_TOTALS',
      ]

      store.dispatch(actions.setTransactionToConfirm(2603411941761054))
        .then(() => {
          const storeActions = store.getActions()
          assert.equal(storeActions.length, expectedActions.length)

          storeActions.forEach((action, index) => assert.equal(action.type, expectedActions[index]))
          done()
        })
    })
  })
})