A Metamask fork with Infura removed and default networks editable
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ciphermask/ui/app/selectors/tests/send.test.js

594 lines
15 KiB

import assert from 'assert'
import sinon from 'sinon'
import {
accountsWithSendEtherInfoSelector,
getCurrentAccountWithSendEtherInfo,
} from '..'
import {
getBlockGasLimit,
getConversionRate,
getCurrentNetwork,
getNativeCurrency,
getGasLimit,
getGasPrice,
getGasTotal,
getPrimaryCurrency,
getSelectedToken,
getSelectedTokenContract,
getSendAmount,
sendAmountIsInError,
getSendEditingTransactionId,
getSendErrors,
getSendFrom,
getSendFromBalance,
getSendFromObject,
getSendHexDataFeatureFlagState,
getSendMaxModeState,
getSendTo,
getSendToAccounts,
getTokenBalance,
getUnapprovedTxs,
gasFeeIsInError,
getGasLoadingError,
getGasButtonGroupShown,
getTitleKey,
isSendFormInError,
} from '../send'
import mockState from './send-selectors-test-data'
describe('send selectors', function () {
const tempGlobalEth = Object.assign({}, global.eth)
beforeEach(function () {
global.eth = {
contract: sinon.stub().returns({
at: (address) => 'mockAt:' + address,
}),
}
})
afterEach(function () {
global.eth = tempGlobalEth
})
describe('accountsWithSendEtherInfoSelector()', function () {
it('should return an array of account objects with name info from identities', function () {
assert.deepEqual(
accountsWithSendEtherInfoSelector(mockState),
[
{
code: '0x',
balance: '0x47c9d71831c76efe',
nonce: '0x1b',
address: '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825',
name: 'Send Account 1',
},
{
code: '0x',
balance: '0x37452b1315889f80',
nonce: '0xa',
address: '0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb',
name: 'Send Account 2',
},
{
code: '0x',
balance: '0x30c9d71831c76efe',
nonce: '0x1c',
address: '0x2f8d4a878cfa04a6e60d46362f5644deab66572d',
name: 'Send Account 3',
},
{
code: '0x',
balance: '0x0',
nonce: '0x0',
address: '0xd85a4b6a394794842887b8284293d69163007bbb',
name: 'Send Account 4',
},
]
)
})
})
describe('getBlockGasLimit', function () {
it('should return the current block gas limit', function () {
assert.deepEqual(
getBlockGasLimit(mockState),
'0x4c1878'
)
})
})
describe('getConversionRate()', function () {
it('should return the eth conversion rate', function () {
assert.deepEqual(
getConversionRate(mockState),
1200.88200327
)
})
})
describe('getCurrentAccountWithSendEtherInfo()', function () {
it('should return the currently selected account with identity info', function () {
assert.deepEqual(
getCurrentAccountWithSendEtherInfo(mockState),
{
code: '0x',
balance: '0x0',
nonce: '0x0',
address: '0xd85a4b6a394794842887b8284293d69163007bbb',
name: 'Send Account 4',
}
)
})
})
describe('getNativeCurrency()', function () {
it('should return the ticker symbol of the selected network', function () {
assert.equal(
getNativeCurrency(mockState),
'ETH'
)
})
})
describe('getCurrentNetwork()', function () {
it('should return the id of the currently selected network', function () {
assert.equal(
getCurrentNetwork(mockState),
'3'
)
})
})
describe('getGasLimit()', function () {
it('should return the send.gasLimit', function () {
assert.equal(
getGasLimit(mockState),
'0xFFFF'
)
})
})
describe('getGasPrice()', function () {
it('should return the send.gasPrice', function () {
assert.equal(
getGasPrice(mockState),
'0xaa'
)
})
})
describe('getGasTotal()', function () {
it('should return the send.gasTotal', function () {
assert.equal(
getGasTotal(mockState),
'a9ff56'
)
})
})
describe('getPrimaryCurrency()', function () {
it('should return the symbol of the selected token', function () {
assert.equal(
getPrimaryCurrency(mockState),
'DEF'
)
})
})
describe('getSelectedToken()', function () {
it('should return the currently selected token if selected', function () {
assert.deepEqual(
getSelectedToken(mockState),
{
address: '0x8d6b81208414189a58339873ab429b6c47ab92d3',
decimals: 4,
symbol: 'DEF',
}
)
})
it('should return the send token if none is currently selected, but a send token exists', function () {
const mockSendToken = {
address: '0x123456708414189a58339873ab429b6c47ab92d3',
decimals: 4,
symbol: 'JKL',
}
const editedMockState = {
metamask: Object.assign({}, mockState.metamask, {
selectedTokenAddress: null,
send: {
token: mockSendToken,
},
}),
}
assert.deepEqual(
getSelectedToken(editedMockState),
Object.assign({}, mockSendToken)
)
})
})
describe('getSelectedTokenContract()', function () {
it('should return the contract at the selected token address', function () {
assert.equal(
getSelectedTokenContract(mockState),
'mockAt:0x8d6b81208414189a58339873ab429b6c47ab92d3'
)
})
it('should return null if no token is selected', function () {
const modifiedMetamaskState = Object.assign({}, mockState.metamask, { selectedTokenAddress: false })
assert.equal(
getSelectedTokenContract(Object.assign({}, mockState, { metamask: modifiedMetamaskState })),
null
)
})
})
describe('getSendAmount()', function () {
it('should return the send.amount', function () {
assert.equal(
getSendAmount(mockState),
'0x080'
)
})
})
describe('getSendEditingTransactionId()', function () {
it('should return the send.editingTransactionId', function () {
assert.equal(
getSendEditingTransactionId(mockState),
97531
)
})
})
describe('getSendErrors()', function () {
it('should return the send.errors', function () {
assert.deepEqual(
getSendErrors(mockState),
{ someError: null }
)
})
})
describe('getSendHexDataFeatureFlagState()', function () {
it('should return the sendHexData feature flag state', function () {
assert.deepEqual(
getSendHexDataFeatureFlagState(mockState),
true
)
})
})
describe('getSendFrom()', function () {
it('should return the send.from', function () {
assert.deepEqual(
getSendFrom(mockState),
'0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb',
)
})
})
describe('getSendFromBalance()', function () {
it('should get the send.from balance if it exists', function () {
assert.equal(
getSendFromBalance(mockState),
'0x37452b1315889f80'
)
})
it('should get the selected account balance if the send.from does not exist', function () {
const editedMockState = {
metamask: Object.assign({}, mockState.metamask, {
send: {
from: null,
},
}),
}
assert.equal(
getSendFromBalance(editedMockState),
'0x0'
)
})
})
describe('getSendFromObject()', function () {
it('should return send.from if it exists', function () {
assert.deepEqual(
getSendFromObject(mockState),
{
address: '0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb',
balance: '0x37452b1315889f80',
code: '0x',
nonce: '0xa',
}
)
})
it('should return the current account if send.from does not exist', function () {
const editedMockState = {
metamask: Object.assign({}, mockState.metamask, {
send: {
from: null,
},
}),
}
assert.deepEqual(
getSendFromObject(editedMockState),
{
code: '0x',
balance: '0x0',
nonce: '0x0',
address: '0xd85a4b6a394794842887b8284293d69163007bbb',
}
)
})
})
describe('getSendMaxModeState()', function () {
it('should return send.maxModeOn', function () {
assert.equal(
getSendMaxModeState(mockState),
false
)
})
})
describe('getSendTo()', function () {
it('should return send.to', function () {
assert.equal(
getSendTo(mockState),
'0x987fedabc'
)
})
})
describe('getSendToAccounts()', function () {
it('should return an array including all the users accounts and the address book', function () {
assert.deepEqual(
getSendToAccounts(mockState),
[
{
code: '0x',
balance: '0x47c9d71831c76efe',
nonce: '0x1b',
address: '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825',
name: 'Send Account 1',
},
{
code: '0x',
balance: '0x37452b1315889f80',
nonce: '0xa',
address: '0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb',
name: 'Send Account 2',
},
{
code: '0x',
balance: '0x30c9d71831c76efe',
nonce: '0x1c',
address: '0x2f8d4a878cfa04a6e60d46362f5644deab66572d',
name: 'Send Account 3',
},
{
code: '0x',
balance: '0x0',
nonce: '0x0',
address: '0xd85a4b6a394794842887b8284293d69163007bbb',
name: 'Send Account 4',
},
{
address: '0x06195827297c7a80a443b6894d3bdb8824b43896',
name: 'Address Book Account 1',
Address book send plus contact list (#6914) * Style Send Header * Move Send to-row to send view and restyle * Add "Recents" group to select recipient view * Rename SendToRow to AddRecipient * Basic UI and Layout * New ENSInput component * wip - fuzzy search for input * small refactor * Add Dialog * contact list initial * initial error on invalid address * clean up edit * Click to open modal * Create AddToAddressBookModal component * Modal styling and layout * modal i18n * Add to Addressbook * ens wip * ens wip * ENS Resolution * Reset input * Send to explicit address * Happy Path Complete * Add back error checking * Reset send-to when emptying input * Add back warning object * Fix linter * Fix unit test #1 - fix import paths * Remove dead tests * One more to go * Fix all unit tests * add unit test for reducers and actions * test rendering AddRecipient * Add tests for dialog boxes in AddRecipient * Add test for validating * Fix linter * Fix e2e tests * Token send e2e fix * Style View Contact * Style edit-contact * Fix e2e * Fix from-import-beta-ui e2e spec * Make section header say "add recipient” by default * Auto-focus add recipient input * Update placeholder text * Update input title font size * Auto advance to next step if user paste a valid address * Ellipsify address when recipient is selected * Fix app header background color on desktop * Give each form row a margin of 16px * Use .container/.component naming pattern for ens-input * Auto-focus on input when add to addressbook modal is opened; Save on Enter * Fix and add unit test * Fix selectors name in e2e tests * Correct e2e test token amount for address-book-send changes * Adds e2e test for editing a transaction * Delete test/integration/lib/send-new-ui.js * Add tests for amount max button and high value error on send screen to test/e2e/metamask-ui.spec.js * lint and revert to address as object keys * add chainId based on current network to address book entry * fix test * only display contacts for the current network * Improve ENS message when not found on current network * Add error to indicate when network does not support ENS * bump gaba * address book, resolve comments * Move contact-list to its own component * De-duplicate getaddressbook selector and refactor name selection logic in contact-list-tab/ * Use contact-list component in contact-list-tab.component (i.e. in settings) * Improve/fix settings headers for popup and browser views * Lint fixes related to address book updates * Add 'My accounts' page to settings address book * Update add new contact button in settings to match floating circular design * Improve styles of view contact page * Improve styles and labels of the add-contact.component * Further lint fixes related to address book updates * Update unit tests as per address book updates * Ensure that contact list groups are sorted alphabetically * Refactor settings component to use a container for connection to redux; allow display of addressbook name in settings header * Decouple ens-input.component from send context * Add ens resolution to add contact screen in settings * Switching networks when an ens address is shown on send form removes the ens address. * Resolve send screen search for ensAddress to matching address book entry if it exists * Show resolved ens icon and address if exists (settings: add-contact.component) * Make the displayed and copied address in view-contact.component the checksummed address * Default alias state prop in AddToAddressBookModal to empty string * Use keyCode to detect enter key in AddToAddressBookModal * Ensure add-contact component properly updates after QR code detection * Fix display of all recents after clicking 'Load More' in contact list * Fix send screen contact searching after network switching * Code cleanup related to address book changes * Update unit tests for address book changes * Update ENS name not found on network message * Add ens registration error message * Cancel on edit mode takes user back to view screen * Adds support for memo to settings contact list view and edit screens * Modify designs of edit and view contact in popup environment * Update settings content list UX to show split columns in fullscreen and proper internal navigation * Correct background address book API usages in UI
5 years ago
chainId: '3',
},
]
)
})
})
describe('getTokenBalance()', function () {
it('should', function () {
assert.equal(
getTokenBalance(mockState),
3434
)
})
})
describe('getUnapprovedTxs()', function () {
it('should return the unapproved txs', function () {
assert.deepEqual(
getUnapprovedTxs(mockState),
{
4768706228115573: {
id: 4768706228115573,
time: 1487363153561,
status: 'unapproved',
gasMultiplier: 1,
metamaskNetworkId: '3',
txParams: {
from: '0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb',
to: '0x18a3462427bcc9133bb46e88bcbe39cd7ef0e761',
value: '0xde0b6b3a7640000',
metamaskId: 4768706228115573,
metamaskNetworkId: '3',
gas: '0x5209',
},
txFee: '17e0186e60800',
txValue: 'de0b6b3a7640000',
maxCost: 'de234b52e4a0800',
gasPrice: '4a817c800',
},
}
)
})
})
describe('send-amount-row selectors', function () {
describe('sendAmountIsInError()', function () {
it('should return true if send.errors.amount is truthy', function () {
const state = {
send: {
errors: {
amount: 'abc',
},
},
}
assert.equal(sendAmountIsInError(state), true)
})
it('should return false if send.errors.amount is falsy', function () {
const state = {
send: {
errors: {
amount: null,
},
},
}
assert.equal(sendAmountIsInError(state), false)
})
})
})
describe('send-gas-row selectors', function () {
describe('getGasLoadingError()', function () {
it('should return send.errors.gasLoading', function () {
const state = {
send: {
errors: {
gasLoading: 'abc',
},
},
}
assert.equal(getGasLoadingError(state), 'abc')
})
})
describe('gasFeeIsInError()', function () {
it('should return true if send.errors.gasFee is truthy', function () {
const state = {
send: {
errors: {
gasFee: 'def',
},
},
}
assert.equal(gasFeeIsInError(state), true)
})
it('should return false send.errors.gasFee is falsely', function () {
const state = {
send: {
errors: {
gasFee: null,
},
},
}
assert.equal(gasFeeIsInError(state), false)
})
})
describe('getGasButtonGroupShown()', function () {
it('should return send.gasButtonGroupShown', function () {
const state = {
send: {
gasButtonGroupShown: 'foobar',
},
}
assert.equal(getGasButtonGroupShown(state), 'foobar')
})
})
})
describe('send-header selectors', function () {
const getMetamaskSendMockState = (send) => {
return {
metamask: {
send: { ...send },
},
}
}
describe('getTitleKey()', function () {
it('should return the correct key when "to" is empty', function () {
assert.equal(getTitleKey(getMetamaskSendMockState({})), 'addRecipient')
})
it('should return the correct key when getSendEditingTransactionId is truthy', function () {
assert.equal(
getTitleKey(
getMetamaskSendMockState({
to: true,
editingTransactionId: true,
token: true, // this can be whatever
})
), 'edit')
})
it('should return the correct key when getSendEditingTransactionId is falsy and getSelectedToken is truthy', function () {
assert.equal(
getTitleKey(
getMetamaskSendMockState({
to: true,
editingTransactionId: false,
token: true,
})
), 'sendTokens')
})
it('should return the correct key when getSendEditingTransactionId is falsy and getSelectedToken is falsy', function () {
assert.equal(
getTitleKey(
getMetamaskSendMockState({
to: true,
editingTransactionId: false,
token: false,
})
), 'sendETH')
})
})
})
describe('send-footer selectors', function () {
const getSendMockState = (send) => {
return {
send: { ...send },
}
}
describe('isSendFormInError()', function () {
it('should return true if any of the values of the object returned by getSendErrors are truthy', function () {
assert.equal(isSendFormInError(
getSendMockState({
errors: [ true ],
})
), true)
})
it('should return false if all of the values of the object returned by getSendErrors are falsy', function () {
assert.equal(isSendFormInError(
getSendMockState({
errors: [],
})
), false)
assert.equal(isSendFormInError(
getSendMockState({
errors: [ false ],
})
), false)
})
})
})
})