mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 01:47:00 +01:00
Final conversion of tests from enzyme to @testing-library/react (#16862)
* Add transaction activity log component * Remove duplicate tx activity log snapshot. * Convert Advanced Tab to tlr. * Lint fix * Change ENS to DNS in mock state data. * Add test ids for speedup, cancel, rety buttons. * Convert TransactionListItemDetails component to RTL. * Convert PageContainerHeader component to RTL. * Convert TokenInput component to RTL. * Convert UnitInput component to RTL. * Convert withModalProps to RTL. * Convert i18n-helper to RTL. * Convert ConfirmSeedPhrase component to TLR. * Convert AddRecipient component to RTL. * Set process.env metamask build type to 'main' for test Co-authored-by: Brad Decker <bhdecker84@gmail.com> Co-authored-by: Pedro Figueiredo <pedro.figueiredo@consensys.net>
This commit is contained in:
parent
a0bb4a6c5a
commit
4c3c4eebac
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"ENS": {
|
"DNS": {
|
||||||
"resolution": ""
|
"resolution": ""
|
||||||
},
|
},
|
||||||
"appState": {
|
"appState": {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"ENS": {
|
"DNS": {
|
||||||
"resolution": ""
|
"resolution": null
|
||||||
},
|
},
|
||||||
"appState": {
|
"appState": {
|
||||||
"networkDropdownOpen": false,
|
"networkDropdownOpen": false,
|
||||||
|
@ -7,6 +7,7 @@ import log from 'loglevel';
|
|||||||
import { JSDOM } from 'jsdom';
|
import { JSDOM } from 'jsdom';
|
||||||
|
|
||||||
process.env.IN_TEST = true;
|
process.env.IN_TEST = true;
|
||||||
|
process.env.METAMASK_BUILD_TYPE = 'main';
|
||||||
|
|
||||||
global.chrome = {
|
global.chrome = {
|
||||||
runtime: { id: 'testid', getManifest: () => ({ manifest_version: 2 }) },
|
runtime: { id: 'testid', getManifest: () => ({ manifest_version: 2 }) },
|
||||||
|
@ -40,6 +40,7 @@ export default function CancelButton({
|
|||||||
detailsModal,
|
detailsModal,
|
||||||
})}
|
})}
|
||||||
disabled={!hasEnoughCancelGas}
|
disabled={!hasEnoughCancelGas}
|
||||||
|
data-testid="cancel-button"
|
||||||
>
|
>
|
||||||
{t('cancel')}
|
{t('cancel')}
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -169,6 +169,7 @@ export default class TransactionListItemDetails extends PureComponent {
|
|||||||
type="primary"
|
type="primary"
|
||||||
onClick={this.handleRetry}
|
onClick={this.handleRetry}
|
||||||
className="transaction-list-item-details__header-button-rounded-button"
|
className="transaction-list-item-details__header-button-rounded-button"
|
||||||
|
data-testid="speedup-button"
|
||||||
>
|
>
|
||||||
{t('speedUp')}
|
{t('speedUp')}
|
||||||
</Button>
|
</Button>
|
||||||
@ -186,6 +187,7 @@ export default class TransactionListItemDetails extends PureComponent {
|
|||||||
type="raised"
|
type="raised"
|
||||||
onClick={this.handleRetry}
|
onClick={this.handleRetry}
|
||||||
className="transaction-list-item-details__header-button"
|
className="transaction-list-item-details__header-button"
|
||||||
|
data-testid="rety-button"
|
||||||
>
|
>
|
||||||
<i className="fa fa-sync"></i>
|
<i className="fa fa-sync"></i>
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -1,234 +1,125 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from 'enzyme';
|
import configureMockStore from 'redux-mock-store';
|
||||||
import Button from '../../ui/button';
|
import thunk from 'redux-thunk';
|
||||||
import SenderToRecipient from '../../ui/sender-to-recipient';
|
|
||||||
import TransactionBreakdown from '../transaction-breakdown';
|
|
||||||
import TransactionActivityLog from '../transaction-activity-log';
|
|
||||||
import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction';
|
import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction';
|
||||||
import { GAS_LIMITS } from '../../../../shared/constants/gas';
|
import { GAS_LIMITS } from '../../../../shared/constants/gas';
|
||||||
import TransactionStatus from '../transaction-status/transaction-status.component';
|
import { renderWithProvider } from '../../../../test/lib/render-helpers';
|
||||||
import TransactionListItemDetails from './transaction-list-item-details.component';
|
import mockState from '../../../../test/data/mock-state.json';
|
||||||
|
import TransactionListItemDetails from '.';
|
||||||
|
|
||||||
|
jest.mock('../../../store/actions.js', () => ({
|
||||||
|
tryReverseResolveAddress: () => jest.fn(),
|
||||||
|
getGasFeeEstimatesAndStartPolling: jest.fn().mockResolvedValue(),
|
||||||
|
addPollingTokenToAppState: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
describe('TransactionListItemDetails Component', () => {
|
describe('TransactionListItemDetails Component', () => {
|
||||||
it('should render properly', () => {
|
const transaction = {
|
||||||
const transaction = {
|
history: [],
|
||||||
history: [],
|
id: 1,
|
||||||
id: 1,
|
status: TRANSACTION_STATUSES.CONFIRMED,
|
||||||
status: TRANSACTION_STATUSES.CONFIRMED,
|
txParams: {
|
||||||
txParams: {
|
from: '0x1',
|
||||||
from: '0x1',
|
gas: GAS_LIMITS.SIMPLE,
|
||||||
gas: GAS_LIMITS.SIMPLE,
|
gasPrice: '0x3b9aca00',
|
||||||
gasPrice: '0x3b9aca00',
|
|
||||||
nonce: '0xa4',
|
|
||||||
to: '0x2',
|
|
||||||
value: '0x2386f26fc10000',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const transactionGroup = {
|
|
||||||
transactions: [transaction],
|
|
||||||
primaryTransaction: transaction,
|
|
||||||
initialTransaction: transaction,
|
|
||||||
};
|
|
||||||
|
|
||||||
const rpcPrefs = {
|
|
||||||
blockExplorerUrl: 'https://customblockexplorer.com/',
|
|
||||||
};
|
|
||||||
|
|
||||||
const blockExplorerLinkText = {
|
|
||||||
firstPart: 'addBlockExplorer',
|
|
||||||
secondPart: '',
|
|
||||||
};
|
|
||||||
|
|
||||||
const wrapper = shallow(
|
|
||||||
<TransactionListItemDetails
|
|
||||||
onClose={() => undefined}
|
|
||||||
title="Test Transaction Details"
|
|
||||||
recipientAddress="0x1"
|
|
||||||
senderAddress="0x2"
|
|
||||||
tryReverseResolveAddress={() => undefined}
|
|
||||||
transactionGroup={transactionGroup}
|
|
||||||
senderNickname="sender-nickname"
|
|
||||||
recipientNickname="recipient-nickname"
|
|
||||||
transactionStatus={TransactionStatus}
|
|
||||||
rpcPrefs={rpcPrefs}
|
|
||||||
blockExplorerLinkText={blockExplorerLinkText}
|
|
||||||
/>,
|
|
||||||
{ context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } },
|
|
||||||
);
|
|
||||||
const child = wrapper.childAt(0);
|
|
||||||
expect(child.hasClass('transaction-list-item-details')).toStrictEqual(true);
|
|
||||||
expect(child.find(Button)).toHaveLength(2);
|
|
||||||
expect(child.find(SenderToRecipient)).toHaveLength(1);
|
|
||||||
expect(child.find(TransactionBreakdown)).toHaveLength(1);
|
|
||||||
expect(child.find(TransactionActivityLog)).toHaveLength(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render a retry button', () => {
|
|
||||||
const transaction = {
|
|
||||||
history: [],
|
|
||||||
id: 1,
|
|
||||||
status: TRANSACTION_STATUSES.CONFIRMED,
|
|
||||||
txParams: {
|
|
||||||
from: '0x1',
|
|
||||||
gas: GAS_LIMITS.SIMPLE,
|
|
||||||
gasPrice: '0x3b9aca00',
|
|
||||||
nonce: '0xa4',
|
|
||||||
to: '0x2',
|
|
||||||
value: '0x2386f26fc10000',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const transactionGroup = {
|
|
||||||
transactions: [transaction],
|
|
||||||
primaryTransaction: transaction,
|
|
||||||
initialTransaction: transaction,
|
|
||||||
nonce: '0xa4',
|
nonce: '0xa4',
|
||||||
hasRetried: false,
|
to: '0x2',
|
||||||
hasCancelled: false,
|
value: '0x2386f26fc10000',
|
||||||
};
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const rpcPrefs = {
|
const transactionGroup = {
|
||||||
blockExplorerUrl: 'https://customblockexplorer.com/',
|
transactions: [transaction],
|
||||||
};
|
primaryTransaction: transaction,
|
||||||
|
initialTransaction: transaction,
|
||||||
|
nonce: '0xa4',
|
||||||
|
hasRetried: false,
|
||||||
|
hasCancelled: false,
|
||||||
|
};
|
||||||
|
|
||||||
const blockExplorerLinkText = {
|
const rpcPrefs = {
|
||||||
firstPart: 'addBlockExplorer',
|
blockExplorerUrl: 'https://customblockexplorer.com/',
|
||||||
secondPart: '',
|
};
|
||||||
};
|
|
||||||
|
|
||||||
const wrapper = shallow(
|
const blockExplorerLinkText = {
|
||||||
<TransactionListItemDetails
|
firstPart: 'addBlockExplorer',
|
||||||
onClose={() => undefined}
|
secondPart: '',
|
||||||
title="Test Transaction Details"
|
};
|
||||||
recipientAddress="0x1"
|
|
||||||
senderAddress="0x2"
|
const props = {
|
||||||
tryReverseResolveAddress={() => undefined}
|
onClose: jest.fn(),
|
||||||
transactionGroup={transactionGroup}
|
title: 'Test Transaction Details',
|
||||||
showSpeedUp
|
recipientAddress: '0xAddress',
|
||||||
senderNickname="sender-nickname"
|
senderAddress: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc',
|
||||||
recipientNickname="recipient-nickname"
|
tryReverseResolveAddress: jest.fn(),
|
||||||
transactionStatus={TransactionStatus}
|
transactionGroup,
|
||||||
rpcPrefs={rpcPrefs}
|
transactionStatus: () => <div></div>,
|
||||||
blockExplorerLinkText={blockExplorerLinkText}
|
blockExplorerLinkText,
|
||||||
/>,
|
rpcPrefs,
|
||||||
{ context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } },
|
};
|
||||||
|
|
||||||
|
it('should render title with title prop', () => {
|
||||||
|
const mockStore = configureMockStore([thunk])(mockState);
|
||||||
|
|
||||||
|
const { queryByText } = renderWithProvider(
|
||||||
|
<TransactionListItemDetails {...props} />,
|
||||||
|
mockStore,
|
||||||
);
|
);
|
||||||
|
|
||||||
const child = wrapper.childAt(0);
|
expect(queryByText(props.title)).toBeInTheDocument();
|
||||||
|
|
||||||
expect(child.hasClass('transaction-list-item-details')).toStrictEqual(true);
|
|
||||||
expect(child.find(Button)).toHaveLength(3);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should disable the Copy Tx ID and View In Etherscan buttons when tx hash is missing', () => {
|
describe('Retry button', () => {
|
||||||
const transaction = {
|
it('should render retry button with showRetry prop', () => {
|
||||||
history: [],
|
const retryProps = {
|
||||||
id: 1,
|
...props,
|
||||||
status: 'confirmed',
|
showRetry: true,
|
||||||
txParams: {
|
};
|
||||||
from: '0x1',
|
|
||||||
gas: GAS_LIMITS.SIMPLE,
|
|
||||||
gasPrice: '0x3b9aca00',
|
|
||||||
nonce: '0xa4',
|
|
||||||
to: '0x2',
|
|
||||||
value: '0x2386f26fc10000',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const transactionGroup = {
|
const mockStore = configureMockStore([thunk])(mockState);
|
||||||
transactions: [transaction],
|
|
||||||
primaryTransaction: transaction,
|
|
||||||
initialTransaction: transaction,
|
|
||||||
};
|
|
||||||
|
|
||||||
const rpcPrefs = {
|
const { queryByTestId } = renderWithProvider(
|
||||||
blockExplorerUrl: 'https://customblockexplorer.com/',
|
<TransactionListItemDetails {...retryProps} />,
|
||||||
};
|
mockStore,
|
||||||
|
);
|
||||||
|
|
||||||
const blockExplorerLinkText = {
|
expect(queryByTestId('rety-button')).toBeInTheDocument();
|
||||||
firstPart: 'addBlockExplorer',
|
});
|
||||||
secondPart: '',
|
|
||||||
};
|
|
||||||
|
|
||||||
const wrapper = shallow(
|
|
||||||
<TransactionListItemDetails
|
|
||||||
onClose={() => undefined}
|
|
||||||
title="Test Transaction Details"
|
|
||||||
recipientAddress="0x1"
|
|
||||||
senderAddress="0x2"
|
|
||||||
tryReverseResolveAddress={() => undefined}
|
|
||||||
transactionGroup={transactionGroup}
|
|
||||||
senderNickname="sender-nickname"
|
|
||||||
recipientNickname="recipient-nickname"
|
|
||||||
transactionStatus={TransactionStatus}
|
|
||||||
rpcPrefs={rpcPrefs}
|
|
||||||
blockExplorerLinkText={blockExplorerLinkText}
|
|
||||||
/>,
|
|
||||||
{ context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } },
|
|
||||||
);
|
|
||||||
|
|
||||||
const child = wrapper.childAt(0);
|
|
||||||
|
|
||||||
expect(child.hasClass('transaction-list-item-details')).toStrictEqual(true);
|
|
||||||
const buttons = child.find(Button);
|
|
||||||
expect(buttons.at(0).prop('disabled')).toStrictEqual(true);
|
|
||||||
expect(buttons.at(1).prop('disabled')).toStrictEqual(true);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render functional Copy Tx ID and View In Etherscan buttons when tx hash exists', () => {
|
describe('Cancel button', () => {
|
||||||
const transaction = {
|
it('should render cancel button with showCancel prop', () => {
|
||||||
history: [],
|
const retryProps = {
|
||||||
id: 1,
|
...props,
|
||||||
status: 'confirmed',
|
showCancel: true,
|
||||||
hash: '0xaa',
|
};
|
||||||
txParams: {
|
|
||||||
from: '0x1',
|
|
||||||
gas: GAS_LIMITS.SIMPLE,
|
|
||||||
gasPrice: '0x3b9aca00',
|
|
||||||
nonce: '0xa4',
|
|
||||||
to: '0x2',
|
|
||||||
value: '0x2386f26fc10000',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const transactionGroup = {
|
const mockStore = configureMockStore([thunk])(mockState);
|
||||||
transactions: [transaction],
|
|
||||||
primaryTransaction: transaction,
|
|
||||||
initialTransaction: transaction,
|
|
||||||
};
|
|
||||||
|
|
||||||
const rpcPrefs = {
|
const { queryByTestId } = renderWithProvider(
|
||||||
blockExplorerUrl: 'https://customblockexplorer.com/',
|
<TransactionListItemDetails {...retryProps} />,
|
||||||
};
|
mockStore,
|
||||||
|
);
|
||||||
|
|
||||||
const blockExplorerLinkText = {
|
expect(queryByTestId('cancel-button')).toBeInTheDocument();
|
||||||
firstPart: 'addBlockExplorer',
|
});
|
||||||
secondPart: '',
|
});
|
||||||
};
|
|
||||||
|
|
||||||
const wrapper = shallow(
|
describe('Speedup button', () => {
|
||||||
<TransactionListItemDetails
|
it('should render speedup button with showSpeedUp prop', () => {
|
||||||
onClose={() => undefined}
|
const retryProps = {
|
||||||
title="Test Transaction Details"
|
...props,
|
||||||
recipientAddress="0x1"
|
showSpeedUp: true,
|
||||||
senderAddress="0x2"
|
};
|
||||||
tryReverseResolveAddress={() => undefined}
|
|
||||||
transactionGroup={transactionGroup}
|
|
||||||
senderNickname="sender-nickname"
|
|
||||||
recipientNickname="recipient-nickname"
|
|
||||||
transactionStatus={TransactionStatus}
|
|
||||||
rpcPrefs={rpcPrefs}
|
|
||||||
blockExplorerLinkText={blockExplorerLinkText}
|
|
||||||
/>,
|
|
||||||
{ context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } },
|
|
||||||
);
|
|
||||||
|
|
||||||
const child = wrapper.childAt(0);
|
const mockStore = configureMockStore([thunk])(mockState);
|
||||||
|
|
||||||
expect(child.hasClass('transaction-list-item-details')).toStrictEqual(true);
|
const { queryByTestId } = renderWithProvider(
|
||||||
const buttons = child.find(Button);
|
<TransactionListItemDetails {...retryProps} />,
|
||||||
expect(buttons.at(0).prop('disabled')).toStrictEqual(false);
|
mockStore,
|
||||||
expect(buttons.at(1).prop('disabled')).toStrictEqual(false);
|
);
|
||||||
|
|
||||||
|
expect(queryByTestId('speedup-button')).toBeInTheDocument();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`Page Container Header should match snapshot 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="page-container__header page-container__header--no-padding-bottom"
|
||||||
|
data-testid="page-container__header"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="page-container__header-row"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="page-container__back-button"
|
||||||
|
>
|
||||||
|
Back
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="page-container__title"
|
||||||
|
>
|
||||||
|
Test Title
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="page-container__subtitle"
|
||||||
|
>
|
||||||
|
Test Subtitle
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
aria-label="close"
|
||||||
|
class="page-container__header-close"
|
||||||
|
/>
|
||||||
|
<ul
|
||||||
|
class="page-container__tabs"
|
||||||
|
>
|
||||||
|
Test Tab
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
@ -1,85 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { shallow } from 'enzyme';
|
|
||||||
import sinon from 'sinon';
|
|
||||||
import PageContainerHeader from './page-container-header.component';
|
|
||||||
|
|
||||||
describe('Page Container Header', () => {
|
|
||||||
let wrapper, style, onBackButtonClick, onClose;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
style = { test: 'style' };
|
|
||||||
onBackButtonClick = sinon.spy();
|
|
||||||
onClose = sinon.spy();
|
|
||||||
|
|
||||||
wrapper = shallow(
|
|
||||||
<PageContainerHeader
|
|
||||||
showBackButton
|
|
||||||
onBackButtonClick={onBackButtonClick}
|
|
||||||
backButtonStyles={style}
|
|
||||||
title="Test Title"
|
|
||||||
subtitle="Test Subtitle"
|
|
||||||
tabs="Test Tab"
|
|
||||||
onClose={onClose}
|
|
||||||
/>,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Render Header Row', () => {
|
|
||||||
it('renders back button', () => {
|
|
||||||
expect(wrapper.find('.page-container__back-button')).toHaveLength(1);
|
|
||||||
expect(wrapper.find('.page-container__back-button').text()).toStrictEqual(
|
|
||||||
'Back',
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('ensures style prop', () => {
|
|
||||||
expect(
|
|
||||||
wrapper.find('.page-container__back-button').props().style,
|
|
||||||
).toStrictEqual(style);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call back button when click is simulated', () => {
|
|
||||||
wrapper.find('.page-container__back-button').prop('onClick')();
|
|
||||||
expect(onBackButtonClick.callCount).toStrictEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Render', () => {
|
|
||||||
let header, headerRow, pageTitle, pageSubtitle, pageClose, pageTab;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
header = wrapper.find('.page-container__header--no-padding-bottom');
|
|
||||||
headerRow = wrapper.find('.page-container__header-row');
|
|
||||||
pageTitle = wrapper.find('.page-container__title');
|
|
||||||
pageSubtitle = wrapper.find('.page-container__subtitle');
|
|
||||||
pageClose = wrapper.find('.page-container__header-close');
|
|
||||||
pageTab = wrapper.find('.page-container__tabs');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders page container', () => {
|
|
||||||
expect(header).toHaveLength(1);
|
|
||||||
expect(headerRow).toHaveLength(1);
|
|
||||||
expect(pageTitle).toHaveLength(1);
|
|
||||||
expect(pageSubtitle).toHaveLength(1);
|
|
||||||
expect(pageClose).toHaveLength(1);
|
|
||||||
expect(pageTab).toHaveLength(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders title', () => {
|
|
||||||
expect(pageTitle.text()).toStrictEqual('Test Title');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders subtitle', () => {
|
|
||||||
expect(pageSubtitle.text()).toStrictEqual('Test Subtitle');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders tabs', () => {
|
|
||||||
expect(pageTab.text()).toStrictEqual('Test Tab');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call close when click is simulated', () => {
|
|
||||||
pageClose.prop('onClick')();
|
|
||||||
expect(onClose.callCount).toStrictEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -0,0 +1,36 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { fireEvent } from '@testing-library/react';
|
||||||
|
import { renderWithProvider } from '../../../../../test/lib/render-helpers';
|
||||||
|
import PageContainerHeader from '.';
|
||||||
|
|
||||||
|
describe('Page Container Header', () => {
|
||||||
|
const props = {
|
||||||
|
showBackButton: true,
|
||||||
|
onBackButtonClick: jest.fn(),
|
||||||
|
backButtonStyles: { test: 'style' },
|
||||||
|
title: 'Test Title',
|
||||||
|
subtitle: 'Test Subtitle',
|
||||||
|
tabs: 'Test Tab',
|
||||||
|
onClose: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
it('should match snapshot', () => {
|
||||||
|
const { container } = renderWithProvider(
|
||||||
|
<PageContainerHeader {...props} />,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(container).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call back button when click is simulated', () => {
|
||||||
|
const { queryByText } = renderWithProvider(
|
||||||
|
<PageContainerHeader {...props} />,
|
||||||
|
);
|
||||||
|
|
||||||
|
const backButton = queryByText('Back');
|
||||||
|
|
||||||
|
fireEvent.click(backButton);
|
||||||
|
|
||||||
|
expect(props.onBackButtonClick).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,37 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`TokenInput Component Name of the group should render properly 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="unit-input"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="unit-input__inputs"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="unit-input__input-container"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="unit-input__input"
|
||||||
|
data-testid="token-input"
|
||||||
|
dir="ltr"
|
||||||
|
placeholder="0"
|
||||||
|
style="width: 1.5ch;"
|
||||||
|
type="number"
|
||||||
|
value="0"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="unit-input__suffix"
|
||||||
|
>
|
||||||
|
TEST
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="currency-input__conversion-component"
|
||||||
|
>
|
||||||
|
No conversion rate available
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
@ -24,6 +24,7 @@ export default class TokenInput extends PureComponent {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
dataTestId: PropTypes.string,
|
||||||
currentCurrency: PropTypes.string,
|
currentCurrency: PropTypes.string,
|
||||||
onChange: PropTypes.func,
|
onChange: PropTypes.func,
|
||||||
value: PropTypes.string,
|
value: PropTypes.string,
|
||||||
|
@ -1,513 +1,117 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { shallow, mount } from 'enzyme';
|
|
||||||
import { Provider } from 'react-redux';
|
|
||||||
import configureMockStore from 'redux-mock-store';
|
import configureMockStore from 'redux-mock-store';
|
||||||
import UnitInput from '../unit-input';
|
import { fireEvent } from '@testing-library/react';
|
||||||
import CurrencyDisplay from '../currency-display';
|
import { renderWithProvider } from '../../../../test/lib/render-helpers';
|
||||||
import TokenInput from './token-input.component';
|
import mockState from '../../../../test/data/mock-state.json';
|
||||||
|
import TokenInput from '.';
|
||||||
|
|
||||||
describe('TokenInput Component', () => {
|
describe('TokenInput Component', () => {
|
||||||
const t = (key) => `translate ${key}`;
|
const props = {
|
||||||
|
dataTestId: 'token-input',
|
||||||
|
onChange: jest.fn(),
|
||||||
|
token: {
|
||||||
|
address: '0x108cf70c7d384c552f42c07c41c0e1e46d77ea0d',
|
||||||
|
symbol: 'TEST',
|
||||||
|
decimals: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
describe('rendering', () => {
|
afterEach(() => {
|
||||||
|
props.onChange.mockReset();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Name of the group', () => {
|
||||||
it('should render properly', () => {
|
it('should render properly', () => {
|
||||||
const mockStore = {
|
const mockStore = configureMockStore()(mockState);
|
||||||
metamask: {
|
|
||||||
currentCurrency: 'usd',
|
|
||||||
conversionRate: 231.06,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const store = configureMockStore()(mockStore);
|
|
||||||
|
|
||||||
const wrapper = mount(
|
const { container } = renderWithProvider(
|
||||||
<Provider store={store}>
|
<TokenInput {...props} />,
|
||||||
<TokenInput
|
mockStore,
|
||||||
token={{
|
|
||||||
address: '0x1',
|
|
||||||
decimals: 4,
|
|
||||||
symbol: 'ABC',
|
|
||||||
}}
|
|
||||||
tokens={[
|
|
||||||
{
|
|
||||||
address: '0x1',
|
|
||||||
decimals: 4,
|
|
||||||
symbol: 'ABC',
|
|
||||||
image: null,
|
|
||||||
isERC721: false,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</Provider>,
|
|
||||||
{
|
|
||||||
context: { t },
|
|
||||||
childContextTypes: {
|
|
||||||
t: PropTypes.func,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(wrapper).toHaveLength(1);
|
expect(container).toMatchSnapshot();
|
||||||
expect(wrapper.find('.unit-input__suffix')).toHaveLength(1);
|
|
||||||
expect(wrapper.find('.unit-input__suffix').text()).toStrictEqual('ABC');
|
|
||||||
expect(
|
|
||||||
wrapper.find('.currency-input__conversion-component'),
|
|
||||||
).toHaveLength(1);
|
|
||||||
expect(
|
|
||||||
wrapper.find('.currency-input__conversion-component').text(),
|
|
||||||
).toStrictEqual('translate noConversionRateAvailable');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render properly with tokenExchangeRates', () => {
|
|
||||||
const mockStore = {
|
|
||||||
metamask: {
|
|
||||||
currentCurrency: 'usd',
|
|
||||||
conversionRate: 231.06,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const store = configureMockStore()(mockStore);
|
|
||||||
|
|
||||||
const wrapper = mount(
|
|
||||||
<Provider store={store}>
|
|
||||||
<TokenInput
|
|
||||||
token={{
|
|
||||||
address: '0x1',
|
|
||||||
decimals: 4,
|
|
||||||
symbol: 'ABC',
|
|
||||||
}}
|
|
||||||
tokens={[
|
|
||||||
{
|
|
||||||
address: '0x1',
|
|
||||||
decimals: 4,
|
|
||||||
symbol: 'ABC',
|
|
||||||
image: null,
|
|
||||||
isERC721: false,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
tokenExchangeRates={{ '0x1': 2 }}
|
|
||||||
/>
|
|
||||||
</Provider>,
|
|
||||||
{
|
|
||||||
context: { t },
|
|
||||||
childContextTypes: {
|
|
||||||
t: PropTypes.func,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(wrapper).toHaveLength(1);
|
|
||||||
expect(wrapper.find('.unit-input__suffix')).toHaveLength(1);
|
|
||||||
expect(wrapper.find('.unit-input__suffix').text()).toStrictEqual('ABC');
|
|
||||||
expect(wrapper.find(CurrencyDisplay)).toHaveLength(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render properly with a token value for ETH', () => {
|
|
||||||
const mockStore = {
|
|
||||||
metamask: {
|
|
||||||
currentCurrency: 'usd',
|
|
||||||
conversionRate: 231.06,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const store = configureMockStore()(mockStore);
|
|
||||||
|
|
||||||
const wrapper = mount(
|
|
||||||
<Provider store={store}>
|
|
||||||
<TokenInput
|
|
||||||
value="2710"
|
|
||||||
token={{
|
|
||||||
address: '0x1',
|
|
||||||
decimals: 4,
|
|
||||||
symbol: 'ABC',
|
|
||||||
}}
|
|
||||||
tokens={[
|
|
||||||
{
|
|
||||||
address: '0x1',
|
|
||||||
decimals: 4,
|
|
||||||
symbol: 'ABC',
|
|
||||||
image: null,
|
|
||||||
isERC721: false,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
tokenExchangeRates={{ '0x1': 2 }}
|
|
||||||
/>
|
|
||||||
</Provider>,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(wrapper).toHaveLength(1);
|
|
||||||
const tokenInputInstance = wrapper.find(TokenInput).at(0).instance();
|
|
||||||
expect(tokenInputInstance.state.decimalValue).toStrictEqual('1');
|
|
||||||
expect(tokenInputInstance.state.hexValue).toStrictEqual('2710');
|
|
||||||
expect(wrapper.find('.unit-input__suffix')).toHaveLength(1);
|
|
||||||
expect(wrapper.find('.unit-input__suffix').text()).toStrictEqual('ABC');
|
|
||||||
expect(wrapper.find('.unit-input__input').props().value).toStrictEqual(
|
|
||||||
'1',
|
|
||||||
);
|
|
||||||
expect(wrapper.find('.currency-display-component').text()).toStrictEqual(
|
|
||||||
'2ETH',
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render properly with a token value for fiat', () => {
|
|
||||||
const mockStore = {
|
|
||||||
metamask: {
|
|
||||||
currentCurrency: 'usd',
|
|
||||||
conversionRate: 231.06,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const store = configureMockStore()(mockStore);
|
|
||||||
|
|
||||||
const wrapper = mount(
|
|
||||||
<Provider store={store}>
|
|
||||||
<TokenInput
|
|
||||||
value="2710"
|
|
||||||
token={{
|
|
||||||
address: '0x1',
|
|
||||||
decimals: 4,
|
|
||||||
symbol: 'ABC',
|
|
||||||
}}
|
|
||||||
tokens={[
|
|
||||||
{
|
|
||||||
address: '0x1',
|
|
||||||
decimals: 4,
|
|
||||||
symbol: 'ABC',
|
|
||||||
image: null,
|
|
||||||
isERC721: false,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
tokenExchangeRates={{ '0x1': 2 }}
|
|
||||||
showFiat
|
|
||||||
currentCurrency="usd"
|
|
||||||
/>
|
|
||||||
</Provider>,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(wrapper).toHaveLength(1);
|
|
||||||
const tokenInputInstance = wrapper.find(TokenInput).at(0).instance();
|
|
||||||
expect(tokenInputInstance.state.decimalValue).toStrictEqual('1');
|
|
||||||
expect(tokenInputInstance.state.hexValue).toStrictEqual('2710');
|
|
||||||
expect(wrapper.find('.unit-input__suffix')).toHaveLength(1);
|
|
||||||
expect(wrapper.find('.unit-input__suffix').text()).toStrictEqual('ABC');
|
|
||||||
expect(wrapper.find('.unit-input__input').props().value).toStrictEqual(
|
|
||||||
'1',
|
|
||||||
);
|
|
||||||
expect(wrapper.find('.currency-display-component').text()).toStrictEqual(
|
|
||||||
'$462.12USD',
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render properly with a token value for fiat, but hideConversion is true', () => {
|
|
||||||
const mockStore = {
|
|
||||||
metamask: {
|
|
||||||
currentCurrency: 'usd',
|
|
||||||
conversionRate: 231.06,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const store = configureMockStore()(mockStore);
|
|
||||||
|
|
||||||
const wrapper = mount(
|
|
||||||
<Provider store={store}>
|
|
||||||
<TokenInput
|
|
||||||
value="2710"
|
|
||||||
token={{
|
|
||||||
address: '0x1',
|
|
||||||
decimals: 4,
|
|
||||||
symbol: 'ABC',
|
|
||||||
}}
|
|
||||||
tokens={[
|
|
||||||
{
|
|
||||||
address: '0x1',
|
|
||||||
decimals: 4,
|
|
||||||
symbol: 'ABC',
|
|
||||||
image: null,
|
|
||||||
isERC721: false,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
tokenExchangeRates={{ '0x1': 2 }}
|
|
||||||
showFiat
|
|
||||||
hideConversion
|
|
||||||
/>
|
|
||||||
</Provider>,
|
|
||||||
{
|
|
||||||
context: { t },
|
|
||||||
childContextTypes: {
|
|
||||||
t: PropTypes.func,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(wrapper).toHaveLength(1);
|
|
||||||
const tokenInputInstance = wrapper.find(TokenInput).at(0).instance();
|
|
||||||
expect(tokenInputInstance.state.decimalValue).toStrictEqual('1');
|
|
||||||
expect(tokenInputInstance.state.hexValue).toStrictEqual('2710');
|
|
||||||
expect(wrapper.find('.unit-input__suffix')).toHaveLength(1);
|
|
||||||
expect(wrapper.find('.unit-input__suffix').text()).toStrictEqual('ABC');
|
|
||||||
expect(wrapper.find('.unit-input__input').props().value).toStrictEqual(
|
|
||||||
'1',
|
|
||||||
);
|
|
||||||
expect(
|
|
||||||
wrapper.find('.currency-input__conversion-component').text(),
|
|
||||||
).toStrictEqual('translate noConversionRateAvailable');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('handling actions', () => {
|
describe('Conversion Display', () => {
|
||||||
const handleChangeSpy = jest.fn();
|
it('should render conversionRate', () => {
|
||||||
|
const showFiatState = {
|
||||||
afterEach(() => {
|
...mockState,
|
||||||
handleChangeSpy.mockClear();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call onChange on input changes with the hex value for ETH', () => {
|
|
||||||
const mockStore = {
|
|
||||||
metamask: {
|
metamask: {
|
||||||
currentCurrency: 'usd',
|
...mockState.metamask,
|
||||||
conversionRate: 231.06,
|
preferences: {
|
||||||
|
...mockState.metamask.preferences,
|
||||||
|
showFiatInTestnets: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const store = configureMockStore()(mockStore);
|
const mockStore = configureMockStore()(showFiatState);
|
||||||
const wrapper = mount(
|
|
||||||
<Provider store={store}>
|
const { queryByTitle } = renderWithProvider(
|
||||||
<TokenInput
|
<TokenInput {...props} />,
|
||||||
onChange={handleChangeSpy}
|
mockStore,
|
||||||
token={{
|
|
||||||
address: '0x1',
|
|
||||||
decimals: 4,
|
|
||||||
symbol: 'ABC',
|
|
||||||
}}
|
|
||||||
tokens={[
|
|
||||||
{
|
|
||||||
address: '0x1',
|
|
||||||
decimals: 4,
|
|
||||||
symbol: 'ABC',
|
|
||||||
image: null,
|
|
||||||
isERC721: false,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
tokenExchangeRates={{ '0x1': 2 }}
|
|
||||||
/>
|
|
||||||
</Provider>,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(wrapper).toHaveLength(1);
|
expect(queryByTitle('0 ETH')).toBeInTheDocument();
|
||||||
expect(handleChangeSpy.mock.calls).toHaveLength(0);
|
|
||||||
|
|
||||||
const tokenInputInstance = wrapper.find(TokenInput).at(0).instance();
|
|
||||||
expect(tokenInputInstance.state.decimalValue).toStrictEqual(0);
|
|
||||||
expect(tokenInputInstance.state.hexValue).toBeUndefined();
|
|
||||||
expect(wrapper.find('.currency-display-component').text()).toStrictEqual(
|
|
||||||
'0ETH',
|
|
||||||
);
|
|
||||||
const input = wrapper.find('input');
|
|
||||||
expect(input.props().value).toStrictEqual(0);
|
|
||||||
|
|
||||||
input.simulate('change', { target: { value: '1' } });
|
|
||||||
expect(handleChangeSpy.mock.calls).toHaveLength(1);
|
|
||||||
expect(handleChangeSpy.mock.calls[0][0]).toStrictEqual('2710');
|
|
||||||
expect(wrapper.find('.currency-display-component').text()).toStrictEqual(
|
|
||||||
'2ETH',
|
|
||||||
);
|
|
||||||
expect(tokenInputInstance.state.decimalValue).toStrictEqual('1');
|
|
||||||
expect(tokenInputInstance.state.hexValue).toStrictEqual('2710');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call onChange on input changes with the hex value for fiat', () => {
|
it('should render showFiat', () => {
|
||||||
const mockStore = {
|
const showFiatState = {
|
||||||
|
...mockState,
|
||||||
metamask: {
|
metamask: {
|
||||||
currentCurrency: 'usd',
|
...mockState.metamask,
|
||||||
conversionRate: 231.06,
|
preferences: {
|
||||||
|
...mockState.metamask.preferences,
|
||||||
|
showFiatInTestnets: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const store = configureMockStore()(mockStore);
|
|
||||||
const wrapper = mount(
|
|
||||||
<Provider store={store}>
|
|
||||||
<TokenInput
|
|
||||||
onChange={handleChangeSpy}
|
|
||||||
token={{
|
|
||||||
address: '0x1',
|
|
||||||
decimals: 4,
|
|
||||||
symbol: 'ABC',
|
|
||||||
}}
|
|
||||||
tokens={[
|
|
||||||
{
|
|
||||||
address: '0x1',
|
|
||||||
decimals: 4,
|
|
||||||
symbol: 'ABC',
|
|
||||||
image: null,
|
|
||||||
isERC721: false,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
tokenExchangeRates={{ '0x1': 2 }}
|
|
||||||
showFiat
|
|
||||||
currentCurrency="usd"
|
|
||||||
/>
|
|
||||||
</Provider>,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(wrapper).toHaveLength(1);
|
const showFiatProps = {
|
||||||
expect(handleChangeSpy.mock.calls).toHaveLength(0);
|
...props,
|
||||||
|
showFiat: true,
|
||||||
const tokenInputInstance = wrapper.find(TokenInput).at(0).instance();
|
|
||||||
expect(tokenInputInstance.state.decimalValue).toStrictEqual(0);
|
|
||||||
expect(tokenInputInstance.state.hexValue).toBeUndefined();
|
|
||||||
expect(wrapper.find('.currency-display-component').text()).toStrictEqual(
|
|
||||||
'$0.00USD',
|
|
||||||
);
|
|
||||||
const input = wrapper.find('input');
|
|
||||||
expect(input.props().value).toStrictEqual(0);
|
|
||||||
|
|
||||||
input.simulate('change', { target: { value: '1' } });
|
|
||||||
expect(handleChangeSpy.mock.calls).toHaveLength(1);
|
|
||||||
expect(handleChangeSpy.mock.calls[0][0]).toStrictEqual('2710');
|
|
||||||
expect(wrapper.find('.currency-display-component').text()).toStrictEqual(
|
|
||||||
'$462.12USD',
|
|
||||||
);
|
|
||||||
expect(tokenInputInstance.state.decimalValue).toStrictEqual('1');
|
|
||||||
expect(tokenInputInstance.state.hexValue).toStrictEqual('2710');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should change the state and pass in a new decimalValue when props.value changes', () => {
|
|
||||||
const mockStore = {
|
|
||||||
metamask: {
|
|
||||||
currentCurrency: 'usd',
|
|
||||||
conversionRate: 231.06,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
const store = configureMockStore()(mockStore);
|
|
||||||
const wrapper = shallow(
|
const mockStore = configureMockStore()(showFiatState);
|
||||||
<Provider store={store}>
|
|
||||||
<TokenInput
|
const { queryByTitle } = renderWithProvider(
|
||||||
onChange={handleChangeSpy}
|
<TokenInput {...showFiatProps} />,
|
||||||
token={{
|
mockStore,
|
||||||
address: '0x1',
|
|
||||||
decimals: 4,
|
|
||||||
symbol: 'ABC',
|
|
||||||
}}
|
|
||||||
tokens={[
|
|
||||||
{
|
|
||||||
address: '0x1',
|
|
||||||
decimals: 4,
|
|
||||||
symbol: 'ABC',
|
|
||||||
image: null,
|
|
||||||
isERC721: false,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
tokenExchangeRates={{ '0x1': 2 }}
|
|
||||||
showFiat
|
|
||||||
/>
|
|
||||||
</Provider>,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(wrapper).toHaveLength(1);
|
expect(queryByTitle('$0.00 USD')).toBeInTheDocument();
|
||||||
const tokenInputInstance = wrapper.find(TokenInput).dive();
|
|
||||||
expect(tokenInputInstance.state('decimalValue')).toStrictEqual(0);
|
|
||||||
expect(tokenInputInstance.state('hexValue')).toBeUndefined();
|
|
||||||
expect(tokenInputInstance.find(UnitInput).props().value).toStrictEqual(0);
|
|
||||||
|
|
||||||
tokenInputInstance.setProps({ value: '2710' });
|
|
||||||
tokenInputInstance.update();
|
|
||||||
expect(tokenInputInstance.state('decimalValue')).toStrictEqual('1');
|
|
||||||
expect(tokenInputInstance.state('hexValue')).toStrictEqual('2710');
|
|
||||||
expect(tokenInputInstance.find(UnitInput).props().value).toStrictEqual(
|
|
||||||
'1',
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Token Input Decimals Check', () => {
|
describe('handle', () => {
|
||||||
const handleChangeSpy = jest.fn();
|
it('should handle', () => {
|
||||||
|
const mockStore = configureMockStore()(mockState);
|
||||||
|
|
||||||
afterEach(() => {
|
const { queryByTestId } = renderWithProvider(
|
||||||
handleChangeSpy.mockClear();
|
<TokenInput {...props} />,
|
||||||
|
mockStore,
|
||||||
|
);
|
||||||
|
|
||||||
|
const tokenInput = queryByTestId('token-input');
|
||||||
|
|
||||||
|
fireEvent.change(tokenInput, { target: { value: '2' } });
|
||||||
|
|
||||||
|
expect(props.onChange).toHaveBeenCalledWith('2');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render incorrect hex onChange when input decimals is more than token decimals', () => {
|
it('should blur', () => {
|
||||||
const mockStore = {
|
const mockStore = configureMockStore()(mockState);
|
||||||
metamask: {
|
|
||||||
currentCurrency: 'usd',
|
const { queryByTestId } = renderWithProvider(
|
||||||
conversionRate: 231.06,
|
<TokenInput {...props} />,
|
||||||
},
|
mockStore,
|
||||||
};
|
|
||||||
const store = configureMockStore()(mockStore);
|
|
||||||
const wrapper = mount(
|
|
||||||
<Provider store={store}>
|
|
||||||
<TokenInput
|
|
||||||
onChange={handleChangeSpy}
|
|
||||||
token={{
|
|
||||||
address: '0x1',
|
|
||||||
decimals: 4,
|
|
||||||
symbol: 'ABC',
|
|
||||||
}}
|
|
||||||
tokens={[
|
|
||||||
{
|
|
||||||
address: '0x1',
|
|
||||||
decimals: 4,
|
|
||||||
symbol: 'ABC',
|
|
||||||
image: null,
|
|
||||||
isERC721: false,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
tokenExchangeRates={{ '0x1': 2 }}
|
|
||||||
showFiat
|
|
||||||
currentCurrency="usd"
|
|
||||||
/>
|
|
||||||
</Provider>,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(wrapper).toHaveLength(1);
|
const tokenInput = queryByTestId('token-input');
|
||||||
expect(handleChangeSpy.mock.calls).toHaveLength(0);
|
|
||||||
|
|
||||||
const input = wrapper.find('input');
|
fireEvent.blur(tokenInput, { target: { value: '2' } });
|
||||||
expect(input.props().value).toStrictEqual(0);
|
|
||||||
|
|
||||||
input.simulate('change', { target: { value: '1.11111' } });
|
expect(props.onChange).toHaveBeenCalledWith('2');
|
||||||
expect(handleChangeSpy.mock.calls).toHaveLength(1);
|
|
||||||
|
|
||||||
expect(handleChangeSpy.mock.calls[0][0]).toStrictEqual(
|
|
||||||
'2b67.1999999999999999999a',
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render correct hex onChange when input decimals is more than token decimals by omitting excess fractional part on blur', () => {
|
|
||||||
const mockStore = {
|
|
||||||
metamask: {
|
|
||||||
currentCurrency: 'usd',
|
|
||||||
conversionRate: 231.06,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const store = configureMockStore()(mockStore);
|
|
||||||
|
|
||||||
const wrapper = mount(
|
|
||||||
<Provider store={store}>
|
|
||||||
<TokenInput
|
|
||||||
onChange={handleChangeSpy}
|
|
||||||
token={{
|
|
||||||
address: '0x1',
|
|
||||||
decimals: 4,
|
|
||||||
symbol: 'ABC',
|
|
||||||
}}
|
|
||||||
tokens={[
|
|
||||||
{
|
|
||||||
address: '0x1',
|
|
||||||
decimals: 4,
|
|
||||||
symbol: 'ABC',
|
|
||||||
image: null,
|
|
||||||
isERC721: false,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
tokenExchangeRates={{ '0x1': 2 }}
|
|
||||||
showFiat
|
|
||||||
currentCurrency="usd"
|
|
||||||
/>
|
|
||||||
</Provider>,
|
|
||||||
);
|
|
||||||
expect(wrapper).toHaveLength(1);
|
|
||||||
|
|
||||||
const input = wrapper.find('input');
|
|
||||||
|
|
||||||
input.simulate('blur', { target: { value: '1.11111' } });
|
|
||||||
|
|
||||||
expect(handleChangeSpy.mock.calls).toHaveLength(1);
|
|
||||||
expect(handleChangeSpy.mock.calls[0][0]).toStrictEqual('2b67');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -0,0 +1,111 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`UnitInput Component rendering should match snapshot of error class when props.error === true 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="unit-input unit-input--error"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="unit-input__inputs"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="unit-input__input-container"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="unit-input__input"
|
||||||
|
dir="ltr"
|
||||||
|
placeholder="0"
|
||||||
|
style="width: 1.5ch;"
|
||||||
|
type="number"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`UnitInput Component rendering should match snapshot with a child component 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="unit-input"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="unit-input__inputs"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="unit-input__input-container"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="unit-input__input"
|
||||||
|
dir="ltr"
|
||||||
|
placeholder="0"
|
||||||
|
style="width: 1.5ch;"
|
||||||
|
type="number"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="testing"
|
||||||
|
>
|
||||||
|
TESTCOMPONENT
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`UnitInput Component rendering should match snapshot with a suffix 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="unit-input"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="unit-input__inputs"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="unit-input__input-container"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="unit-input__input"
|
||||||
|
dir="ltr"
|
||||||
|
placeholder="0"
|
||||||
|
style="width: 1.5ch;"
|
||||||
|
type="number"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="unit-input__suffix"
|
||||||
|
>
|
||||||
|
ETH
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`UnitInput Component rendering should match snapshot without a suffix 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="unit-input"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="unit-input__inputs"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="unit-input__input-container"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="unit-input__input"
|
||||||
|
dir="ltr"
|
||||||
|
placeholder="0"
|
||||||
|
style="width: 1.5ch;"
|
||||||
|
type="number"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
@ -1,98 +1,59 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow, mount } from 'enzyme';
|
import { fireEvent } from '@testing-library/react';
|
||||||
import sinon from 'sinon';
|
import { renderWithProvider } from '../../../../test/lib/render-helpers';
|
||||||
import UnitInput from './unit-input.component';
|
import UnitInput from './unit-input.component';
|
||||||
|
|
||||||
describe('UnitInput Component', () => {
|
describe('UnitInput Component', () => {
|
||||||
describe('rendering', () => {
|
describe('rendering', () => {
|
||||||
it('should render properly without a suffix', () => {
|
it('should match snapshot without a suffix', () => {
|
||||||
const wrapper = shallow(<UnitInput />);
|
const { container } = renderWithProvider(<UnitInput />);
|
||||||
|
|
||||||
expect(wrapper).toHaveLength(1);
|
expect(container).toMatchSnapshot();
|
||||||
expect(wrapper.find('.unit-input__suffix')).toHaveLength(0);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render properly with a suffix', () => {
|
it('should match snapshot with a suffix', () => {
|
||||||
const wrapper = shallow(<UnitInput suffix="ETH" />);
|
const { container } = renderWithProvider(<UnitInput suffix="ETH" />);
|
||||||
|
|
||||||
expect(wrapper).toHaveLength(1);
|
expect(container).toMatchSnapshot();
|
||||||
expect(wrapper.find('.unit-input__suffix')).toHaveLength(1);
|
|
||||||
expect(wrapper.find('.unit-input__suffix').text()).toStrictEqual('ETH');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render properly with a child component', () => {
|
it('should match snapshot with a child component', () => {
|
||||||
const wrapper = shallow(
|
const { container } = renderWithProvider(
|
||||||
<UnitInput>
|
<UnitInput>
|
||||||
<div className="testing">TESTCOMPONENT</div>
|
<div className="testing">TESTCOMPONENT</div>
|
||||||
</UnitInput>,
|
</UnitInput>,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(wrapper).toHaveLength(1);
|
expect(container).toMatchSnapshot();
|
||||||
expect(wrapper.find('.testing')).toHaveLength(1);
|
|
||||||
expect(wrapper.find('.testing').text()).toStrictEqual('TESTCOMPONENT');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render with an error class when props.error === true', () => {
|
it('should match snapshot of error class when props.error === true', () => {
|
||||||
const wrapper = shallow(<UnitInput error />);
|
const { container } = renderWithProvider(<UnitInput error />);
|
||||||
|
|
||||||
expect(wrapper).toHaveLength(1);
|
expect(container).toMatchSnapshot();
|
||||||
expect(wrapper.find('.unit-input--error')).toHaveLength(1);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('handling actions', () => {
|
describe('handling actions', () => {
|
||||||
const handleChangeSpy = sinon.spy();
|
const handleChangeSpy = jest.fn();
|
||||||
const handleBlurSpy = sinon.spy();
|
const handleOnBlurSpy = jest.fn();
|
||||||
|
|
||||||
afterEach(() => {
|
it('should call onChange and onBlur on input changes with the value', async () => {
|
||||||
handleChangeSpy.resetHistory();
|
const { queryByTestId } = renderWithProvider(
|
||||||
handleBlurSpy.resetHistory();
|
<UnitInput
|
||||||
});
|
onChange={handleChangeSpy}
|
||||||
|
onBlur={handleOnBlurSpy}
|
||||||
|
dataTestId="unit-input"
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
it('should focus the input on component click', () => {
|
const input = queryByTestId('unit-input');
|
||||||
const wrapper = mount(<UnitInput />);
|
|
||||||
|
|
||||||
expect(wrapper).toHaveLength(1);
|
fireEvent.blur(input);
|
||||||
const handleFocusSpy = sinon.spy(wrapper.instance(), 'handleFocus');
|
fireEvent.change(input, { target: { value: 2 } });
|
||||||
wrapper.instance().forceUpdate();
|
|
||||||
wrapper.update();
|
|
||||||
expect(handleFocusSpy.callCount).toStrictEqual(0);
|
|
||||||
wrapper.find('.unit-input').simulate('click');
|
|
||||||
expect(handleFocusSpy.callCount).toStrictEqual(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call onChange on input changes with the value', () => {
|
expect(handleOnBlurSpy).toHaveBeenCalled();
|
||||||
const wrapper = mount(<UnitInput onChange={handleChangeSpy} />);
|
expect(handleChangeSpy).toHaveBeenCalledWith('2');
|
||||||
|
|
||||||
expect(wrapper).toHaveLength(1);
|
|
||||||
expect(handleChangeSpy.callCount).toStrictEqual(0);
|
|
||||||
const input = wrapper.find('input');
|
|
||||||
input.simulate('change', { target: { value: 123 } });
|
|
||||||
expect(handleChangeSpy.callCount).toStrictEqual(1);
|
|
||||||
expect(handleChangeSpy.calledWith(123)).toStrictEqual(true);
|
|
||||||
expect(wrapper.state('value')).toStrictEqual(123);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set the component state value with props.value', () => {
|
|
||||||
const wrapper = mount(<UnitInput value={123} />);
|
|
||||||
|
|
||||||
expect(wrapper).toHaveLength(1);
|
|
||||||
expect(wrapper.state('value')).toStrictEqual(123);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should update the component state value with props.value', () => {
|
|
||||||
const wrapper = mount(<UnitInput onChange={handleChangeSpy} />);
|
|
||||||
|
|
||||||
expect(wrapper).toHaveLength(1);
|
|
||||||
expect(handleChangeSpy.callCount).toStrictEqual(0);
|
|
||||||
const input = wrapper.find('input');
|
|
||||||
input.simulate('change', { target: { value: 123 } });
|
|
||||||
expect(wrapper.state('value')).toStrictEqual(123);
|
|
||||||
expect(handleChangeSpy.callCount).toStrictEqual(1);
|
|
||||||
expect(handleChangeSpy.calledWith(123)).toStrictEqual(true);
|
|
||||||
wrapper.setProps({ value: 456 });
|
|
||||||
expect(wrapper.state('value')).toStrictEqual(456);
|
|
||||||
expect(handleChangeSpy.callCount).toStrictEqual(1);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`withModalProps should return a component wrapped with modal state props 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="test"
|
||||||
|
>
|
||||||
|
Testing
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
@ -1,6 +1,6 @@
|
|||||||
import configureMockStore from 'redux-mock-store';
|
import configureMockStore from 'redux-mock-store';
|
||||||
import { mount } from 'enzyme';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { renderWithProvider } from '../../../../test/lib/render-helpers';
|
||||||
import withModalProps from './with-modal-props';
|
import withModalProps from './with-modal-props';
|
||||||
|
|
||||||
const mockState = {
|
const mockState = {
|
||||||
@ -22,16 +22,10 @@ describe('withModalProps', () => {
|
|||||||
const TestComponent = () => <div className="test">Testing</div>;
|
const TestComponent = () => <div className="test">Testing</div>;
|
||||||
const WrappedComponent = withModalProps(TestComponent);
|
const WrappedComponent = withModalProps(TestComponent);
|
||||||
const store = configureMockStore()(mockState);
|
const store = configureMockStore()(mockState);
|
||||||
const wrapper = mount(<WrappedComponent store={store} />);
|
const { container } = renderWithProvider(
|
||||||
|
<WrappedComponent store={store} />,
|
||||||
|
);
|
||||||
|
|
||||||
expect(wrapper).toHaveLength(1);
|
expect(container).toMatchSnapshot();
|
||||||
const testComponent = wrapper.find(TestComponent).at(0);
|
|
||||||
expect(testComponent).toHaveLength(1);
|
|
||||||
expect(testComponent.find('.test').text()).toStrictEqual('Testing');
|
|
||||||
const testComponentProps = testComponent.props();
|
|
||||||
expect(testComponentProps.prop1).toStrictEqual('prop1');
|
|
||||||
expect(testComponentProps.prop2).toStrictEqual(2);
|
|
||||||
expect(testComponentProps.prop3).toStrictEqual(true);
|
|
||||||
expect(typeof testComponentProps.hideModal).toStrictEqual('function');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
65
ui/helpers/utils/__snapshots__/i18n-helper.test.js.snap
Normal file
65
ui/helpers/utils/__snapshots__/i18n-helper.test.js.snap
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`i18n helper getMessage should return the correct message when a single react substitution is made 1`] = `
|
||||||
|
<div>
|
||||||
|
<span>
|
||||||
|
|
||||||
|
Testing a react substitution
|
||||||
|
<div
|
||||||
|
style="color: red;"
|
||||||
|
>
|
||||||
|
TEST_SUBSTITUTION_1
|
||||||
|
</div>
|
||||||
|
.
|
||||||
|
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`i18n helper getMessage should return the correct message when substituting a mix of react elements and strings 1`] = `
|
||||||
|
<div>
|
||||||
|
<span>
|
||||||
|
|
||||||
|
Testing a mix
|
||||||
|
TEST_SUBSTITUTION_1
|
||||||
|
of react substitutions
|
||||||
|
<div
|
||||||
|
style="color: orange;"
|
||||||
|
>
|
||||||
|
TEST_SUBSTITUTION_3
|
||||||
|
</div>
|
||||||
|
and string substitutions
|
||||||
|
TEST_SUBSTITUTION_2
|
||||||
|
+
|
||||||
|
<div
|
||||||
|
style="color: pink;"
|
||||||
|
>
|
||||||
|
TEST_SUBSTITUTION_4
|
||||||
|
</div>
|
||||||
|
.
|
||||||
|
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`i18n helper getMessage should return the correct message when two react substitutions are made 1`] = `
|
||||||
|
<div>
|
||||||
|
<span>
|
||||||
|
|
||||||
|
Testing a react substitution
|
||||||
|
<div
|
||||||
|
style="color: red;"
|
||||||
|
>
|
||||||
|
TEST_SUBSTITUTION_1
|
||||||
|
</div>
|
||||||
|
and another
|
||||||
|
<div
|
||||||
|
style="color: blue;"
|
||||||
|
>
|
||||||
|
TEST_SUBSTITUTION_2
|
||||||
|
</div>
|
||||||
|
.
|
||||||
|
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
`;
|
@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from 'enzyme';
|
import { renderWithProvider } from '../../../test/lib/render-helpers';
|
||||||
import { getMessage } from './i18n-helper';
|
import { getMessage } from './i18n-helper';
|
||||||
|
|
||||||
describe('i18n helper', () => {
|
describe('i18n helper', () => {
|
||||||
@ -76,17 +76,17 @@ describe('i18n helper', () => {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
const TEST_SUBSTITUTION_7_1 = (
|
const TEST_SUBSTITUTION_7_1 = (
|
||||||
<div style={{ color: 'red' }} key="test-react-substitutions-1">
|
<div style={{ color: 'red' }} key="test-react-substitutions-7-1">
|
||||||
{t(TEST_KEY_7_HELPER_1)}
|
{t(TEST_KEY_7_HELPER_1)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
const TEST_SUBSTITUTION_7_2 = (
|
const TEST_SUBSTITUTION_7_2 = (
|
||||||
<div style={{ color: 'blue' }} key="test-react-substitutions-1">
|
<div style={{ color: 'blue' }} key="test-react-substitutions-7-2">
|
||||||
{t(TEST_KEY_7_HELPER_2)}
|
{t(TEST_KEY_7_HELPER_2)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
const TEST_SUBSTITUTION_8_1 = (
|
const TEST_SUBSTITUTION_8_1 = (
|
||||||
<div style={{ color: 'orange' }} key="test-react-substitutions-1">
|
<div style={{ color: 'orange' }} key="test-react-substitutions-8-1">
|
||||||
{t(TEST_KEY_8_HELPER_1)}
|
{t(TEST_KEY_8_HELPER_1)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -141,9 +141,10 @@ describe('i18n helper', () => {
|
|||||||
|
|
||||||
it('should return the correct message when a single react substitution is made', () => {
|
it('should return the correct message when a single react substitution is made', () => {
|
||||||
const result = t(TEST_KEY_6, [TEST_SUBSTITUTION_6]);
|
const result = t(TEST_KEY_6, [TEST_SUBSTITUTION_6]);
|
||||||
expect(shallow(result).html()).toStrictEqual(
|
|
||||||
'<span> Testing a react substitution <div style="color:red">TEST_SUBSTITUTION_1</div>. </span>',
|
const { container } = renderWithProvider(result);
|
||||||
);
|
|
||||||
|
expect(container).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return the correct message when two react substitutions are made', () => {
|
it('should return the correct message when two react substitutions are made', () => {
|
||||||
@ -151,9 +152,10 @@ describe('i18n helper', () => {
|
|||||||
TEST_SUBSTITUTION_7_1,
|
TEST_SUBSTITUTION_7_1,
|
||||||
TEST_SUBSTITUTION_7_2,
|
TEST_SUBSTITUTION_7_2,
|
||||||
]);
|
]);
|
||||||
expect(shallow(result).html()).toStrictEqual(
|
|
||||||
'<span> Testing a react substitution <div style="color:red">TEST_SUBSTITUTION_1</div> and another <div style="color:blue">TEST_SUBSTITUTION_2</div>. </span>',
|
const { container } = renderWithProvider(result);
|
||||||
);
|
|
||||||
|
expect(container).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return the correct message when substituting a mix of react elements and strings', () => {
|
it('should return the correct message when substituting a mix of react elements and strings', () => {
|
||||||
@ -163,9 +165,10 @@ describe('i18n helper', () => {
|
|||||||
TEST_SUBSTITUTION_2,
|
TEST_SUBSTITUTION_2,
|
||||||
TEST_SUBSTITUTION_8_2,
|
TEST_SUBSTITUTION_8_2,
|
||||||
]);
|
]);
|
||||||
expect(shallow(result).html()).toStrictEqual(
|
|
||||||
'<span> Testing a mix TEST_SUBSTITUTION_1 of react substitutions <div style="color:orange">TEST_SUBSTITUTION_3</div> and string substitutions TEST_SUBSTITUTION_2 + <div style="color:pink">TEST_SUBSTITUTION_4</div>. </span>',
|
const { container } = renderWithProvider(result);
|
||||||
);
|
|
||||||
|
expect(container).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,125 +1,43 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from 'enzyme';
|
import { DragDropContextProvider } from 'react-dnd';
|
||||||
import sinon from 'sinon';
|
import HTML5Backend from 'react-dnd-html5-backend';
|
||||||
import ConfirmSeedPhrase from './confirm-seed-phrase/confirm-seed-phrase.component';
|
import configureMockStore from 'redux-mock-store';
|
||||||
|
import { fireEvent, waitFor } from '@testing-library/react';
|
||||||
|
import thunk from 'redux-thunk';
|
||||||
|
import { renderWithProvider } from '../../../../test/lib/render-helpers';
|
||||||
|
import ConfirmSeedPhrase from './confirm-seed-phrase';
|
||||||
|
|
||||||
function shallowRender(props = {}, context = {}) {
|
jest.mock('../../../store/actions.js', () => ({
|
||||||
return shallow(<ConfirmSeedPhrase {...props} />, {
|
setSeedPhraseBackedUp: () => jest.fn().mockResolvedValue(),
|
||||||
context: {
|
}));
|
||||||
t: (str) => `${str}_t`,
|
|
||||||
...context,
|
const seedPhrase = '鼠 牛 虎 兔 龍 蛇 馬 羊 猴 雞 狗 豬';
|
||||||
},
|
|
||||||
});
|
function shallowRender(props = {}) {
|
||||||
|
const mockState = {};
|
||||||
|
const mockStore = configureMockStore([thunk])(mockState);
|
||||||
|
|
||||||
|
return renderWithProvider(
|
||||||
|
<DragDropContextProvider backend={HTML5Backend}>
|
||||||
|
<ConfirmSeedPhrase {...props} />
|
||||||
|
</DragDropContextProvider>,
|
||||||
|
mockStore,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('ConfirmSeedPhrase Component', () => {
|
describe('ConfirmSeedPhrase Component', () => {
|
||||||
it('should render correctly', () => {
|
it('should render correctly', () => {
|
||||||
const component = shallowRender({
|
const { queryAllByTestId } = shallowRender({
|
||||||
seedPhrase: '鼠 牛 虎 兔 龍 蛇 馬 羊 猴 雞 狗 豬',
|
seedPhrase,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(
|
// Regex ommitted the empty/undefined draggable boxes
|
||||||
component.find('.confirm-seed-phrase__seed-word--sorted'),
|
expect(queryAllByTestId(/draggable-seed-(?!.*undefined)/u)).toHaveLength(
|
||||||
).toHaveLength(12);
|
12,
|
||||||
});
|
|
||||||
|
|
||||||
it('should add/remove selected on click', () => {
|
|
||||||
const trackEventSpy = sinon.spy();
|
|
||||||
const replaceSpy = sinon.spy();
|
|
||||||
const component = shallowRender(
|
|
||||||
{
|
|
||||||
seedPhrase: '鼠 牛 虎 兔 龍 蛇 馬 羊 猴 雞 狗 豬',
|
|
||||||
history: { replace: replaceSpy },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
trackEvent: trackEventSpy,
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const seeds = component.find('.confirm-seed-phrase__seed-word--sorted');
|
// For 24 word mnemonic phrases.
|
||||||
|
expect(queryAllByTestId(/draggable-seed-undefined/u)).toHaveLength(24);
|
||||||
// Click on 3 seeds to add to selected
|
|
||||||
seeds.at(0).simulate('click');
|
|
||||||
seeds.at(1).simulate('click');
|
|
||||||
seeds.at(2).simulate('click');
|
|
||||||
|
|
||||||
expect(component.state().selectedSeedIndices).toStrictEqual([0, 1, 2]);
|
|
||||||
|
|
||||||
// Click on a selected seed to remove
|
|
||||||
component.state();
|
|
||||||
component.update();
|
|
||||||
component.state();
|
|
||||||
component
|
|
||||||
.find('.confirm-seed-phrase__seed-word--sorted')
|
|
||||||
.at(1)
|
|
||||||
.simulate('click');
|
|
||||||
expect(component.state().selectedSeedIndices).toStrictEqual([0, 2]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render correctly on hover', () => {
|
|
||||||
const trackEventSpy = sinon.spy();
|
|
||||||
const replaceSpy = sinon.spy();
|
|
||||||
const component = shallowRender(
|
|
||||||
{
|
|
||||||
seedPhrase: '鼠 牛 虎 兔 龍 蛇 馬 羊 猴 雞 狗 豬',
|
|
||||||
history: { replace: replaceSpy },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
trackEvent: trackEventSpy,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const seeds = component.find('.confirm-seed-phrase__seed-word--sorted');
|
|
||||||
|
|
||||||
// Click on 3 seeds to add to selected
|
|
||||||
seeds.at(0).simulate('click');
|
|
||||||
seeds.at(1).simulate('click');
|
|
||||||
seeds.at(2).simulate('click');
|
|
||||||
|
|
||||||
// Dragging Seed # 2 to 0 placeth
|
|
||||||
component.instance().setDraggingSeedIndex(2);
|
|
||||||
component.instance().setHoveringIndex(0);
|
|
||||||
|
|
||||||
component.update();
|
|
||||||
|
|
||||||
const pendingSeeds = component.find(
|
|
||||||
'.confirm-seed-phrase__selected-seed-words__pending-seed',
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(pendingSeeds.at(0).props().seedIndex).toStrictEqual(2);
|
|
||||||
expect(pendingSeeds.at(1).props().seedIndex).toStrictEqual(0);
|
|
||||||
expect(pendingSeeds.at(2).props().seedIndex).toStrictEqual(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should insert seed in place on drop', () => {
|
|
||||||
const trackEventSpy = sinon.spy();
|
|
||||||
const replaceSpy = sinon.spy();
|
|
||||||
const component = shallowRender(
|
|
||||||
{
|
|
||||||
seedPhrase: '鼠 牛 虎 兔 龍 蛇 馬 羊 猴 雞 狗 豬',
|
|
||||||
history: { replace: replaceSpy },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
trackEvent: trackEventSpy,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const seeds = component.find('.confirm-seed-phrase__seed-word--sorted');
|
|
||||||
|
|
||||||
// Click on 3 seeds to add to selected
|
|
||||||
seeds.at(0).simulate('click');
|
|
||||||
seeds.at(1).simulate('click');
|
|
||||||
seeds.at(2).simulate('click');
|
|
||||||
|
|
||||||
// Drop Seed # 2 to 0 placeth
|
|
||||||
component.instance().setDraggingSeedIndex(2);
|
|
||||||
component.instance().setHoveringIndex(0);
|
|
||||||
component.instance().onDrop(0);
|
|
||||||
|
|
||||||
component.update();
|
|
||||||
|
|
||||||
expect(component.state().selectedSeedIndices).toStrictEqual([2, 0, 1]);
|
|
||||||
expect(component.state().pendingSeedIndices).toStrictEqual([2, 0, 1]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should submit correctly', async () => {
|
it('should submit correctly', async () => {
|
||||||
@ -137,41 +55,25 @@ describe('ConfirmSeedPhrase Component', () => {
|
|||||||
'狗',
|
'狗',
|
||||||
'豬',
|
'豬',
|
||||||
];
|
];
|
||||||
const trackEventSpy = sinon.spy();
|
|
||||||
const replaceSpy = sinon.spy();
|
|
||||||
const component = shallowRender(
|
|
||||||
{
|
|
||||||
seedPhrase: '鼠 牛 虎 兔 龍 蛇 馬 羊 猴 雞 狗 豬',
|
|
||||||
history: { replace: replaceSpy },
|
|
||||||
setSeedPhraseBackedUp: () => Promise.resolve(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
trackEvent: trackEventSpy,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const sorted = component.state().sortedSeedWords;
|
const history = {
|
||||||
const seeds = component.find('.confirm-seed-phrase__seed-word--sorted');
|
replace: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const { queryByTestId } = shallowRender({
|
||||||
|
seedPhrase,
|
||||||
|
history,
|
||||||
|
});
|
||||||
|
|
||||||
originalSeed.forEach((seed) => {
|
originalSeed.forEach((seed) => {
|
||||||
const seedIndex = sorted.findIndex((s) => s === seed);
|
fireEvent.click(queryByTestId(`draggable-seed-${seed}`));
|
||||||
seeds.at(seedIndex).simulate('click');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
component.update();
|
const confirmSeedPhrase = queryByTestId('confirm-dragged-seed-phrase');
|
||||||
|
fireEvent.click(confirmSeedPhrase);
|
||||||
|
|
||||||
component.find('.first-time-flow__button').simulate('click');
|
await waitFor(() => {
|
||||||
|
expect(history.replace).toHaveBeenCalledWith('/initialize/end-of-flow');
|
||||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
||||||
|
|
||||||
expect(trackEventSpy.args[0][0]).toStrictEqual({
|
|
||||||
category: 'Onboarding',
|
|
||||||
event: 'Wallet Created',
|
|
||||||
properties: {
|
|
||||||
account_type: 'metamask',
|
|
||||||
is_backup_skipped: false,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
expect(replaceSpy.args[0][0]).toStrictEqual('/initialize/end-of-flow');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -198,6 +198,7 @@ export default class ConfirmSeedPhrase extends PureComponent {
|
|||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
|
data-testid="confirm-dragged-seed-phrase"
|
||||||
className="first-time-flow__button"
|
className="first-time-flow__button"
|
||||||
onClick={this.handleSubmit}
|
onClick={this.handleSubmit}
|
||||||
disabled={!this.isValid()}
|
disabled={!this.isValid()}
|
||||||
|
@ -0,0 +1,541 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`Add Recipient Component Domain Resolution should match snapshot 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-item"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class=""
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="identicon"
|
||||||
|
style="height: 28px; width: 28px; border-radius: 14px;"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="border-radius: 50px; overflow: hidden; padding: 0px; margin: 0px; width: 28px; height: 28px; display: inline-block; background: rgb(24, 151, 242);"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
height="28"
|
||||||
|
width="28"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
>
|
||||||
|
<rect
|
||||||
|
fill="#2362E1"
|
||||||
|
height="28"
|
||||||
|
transform="translate(3.140663911693453 -4.667521795329333) rotate(458.4 14 14)"
|
||||||
|
width="28"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
fill="#F94301"
|
||||||
|
height="28"
|
||||||
|
transform="translate(-13.443026878443934 6.993307681050803) rotate(268.8 14 14)"
|
||||||
|
width="28"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
fill="#FA7900"
|
||||||
|
height="28"
|
||||||
|
transform="translate(-7.941722319388745 25.795013895597954) rotate(117.3 14 14)"
|
||||||
|
width="28"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-item__content"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-item__title"
|
||||||
|
>
|
||||||
|
DNS Re...tion
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Add Recipient Component Own Account Recipient Search should match snapshot 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__list"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
class="button btn-link send__select-recipient-wrapper__list__link"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
class="send__select-recipient-wrapper__list__back-caret"
|
||||||
|
fill="currentColor"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 512 512"
|
||||||
|
width="24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="m335 113c8 8 8 22 0 30l-113 113 113 113c8 8 8 22 0 30-8 8-22 8-30 0l-128-128c-8-8-8-22 0-30l128-128c8-8 22-8 30 0z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
Back to all
|
||||||
|
</a>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group"
|
||||||
|
data-testid="recipient-group"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-label"
|
||||||
|
>
|
||||||
|
My accounts
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-item"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class=""
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="identicon"
|
||||||
|
style="height: 28px; width: 28px; border-radius: 14px;"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="border-radius: 50px; overflow: hidden; padding: 0px; margin: 0px; width: 28px; height: 28px; display: inline-block; background: rgb(250, 58, 0);"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
height="28"
|
||||||
|
width="28"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
>
|
||||||
|
<rect
|
||||||
|
fill="#18CDF2"
|
||||||
|
height="28"
|
||||||
|
transform="translate(-0.9173443158196976 -2.8912485607779366) rotate(328.9 14 14)"
|
||||||
|
width="28"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
fill="#035E56"
|
||||||
|
height="28"
|
||||||
|
transform="translate(-16.01115399522804 9.268404137780026) rotate(176.2 14 14)"
|
||||||
|
width="28"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
fill="#F26602"
|
||||||
|
height="28"
|
||||||
|
transform="translate(14.584361765945934 -12.429497257622447) rotate(468.9 14 14)"
|
||||||
|
width="28"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-item__content"
|
||||||
|
data-testid="recipient"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-item__title"
|
||||||
|
>
|
||||||
|
Test Account
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-item__subtitle"
|
||||||
|
>
|
||||||
|
0x0dcd...e7bc
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-item"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class=""
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="identicon"
|
||||||
|
style="height: 28px; width: 28px; border-radius: 14px;"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="border-radius: 50px; overflow: hidden; padding: 0px; margin: 0px; width: 28px; height: 28px; display: inline-block; background: rgb(245, 143, 0);"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
height="28"
|
||||||
|
width="28"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
>
|
||||||
|
<rect
|
||||||
|
fill="#018E74"
|
||||||
|
height="28"
|
||||||
|
transform="translate(5.524091896954402 -4.749745570944453) rotate(358.4 14 14)"
|
||||||
|
width="28"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
fill="#18CAF2"
|
||||||
|
height="28"
|
||||||
|
transform="translate(6.724913619395038 -10.621076649467508) rotate(414.8 14 14)"
|
||||||
|
width="28"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
fill="#C81474"
|
||||||
|
height="28"
|
||||||
|
transform="translate(-4.907795154940259 -21.945972385956175) rotate(322.3 14 14)"
|
||||||
|
width="28"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-item__content"
|
||||||
|
data-testid="recipient"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-item__title"
|
||||||
|
>
|
||||||
|
Test Account 2
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-item__subtitle"
|
||||||
|
>
|
||||||
|
0xec1a...251b
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-item"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class=""
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="identicon"
|
||||||
|
style="height: 28px; width: 28px; border-radius: 14px;"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="border-radius: 50px; overflow: hidden; padding: 0px; margin: 0px; width: 28px; height: 28px; display: inline-block; background: rgb(249, 100, 1);"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
height="28"
|
||||||
|
width="28"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
>
|
||||||
|
<rect
|
||||||
|
fill="#C81432"
|
||||||
|
height="28"
|
||||||
|
transform="translate(-0.510690249475231 -2.7159619403490534) rotate(331.7 14 14)"
|
||||||
|
width="28"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
fill="#187AF2"
|
||||||
|
height="28"
|
||||||
|
transform="translate(-11.127931122273568 5.54021528290869) rotate(160.5 14 14)"
|
||||||
|
width="28"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
fill="#FB183E"
|
||||||
|
height="28"
|
||||||
|
transform="translate(25.084575445435807 -2.611206239472919) rotate(517.6 14 14)"
|
||||||
|
width="28"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-item__content"
|
||||||
|
data-testid="recipient"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-item__title"
|
||||||
|
>
|
||||||
|
Test Ledger 1
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-item__subtitle"
|
||||||
|
>
|
||||||
|
0xc42e...8813
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-item"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class=""
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="identicon"
|
||||||
|
style="height: 28px; width: 28px; border-radius: 14px;"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="border-radius: 50px; overflow: hidden; padding: 0px; margin: 0px; width: 28px; height: 28px; display: inline-block; background: rgb(242, 206, 2);"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
height="28"
|
||||||
|
width="28"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
>
|
||||||
|
<rect
|
||||||
|
fill="#2340E1"
|
||||||
|
height="28"
|
||||||
|
transform="translate(-1.7054541409645272 -0.893781972900803) rotate(257.0 14 14)"
|
||||||
|
width="28"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
fill="#016D8E"
|
||||||
|
height="28"
|
||||||
|
transform="translate(11.213543194590896 2.66257866392058) rotate(77.0 14 14)"
|
||||||
|
width="28"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
fill="#F5F500"
|
||||||
|
height="28"
|
||||||
|
transform="translate(11.486654880888956 -19.46641853277226) rotate(465.0 14 14)"
|
||||||
|
width="28"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-item__content"
|
||||||
|
data-testid="recipient"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-item__title"
|
||||||
|
>
|
||||||
|
Test Account 3
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-item__subtitle"
|
||||||
|
>
|
||||||
|
0xeb9e...4823
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Add Recipient Component Send State should match snapshot 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-item"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class=""
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="identicon"
|
||||||
|
style="height: 28px; width: 28px; border-radius: 14px;"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="border-radius: 50px; overflow: hidden; padding: 0px; margin: 0px; width: 28px; height: 28px; display: inline-block; background: rgb(245, 143, 0);"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
height="28"
|
||||||
|
width="28"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
>
|
||||||
|
<rect
|
||||||
|
fill="#018E74"
|
||||||
|
height="28"
|
||||||
|
transform="translate(5.524091896954402 -4.749745570944453) rotate(358.4 14 14)"
|
||||||
|
width="28"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
fill="#18CAF2"
|
||||||
|
height="28"
|
||||||
|
transform="translate(6.724913619395038 -10.621076649467508) rotate(414.8 14 14)"
|
||||||
|
width="28"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
fill="#C81474"
|
||||||
|
height="28"
|
||||||
|
transform="translate(-4.907795154940259 -21.945972385956175) rotate(322.3 14 14)"
|
||||||
|
width="28"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-item__content"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-item__title"
|
||||||
|
>
|
||||||
|
A
|
||||||
|
c
|
||||||
|
c
|
||||||
|
o
|
||||||
|
u
|
||||||
|
n
|
||||||
|
t
|
||||||
|
|
||||||
|
2
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-item__subtitle"
|
||||||
|
>
|
||||||
|
0xec1a...251b
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Add Recipient Component render should match snapshot 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__list"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__list"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
class="button btn-link send__select-recipient-wrapper__list__link"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
Transfer between my accounts
|
||||||
|
</a>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__recent-group-wrapper"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group"
|
||||||
|
data-testid="recipient-group"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-label"
|
||||||
|
>
|
||||||
|
A
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-item"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class=""
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="identicon"
|
||||||
|
style="height: 28px; width: 28px; border-radius: 14px;"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="border-radius: 50px; overflow: hidden; padding: 0px; margin: 0px; width: 28px; height: 28px; display: inline-block; background: rgb(249, 100, 1);"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
height="28"
|
||||||
|
width="28"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
>
|
||||||
|
<rect
|
||||||
|
fill="#C81432"
|
||||||
|
height="28"
|
||||||
|
transform="translate(-0.510690249475231 -2.7159619403490534) rotate(331.7 14 14)"
|
||||||
|
width="28"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
fill="#187AF2"
|
||||||
|
height="28"
|
||||||
|
transform="translate(-11.127931122273568 5.54021528290869) rotate(160.5 14 14)"
|
||||||
|
width="28"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
fill="#FB183E"
|
||||||
|
height="28"
|
||||||
|
transform="translate(25.084575445435807 -2.611206239472919) rotate(517.6 14 14)"
|
||||||
|
width="28"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-item__content"
|
||||||
|
data-testid="recipient"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-item__title"
|
||||||
|
>
|
||||||
|
Address Book Account 1
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="send__select-recipient-wrapper__group-item__subtitle"
|
||||||
|
>
|
||||||
|
0xc42e...8813
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
@ -1,178 +1,61 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from 'enzyme';
|
import configureMockStore from 'redux-mock-store';
|
||||||
import sinon from 'sinon';
|
import { renderWithProvider } from '../../../../../test/lib/render-helpers';
|
||||||
import Dialog from '../../../../components/ui/dialog';
|
import mockState from '../../../../../test/data/mock-state.json';
|
||||||
import AddRecipient from './add-recipient.component';
|
import mockSendState from '../../../../../test/data/mock-send-state.json';
|
||||||
|
import AddRecipient from '.';
|
||||||
const propsMethodSpies = {
|
|
||||||
updateRecipient: sinon.spy(),
|
|
||||||
useMyAccountsForRecipientSearch: sinon.spy(),
|
|
||||||
useContactListForRecipientSearch: sinon.spy(),
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('AddRecipient Component', () => {
|
|
||||||
let wrapper;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper = shallow(
|
|
||||||
<AddRecipient
|
|
||||||
userInput=""
|
|
||||||
recipient={{
|
|
||||||
address: '',
|
|
||||||
nickname: '',
|
|
||||||
error: '',
|
|
||||||
warning: '',
|
|
||||||
}}
|
|
||||||
updateSendTo={propsMethodSpies.updateSendTo}
|
|
||||||
updateSendToError={propsMethodSpies.updateSendToError}
|
|
||||||
updateSendToWarning={propsMethodSpies.updateSendToWarning}
|
|
||||||
addressBook={[
|
|
||||||
{
|
|
||||||
address: '0x80F061544cC398520615B5d3e7A3BedD70cd4510',
|
|
||||||
name: 'Fav 5',
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
nonContacts={[
|
|
||||||
{
|
|
||||||
address: '0x70F061544cC398520615B5d3e7A3BedD70cd4510',
|
|
||||||
name: 'Fav 7',
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
contacts={[
|
|
||||||
{
|
|
||||||
address: '0x60F061544cC398520615B5d3e7A3BedD70cd4510',
|
|
||||||
name: 'Fav 6',
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>,
|
|
||||||
{ context: { t: (str) => `${str}_t` } },
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
propsMethodSpies.updateRecipient.resetHistory();
|
|
||||||
propsMethodSpies.useMyAccountsForRecipientSearch.resetHistory();
|
|
||||||
propsMethodSpies.useContactListForRecipientSearch.resetHistory();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
describe('Add Recipient Component', () => {
|
||||||
describe('render', () => {
|
describe('render', () => {
|
||||||
it('should render a component', () => {
|
const mockStore = configureMockStore()(mockState);
|
||||||
expect(wrapper.find('.send__select-recipient-wrapper')).toHaveLength(1);
|
it('should match snapshot', () => {
|
||||||
|
const { container } = renderWithProvider(<AddRecipient />, mockStore);
|
||||||
|
|
||||||
|
expect(container).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should render no content if there are no recents, transfers, and contacts', () => {
|
describe('Send State', () => {
|
||||||
wrapper.setProps({
|
const mockStore = configureMockStore()(mockSendState);
|
||||||
ownedAccounts: [],
|
|
||||||
addressBook: [],
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(
|
it('should match snapshot', () => {
|
||||||
wrapper.find('.send__select-recipient-wrapper__list__link'),
|
const { container } = renderWithProvider(<AddRecipient />, mockStore);
|
||||||
).toHaveLength(0);
|
|
||||||
expect(
|
expect(container).toMatchSnapshot();
|
||||||
wrapper.find('.send__select-recipient-wrapper__group'),
|
|
||||||
).toHaveLength(0);
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should render transfer', () => {
|
describe('Domain Resolution', () => {
|
||||||
wrapper.setProps({
|
const mockDomainResolutionState = {
|
||||||
isUsingMyAccountsForRecipientSearch: true,
|
...mockState,
|
||||||
ownedAccounts: [
|
DNS: {
|
||||||
{ address: '0x123', name: '123' },
|
resolution: 'DNS Resolution',
|
||||||
{ address: '0x124', name: '124' },
|
},
|
||||||
],
|
};
|
||||||
addressBook: [{ address: '0x456', name: 'test-name' }],
|
const mockStore = configureMockStore()(mockDomainResolutionState);
|
||||||
});
|
|
||||||
wrapper.setState({ isShowingTransfer: true });
|
|
||||||
|
|
||||||
const xferLink = wrapper.find(
|
it('should match snapshot', () => {
|
||||||
'.send__select-recipient-wrapper__list__link',
|
const { container } = renderWithProvider(<AddRecipient />, mockStore);
|
||||||
);
|
|
||||||
expect(xferLink).toHaveLength(1);
|
|
||||||
|
|
||||||
const groups = wrapper.find('RecipientGroup');
|
expect(container).toMatchSnapshot();
|
||||||
expect(
|
|
||||||
groups.shallow().find('.send__select-recipient-wrapper__group'),
|
|
||||||
).toHaveLength(1);
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should render ContactList', () => {
|
describe('Own Account Recipient Search', () => {
|
||||||
wrapper.setProps({
|
const ownAccountSeachState = {
|
||||||
ownedAccounts: [
|
...mockState,
|
||||||
{ address: '0x123', name: '123' },
|
send: {
|
||||||
{ address: '0x124', name: '124' },
|
...mockState.send,
|
||||||
],
|
recipientInput: 'Test',
|
||||||
addressBook: [{ address: '0x125' }],
|
recipientMode: 'MY_ACCOUNTS',
|
||||||
});
|
},
|
||||||
|
};
|
||||||
|
const mockStore = configureMockStore()(ownAccountSeachState);
|
||||||
|
|
||||||
const contactList = wrapper.find('ContactList');
|
it('should match snapshot', () => {
|
||||||
|
const { container } = renderWithProvider(<AddRecipient />, mockStore);
|
||||||
|
|
||||||
expect(contactList).toHaveLength(1);
|
expect(container).toMatchSnapshot();
|
||||||
});
|
|
||||||
|
|
||||||
it('should render contacts', () => {
|
|
||||||
wrapper.setProps({
|
|
||||||
addressBook: [
|
|
||||||
{ address: '0x125', name: 'alice' },
|
|
||||||
{ address: '0x126', name: 'alex' },
|
|
||||||
{ address: '0x127', name: 'catherine' },
|
|
||||||
],
|
|
||||||
});
|
|
||||||
wrapper.setState({ isShowingTransfer: false });
|
|
||||||
|
|
||||||
const xferLink = wrapper.find(
|
|
||||||
'.send__select-recipient-wrapper__list__link',
|
|
||||||
);
|
|
||||||
expect(xferLink).toHaveLength(0);
|
|
||||||
|
|
||||||
const groups = wrapper.find('ContactList');
|
|
||||||
expect(groups).toHaveLength(1);
|
|
||||||
|
|
||||||
expect(
|
|
||||||
groups.find('.send__select-recipient-wrapper__group-item'),
|
|
||||||
).toHaveLength(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render error when query has no results', () => {
|
|
||||||
wrapper.setProps({
|
|
||||||
addressBook: [],
|
|
||||||
domainError: 'bad',
|
|
||||||
contacts: [],
|
|
||||||
nonContacts: [],
|
|
||||||
});
|
|
||||||
|
|
||||||
const dialog = wrapper.find(Dialog);
|
|
||||||
|
|
||||||
expect(dialog.props().type).toStrictEqual('error');
|
|
||||||
expect(dialog.props().children).toStrictEqual('bad_t');
|
|
||||||
expect(dialog).toHaveLength(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render error when query has ens does not resolve', () => {
|
|
||||||
wrapper.setProps({
|
|
||||||
addressBook: [],
|
|
||||||
domainError: 'very bad',
|
|
||||||
contacts: [],
|
|
||||||
nonContacts: [],
|
|
||||||
});
|
|
||||||
|
|
||||||
const dialog = wrapper.find(Dialog);
|
|
||||||
|
|
||||||
expect(dialog.props().type).toStrictEqual('error');
|
|
||||||
expect(dialog.props().children).toStrictEqual('very bad_t');
|
|
||||||
expect(dialog).toHaveLength(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render error when ens resolved but ens error exists', () => {
|
|
||||||
wrapper.setProps({
|
|
||||||
addressBook: [],
|
|
||||||
domainError: 'bad',
|
|
||||||
domainResolution: '0x128',
|
|
||||||
});
|
|
||||||
|
|
||||||
const dialog = wrapper.find(Dialog);
|
|
||||||
|
|
||||||
expect(dialog).toHaveLength(1);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user