mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-26 12:29:06 +01:00
339 lines
10 KiB
JavaScript
339 lines
10 KiB
JavaScript
import React from 'react';
|
|
import configureMockStore from 'redux-mock-store';
|
|
import { act, fireEvent, screen, waitFor } from '@testing-library/react';
|
|
|
|
import { BigNumber } from '@ethersproject/bignumber';
|
|
import * as TokenUtil from '../../../../shared/lib/token-util.ts';
|
|
import {
|
|
TokenStandard,
|
|
TransactionType,
|
|
} from '../../../../shared/constants/transaction';
|
|
import mockState from '../../../../test/data/mock-state.json';
|
|
import { renderWithProvider } from '../../../../test/lib/render-helpers';
|
|
import { shortenAddress } from '../../../helpers/utils/util';
|
|
import ConfirmPageContainer from '.';
|
|
|
|
const mockOnCancelAll = jest.fn();
|
|
const mockOnCancel = jest.fn();
|
|
const mockOnSubmit = jest.fn();
|
|
const mockHandleCloseEditGas = jest.fn();
|
|
|
|
const props = {
|
|
title: 'Title',
|
|
fromAddress: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5',
|
|
toAddress: '0x7a1A4Ad9cc746a70ee58568466f7996dD0aCE4E8',
|
|
origin: 'testOrigin', // required
|
|
// Footer
|
|
onCancelAll: mockOnCancelAll,
|
|
onCancel: mockOnCancel,
|
|
onSubmit: mockOnSubmit,
|
|
handleCloseEditGas: mockHandleCloseEditGas,
|
|
// Gas Popover
|
|
currentTransaction: {
|
|
id: 8783053010106567,
|
|
time: 1656448479005,
|
|
status: 'unapproved',
|
|
metamaskNetworkId: '5',
|
|
originalGasEstimate: '0x5208',
|
|
userEditedGasLimit: false,
|
|
loadingDefaults: false,
|
|
dappSuggestedGasFees: null,
|
|
sendFlowHistory: [],
|
|
txParams: {
|
|
from: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5',
|
|
to: '0x7a1A4Ad9cc746a70ee58568466f7996dD0aCE4E8',
|
|
value: '0x0',
|
|
gas: '0x5208',
|
|
maxFeePerGas: '0x59682f0d',
|
|
maxPriorityFeePerGas: '0x59682f00',
|
|
},
|
|
origin: 'testOrigin',
|
|
type: 'simpleSend',
|
|
userFeeLevel: 'medium',
|
|
defaultGasEstimates: {
|
|
estimateType: 'medium',
|
|
gas: '0x5208',
|
|
maxFeePerGas: '59682f0d',
|
|
maxPriorityFeePerGas: '59682f00',
|
|
},
|
|
},
|
|
isOwnedAccount: false,
|
|
showAccountInHeader: true,
|
|
showEdit: true,
|
|
hideSenderToRecipient: false,
|
|
toName: '0x7a1...E4E8',
|
|
txData: {
|
|
id: 1230035278491151,
|
|
time: 1671022500513,
|
|
status: 'unapproved',
|
|
metamaskNetworkId: '80001',
|
|
originalGasEstimate: '0xea60',
|
|
userEditedGasLimit: false,
|
|
chainId: '0x13881',
|
|
loadingDefaults: false,
|
|
dappSuggestedGasFees: {
|
|
gasPrice: '0x4a817c800',
|
|
gas: '0xea60',
|
|
},
|
|
sendFlowHistory: [],
|
|
txParams: {
|
|
from: '0xdd34b35ca1de17dfcdc07f79ff1f8f94868c40a1',
|
|
to: '0x7a67ff4a59594a56d46e9308a5c6e197fa83a3cf',
|
|
value: '0x0',
|
|
data: '0x095ea7b30000000000000000000000009bc5baf874d2da8d216ae9f137804184ee5afef40000000000000000000000000000000000000000000000000000000000011170',
|
|
gas: '0xea60',
|
|
maxFeePerGas: '0x0',
|
|
maxPriorityFeePerGas: '0x0',
|
|
},
|
|
origin: 'https://metamask.github.io',
|
|
type: 'simpleSend',
|
|
history: [
|
|
{
|
|
id: 1230035278491151,
|
|
time: 1671022500513,
|
|
status: 'unapproved',
|
|
metamaskNetworkId: '80001',
|
|
originalGasEstimate: '0xea60',
|
|
userEditedGasLimit: false,
|
|
chainId: '0x13881',
|
|
loadingDefaults: true,
|
|
dappSuggestedGasFees: {
|
|
gasPrice: '0x4a817c800',
|
|
gas: '0xea60',
|
|
},
|
|
sendFlowHistory: [],
|
|
txParams: {
|
|
from: '0xdd34b35ca1de17dfcdc07f79ff1f8f94868c40a1',
|
|
to: '0x7a67ff4a59594a56d46e9308a5c6e197fa83a3cf',
|
|
value: '0x0',
|
|
data: '0x095ea7b30000000000000000000000009bc5baf874d2da8d216ae9f137804184ee5afef40000000000000000000000000000000000000000000000000000000000011170',
|
|
gas: '0xea60',
|
|
gasPrice: '0x4a817c800',
|
|
},
|
|
origin: 'https://metamask.github.io',
|
|
type: 'simpleSend',
|
|
},
|
|
[
|
|
{
|
|
op: 'remove',
|
|
path: '/txParams/gasPrice',
|
|
note: 'Added new unapproved transaction.',
|
|
timestamp: 1671022501288,
|
|
},
|
|
{
|
|
op: 'add',
|
|
path: '/txParams/maxFeePerGas',
|
|
value: '0x0',
|
|
},
|
|
{
|
|
op: 'add',
|
|
path: '/txParams/maxPriorityFeePerGas',
|
|
value: '0x0',
|
|
},
|
|
{
|
|
op: 'replace',
|
|
path: '/loadingDefaults',
|
|
value: false,
|
|
},
|
|
{
|
|
op: 'add',
|
|
path: '/userFeeLevel',
|
|
value: 'custom',
|
|
},
|
|
{
|
|
op: 'add',
|
|
path: '/defaultGasEstimates',
|
|
value: {
|
|
estimateType: 'custom',
|
|
gas: '0xea60',
|
|
maxFeePerGas: '0',
|
|
maxPriorityFeePerGas: '0',
|
|
},
|
|
},
|
|
],
|
|
],
|
|
userFeeLevel: 'custom',
|
|
defaultGasEstimates: {
|
|
estimateType: 'custom',
|
|
gas: '0xea60',
|
|
maxFeePerGas: '0',
|
|
maxPriorityFeePerGas: '0',
|
|
},
|
|
},
|
|
};
|
|
|
|
jest.mock('../../../store/actions', () => ({
|
|
disconnectGasFeeEstimatePoller: jest.fn(),
|
|
getGasFeeEstimatesAndStartPolling: jest
|
|
.fn()
|
|
.mockImplementation(() => Promise.resolve()),
|
|
addPollingTokenToAppState: jest.fn(),
|
|
}));
|
|
|
|
jest.mock('../../../pages/swaps/swaps.util', () => {
|
|
const actual = jest.requireActual('../../../pages/swaps/swaps.util');
|
|
return {
|
|
...actual,
|
|
fetchTokenBalance: jest.fn(() => Promise.resolve()),
|
|
};
|
|
});
|
|
|
|
jest.mock('../../../../shared/lib/token-util.ts', () => {
|
|
const actual = jest.requireActual('../../../../shared/lib/token-util.ts');
|
|
return {
|
|
...actual,
|
|
fetchTokenBalance: jest.fn(() => Promise.resolve()),
|
|
};
|
|
});
|
|
|
|
const mockedState = jest.mocked(mockState);
|
|
const mockedProps = jest.mocked(props);
|
|
|
|
const setMockedTransactionType = (type) => {
|
|
mockedProps.currentTransaction.type = type;
|
|
mockedProps.txData.type = type;
|
|
mockedProps.txData.history[0].type = type;
|
|
};
|
|
|
|
describe('Confirm Page Container Container Test', () => {
|
|
afterEach(() => {
|
|
jest.clearAllMocks();
|
|
});
|
|
|
|
describe('Render and simulate button clicks', () => {
|
|
beforeEach(() => {
|
|
const store = configureMockStore()(mockedState);
|
|
renderWithProvider(<ConfirmPageContainer {...props} />, store);
|
|
});
|
|
|
|
it('should render a confirm page container component', () => {
|
|
const pageContainer = screen.queryByTestId('page-container');
|
|
expect(pageContainer).toBeInTheDocument();
|
|
});
|
|
|
|
it('should render navigation', () => {
|
|
const navigationContainer = screen.queryByTestId('navigation-container');
|
|
expect(navigationContainer).toBeInTheDocument();
|
|
});
|
|
|
|
it('should render header', () => {
|
|
const headerContainer = screen.queryByTestId('header-container');
|
|
expect(headerContainer).toBeInTheDocument();
|
|
|
|
const shortenedFromAddress = shortenAddress(props.fromAddress);
|
|
const headerAddress = screen.queryByTestId('header-address');
|
|
expect(headerAddress).toHaveTextContent(shortenedFromAddress);
|
|
});
|
|
|
|
it('should render sender to recipient in header', () => {
|
|
const senderRecipient = screen.queryByTestId('sender-to-recipient');
|
|
expect(senderRecipient).toBeInTheDocument();
|
|
});
|
|
it('should render recipient as address', () => {
|
|
const recipientName = screen.queryByText(shortenAddress(props.toAddress));
|
|
expect(recipientName).toBeInTheDocument();
|
|
});
|
|
|
|
it('should simulate click reject button', () => {
|
|
const rejectButton = screen.getByTestId('page-container-footer-cancel');
|
|
fireEvent.click(rejectButton);
|
|
expect(mockOnCancel).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it('should simulate click submit button', () => {
|
|
const confirmButton = screen.getByTestId('page-container-footer-next');
|
|
fireEvent.click(confirmButton);
|
|
expect(mockOnSubmit).toHaveBeenCalledTimes(1);
|
|
});
|
|
});
|
|
|
|
describe(`when type is '${TransactionType.tokenMethodSetApprovalForAll}'`, () => {
|
|
it('should display warning modal with total token balance', () => {
|
|
const mockValue12AsHexString = '0x0c'; // base-10 representation = 12
|
|
|
|
TokenUtil.fetchTokenBalance.mockImplementation(() => {
|
|
return BigNumber.from(mockValue12AsHexString);
|
|
});
|
|
setMockedTransactionType(TransactionType.tokenMethodSetApprovalForAll);
|
|
const store = configureMockStore()(mockedState);
|
|
|
|
renderWithProvider(
|
|
<ConfirmPageContainer
|
|
{...props}
|
|
showWarningModal
|
|
assetStandard={TokenStandard.ERC721}
|
|
/>,
|
|
store,
|
|
);
|
|
|
|
act(() => {
|
|
const confirmButton = screen.getByTestId('page-container-footer-next');
|
|
fireEvent.click(confirmButton);
|
|
});
|
|
|
|
waitFor(() => {
|
|
expect(
|
|
screen.querySelector('.set-approval-for-all-warning__content'),
|
|
).toBeDefined();
|
|
expect(screen.queryByText('Total: 12')).toBeInTheDocument();
|
|
});
|
|
|
|
expect(mockOnSubmit).toHaveBeenCalledTimes(1);
|
|
});
|
|
});
|
|
|
|
describe('Rendering NetworkAccountBalanceHeader', () => {
|
|
const store = configureMockStore()(mockState);
|
|
|
|
it('should render NetworkAccountBalanceHeader if displayAccountBalanceHeader is true', () => {
|
|
const { getByText } = renderWithProvider(
|
|
<ConfirmPageContainer {...props} displayAccountBalanceHeader />,
|
|
store,
|
|
);
|
|
expect(getByText('Balance')).toBeInTheDocument();
|
|
});
|
|
|
|
it('should not render NetworkAccountBalanceHeader if displayAccountBalanceHeader is false', () => {
|
|
const { queryByText } = renderWithProvider(
|
|
<ConfirmPageContainer {...props} displayAccountBalanceHeader={false} />,
|
|
store,
|
|
);
|
|
expect(queryByText('Balance')).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('Contact/AddressBook name should appear in recipient header', () => {
|
|
it('should not show add to address dialog if recipient is in contact list and should display contact name', () => {
|
|
const addressBookName = 'test save name';
|
|
|
|
const addressBook = {
|
|
'0x5': {
|
|
'0x7a1A4Ad9cc746a70ee58568466f7996dD0aCE4E8': {
|
|
address: '0x7a1A4Ad9cc746a70ee58568466f7996dD0aCE4E8',
|
|
chainId: '054',
|
|
isEns: false,
|
|
memo: '',
|
|
name: addressBookName,
|
|
},
|
|
},
|
|
};
|
|
|
|
mockState.metamask.addressBook = addressBook;
|
|
|
|
const store = configureMockStore()(mockState);
|
|
|
|
renderWithProvider(<ConfirmPageContainer {...props} />, store);
|
|
|
|
// Does not display new address dialog banner
|
|
const newAccountDetectDialog = screen.queryByText(
|
|
/New address detected!/u,
|
|
);
|
|
expect(newAccountDetectDialog).not.toBeInTheDocument();
|
|
|
|
// Shows contact/addressbook name
|
|
const contactName = screen.queryByText(addressBookName);
|
|
expect(contactName).toBeInTheDocument();
|
|
});
|
|
});
|
|
});
|