{
event.stopPropagation();
onCaretClick(aggId);
diff --git a/ui/pages/swaps/select-quote-popover/sort-list/sort-list.test.js b/ui/pages/swaps/select-quote-popover/sort-list/sort-list.test.js
index 51a53b3bf..1c82d7e59 100644
--- a/ui/pages/swaps/select-quote-popover/sort-list/sort-list.test.js
+++ b/ui/pages/swaps/select-quote-popover/sort-list/sort-list.test.js
@@ -1,6 +1,6 @@
import React from 'react';
-import { renderWithProvider } from '../../../../../test/jest';
+import { renderWithProvider, fireEvent } from '../../../../../test/jest';
import SortList from './sort-list';
jest.mock(
@@ -86,4 +86,32 @@ describe('SortList', () => {
document.querySelector('.select-quote-popover__row--selected'),
).toMatchSnapshot();
});
+
+ it('clicks on the "destinationTokenValue" header', () => {
+ const props = createProps();
+ const { getByTestId } = renderWithProvider();
+ fireEvent.click(getByTestId('select-quote-popover__receiving'));
+ expect(props.setSortColumn).toHaveBeenCalledWith('destinationTokenValue');
+ });
+
+ it('clicks on the "rawNetworkFees" header', () => {
+ const props = createProps();
+ const { getByTestId } = renderWithProvider();
+ fireEvent.click(getByTestId('select-quote-popover__network-fees-header'));
+ expect(props.setSortColumn).toHaveBeenCalledWith('rawNetworkFees');
+ });
+
+ it('clicks on the first aggregator', () => {
+ const props = createProps();
+ const { getByTestId } = renderWithProvider();
+ fireEvent.click(getByTestId('select-quote-popover-row-0'));
+ expect(props.onSelect).toHaveBeenCalledWith('Agg1');
+ });
+
+ it('clicks on a caret for the first aggregator', () => {
+ const props = createProps();
+ const { getByTestId } = renderWithProvider();
+ fireEvent.click(getByTestId('select-quote-popover__caret-right-0'));
+ expect(props.onCaretClick).toHaveBeenCalledWith('Agg1');
+ });
});
diff --git a/ui/pages/swaps/slippage-buttons/__snapshots__/slippage-buttons.test.js.snap b/ui/pages/swaps/slippage-buttons/__snapshots__/slippage-buttons.test.js.snap
index 3d363083b..198faf5e6 100644
--- a/ui/pages/swaps/slippage-buttons/__snapshots__/slippage-buttons.test.js.snap
+++ b/ui/pages/swaps/slippage-buttons/__snapshots__/slippage-buttons.test.js.snap
@@ -47,7 +47,7 @@ exports[`SlippageButtons renders the component with initial props 2`] = `
`;
-exports[`SlippageButtons renders the component with the smart transaction opt-in button available 1`] = `
+exports[`SlippageButtons renders the component with the smart transaction opt-in button available, opt into STX 1`] = `
`;
-exports[`SlippageButtons renders the component with the smart transaction opt-in button available 2`] = `
+exports[`SlippageButtons renders the component with the smart transaction opt-in button available, opt into STX 2`] = `
{
const { value } = event.target;
const isValueNumeric = !isNaN(Number(value));
diff --git a/ui/pages/swaps/slippage-buttons/slippage-buttons.test.js b/ui/pages/swaps/slippage-buttons/slippage-buttons.test.js
index 5d87e1297..d8ee9ff78 100644
--- a/ui/pages/swaps/slippage-buttons/slippage-buttons.test.js
+++ b/ui/pages/swaps/slippage-buttons/slippage-buttons.test.js
@@ -1,13 +1,14 @@
import React from 'react';
-import { renderWithProvider } from '../../../../test/jest';
+import { renderWithProvider, fireEvent } from '../../../../test/jest';
+import { SLIPPAGE } from '../../../../shared/constants/swaps';
import SlippageButtons from '.';
const createProps = (customProps = {}) => {
return {
onSelect: jest.fn(),
maxAllowedSlippage: 15,
- currentSlippage: 3,
+ currentSlippage: SLIPPAGE.HIGH,
smartTransactionsEnabled: false,
...customProps,
};
@@ -15,7 +16,7 @@ const createProps = (customProps = {}) => {
describe('SlippageButtons', () => {
it('renders the component with initial props', () => {
- const { getByText, queryByText } = renderWithProvider(
+ const { getByText, queryByText, getByTestId } = renderWithProvider(
,
);
expect(getByText('2%')).toBeInTheDocument();
@@ -29,11 +30,21 @@ describe('SlippageButtons', () => {
document.querySelector('.slippage-buttons__button-group'),
).toMatchSnapshot();
expect(queryByText('Smart transaction')).not.toBeInTheDocument();
+ expect(getByTestId('button-group__button1')).toHaveAttribute(
+ 'aria-checked',
+ 'true',
+ );
});
- it('renders the component with the smart transaction opt-in button available', () => {
+ it('renders the component with the smart transaction opt-in button available, opt into STX', () => {
+ const setSmartTransactionsOptInStatus = jest.fn();
const { getByText } = renderWithProvider(
-
,
+
,
);
expect(getByText('2%')).toBeInTheDocument();
expect(getByText('3%')).toBeInTheDocument();
@@ -46,5 +57,69 @@ describe('SlippageButtons', () => {
document.querySelector('.slippage-buttons__button-group'),
).toMatchSnapshot();
expect(getByText('Smart transaction')).toBeInTheDocument();
+ expect(document.querySelector('.toggle-button--off')).toBeInTheDocument();
+ fireEvent.click(document.querySelector('.toggle-button'));
+ expect(setSmartTransactionsOptInStatus).toHaveBeenCalledWith(true, false);
+ });
+
+ it('renders slippage with a custom value', () => {
+ const { getByText } = renderWithProvider(
+
,
+ );
+ expect(getByText('2.5')).toBeInTheDocument();
+ });
+
+ it('renders the default slippage with Advanced options hidden', () => {
+ const { getByText, queryByText } = renderWithProvider(
+
,
+ );
+ expect(getByText('Advanced options')).toBeInTheDocument();
+ expect(document.querySelector('.fa-angle-down')).toBeInTheDocument();
+ expect(queryByText('2%')).not.toBeInTheDocument();
+ });
+
+ it('opens the Advanced options section and sets a default slippage', () => {
+ const { getByText, getByTestId } = renderWithProvider(
+
,
+ );
+ fireEvent.click(getByText('Advanced options'));
+ fireEvent.click(getByTestId('button-group__button0'));
+ expect(getByTestId('button-group__button0')).toHaveAttribute(
+ 'aria-checked',
+ 'true',
+ );
+ });
+
+ it('opens the Advanced options section and sets a high slippage', () => {
+ const { getByText, getByTestId } = renderWithProvider(
+
,
+ );
+ fireEvent.click(getByText('Advanced options'));
+ fireEvent.click(getByTestId('button-group__button1'));
+ expect(getByTestId('button-group__button1')).toHaveAttribute(
+ 'aria-checked',
+ 'true',
+ );
+ });
+
+ it('sets a custom slippage value', () => {
+ const { getByTestId } = renderWithProvider(
+
,
+ );
+ fireEvent.click(getByTestId('button-group__button2'));
+ expect(getByTestId('button-group__button2')).toHaveAttribute(
+ 'aria-checked',
+ 'true',
+ );
+ const input = getByTestId('slippage-buttons__custom-slippage');
+ fireEvent.change(input, { target: { value: 5 } });
+ fireEvent.click(document);
+ expect(input).toHaveAttribute('value', '5');
});
});
diff --git a/ui/pages/swaps/smart-transaction-status/smart-transaction-status.test.js b/ui/pages/swaps/smart-transaction-status/smart-transaction-status.test.js
index 8c9a118c6..836344d7a 100644
--- a/ui/pages/swaps/smart-transaction-status/smart-transaction-status.test.js
+++ b/ui/pages/swaps/smart-transaction-status/smart-transaction-status.test.js
@@ -6,7 +6,9 @@ import {
renderWithProvider,
createSwapsMockStore,
setBackgroundConnection,
+ fireEvent,
} from '../../../../test/jest';
+import { CHAIN_IDS } from '../../../../shared/constants/network';
import SmartTransactionStatus from '.';
const middleware = [thunk];
@@ -15,6 +17,28 @@ setBackgroundConnection({
setBackgroundSwapRouteState: jest.fn(),
});
+jest.mock('react-router-dom', () => {
+ const original = jest.requireActual('react-router-dom');
+ return {
+ ...original,
+ useHistory: () => ({
+ push: jest.fn(),
+ }),
+ };
+});
+
+jest.mock('../../../ducks/swaps/swaps', () => {
+ const original = jest.requireActual('../../../ducks/swaps/swaps');
+ return {
+ ...original,
+ prepareToLeaveSwaps: jest.fn(() => {
+ return {
+ type: 'MOCK_TYPE',
+ };
+ }),
+ };
+});
+
describe('SmartTransactionStatus', () => {
it('renders the component with initial props', () => {
const store = configureMockStore(middleware)(createSwapsMockStore());
@@ -22,4 +46,109 @@ describe('SmartTransactionStatus', () => {
expect(getByText('Publicly submitting your Swap...')).toBeInTheDocument();
expect(getByText('Close')).toBeInTheDocument();
});
+
+ it('renders the "success" STX status', () => {
+ const mockStore = createSwapsMockStore();
+ const latestSmartTransaction =
+ mockStore.metamask.smartTransactionsState.smartTransactions[
+ CHAIN_IDS.MAINNET
+ ][1];
+ latestSmartTransaction.status = 'success';
+ const store = configureMockStore(middleware)(mockStore);
+ const { getByText } = renderWithProvider(
, store);
+ expect(getByText('Swap complete!')).toBeInTheDocument();
+ expect(getByText('Your USDC is now available.')).toBeInTheDocument();
+ expect(getByText('Create a new swap')).toBeInTheDocument();
+ expect(getByText('Close')).toBeInTheDocument();
+ });
+
+ it('renders the "reverted" STX status', () => {
+ const mockStore = createSwapsMockStore();
+ const latestSmartTransaction =
+ mockStore.metamask.smartTransactionsState.smartTransactions[
+ CHAIN_IDS.MAINNET
+ ][1];
+ latestSmartTransaction.status = 'reverted';
+ const store = configureMockStore(middleware)(mockStore);
+ const { getByText } = renderWithProvider(
, store);
+ expect(getByText('Swap failed')).toBeInTheDocument();
+ expect(getByText('customer support')).toBeInTheDocument();
+ expect(getByText('Close')).toBeInTheDocument();
+ });
+
+ it('renders the "cancelled_user_cancelled" STX status', () => {
+ const mockStore = createSwapsMockStore();
+ const latestSmartTransaction =
+ mockStore.metamask.smartTransactionsState.smartTransactions[
+ CHAIN_IDS.MAINNET
+ ][1];
+ latestSmartTransaction.status = 'cancelled_user_cancelled';
+ const store = configureMockStore(middleware)(mockStore);
+ const { getByText } = renderWithProvider(
, store);
+ expect(getByText('Swap cancelled')).toBeInTheDocument();
+ expect(
+ getByText(
+ 'Your transaction has been cancelled and you did not pay any unnecessary gas fees.',
+ ),
+ ).toBeInTheDocument();
+ expect(getByText('Close')).toBeInTheDocument();
+ });
+
+ it('renders the "deadline_missed" STX status', () => {
+ const mockStore = createSwapsMockStore();
+ const latestSmartTransaction =
+ mockStore.metamask.smartTransactionsState.smartTransactions[
+ CHAIN_IDS.MAINNET
+ ][1];
+ latestSmartTransaction.status = 'deadline_missed';
+ const store = configureMockStore(middleware)(mockStore);
+ const { getByText } = renderWithProvider(
, store);
+ expect(getByText('Swap would have failed')).toBeInTheDocument();
+ expect(
+ getByText(
+ 'Your transaction would have failed and was cancelled to protect you from paying unnecessary gas fees.',
+ ),
+ ).toBeInTheDocument();
+ expect(getByText('Close')).toBeInTheDocument();
+ });
+
+ it('renders the "unknown" STX status', () => {
+ const mockStore = createSwapsMockStore();
+ const latestSmartTransaction =
+ mockStore.metamask.smartTransactionsState.smartTransactions[
+ CHAIN_IDS.MAINNET
+ ][1];
+ latestSmartTransaction.status = 'unknown';
+ const store = configureMockStore(middleware)(mockStore);
+ const { getByText } = renderWithProvider(
, store);
+ expect(getByText('Status unknown')).toBeInTheDocument();
+ expect(
+ getByText(
+ 'A transaction has been successful but we’re unsure what it is. This may be due to submitting another transaction while this swap was processing.',
+ ),
+ ).toBeInTheDocument();
+ expect(getByText('Close')).toBeInTheDocument();
+ });
+
+ it('cancels a transaction', () => {
+ const store = configureMockStore(middleware)(createSwapsMockStore());
+ const { getByText } = renderWithProvider(
, store);
+ expect(getByText('Publicly submitting your Swap...')).toBeInTheDocument();
+ const cancelLink = getByText('Cancel swap for ~0');
+ expect(cancelLink).toBeInTheDocument();
+ fireEvent.click(cancelLink);
+ expect(
+ getByText('Trying to cancel your transaction...'),
+ ).toBeInTheDocument();
+ expect(cancelLink).not.toBeInTheDocument();
+ });
+
+ it('clicks on the Close button', () => {
+ const store = configureMockStore(middleware)(createSwapsMockStore());
+ const { getByText } = renderWithProvider(
, store);
+ expect(getByText('Publicly submitting your Swap...')).toBeInTheDocument();
+ const closeButton = getByText('Close');
+ expect(closeButton).toBeInTheDocument();
+ fireEvent.click(closeButton);
+ });
});
diff --git a/ui/pages/swaps/swaps-footer/swaps-footer.test.js b/ui/pages/swaps/swaps-footer/swaps-footer.test.js
index 1278f18fa..0b721da89 100644
--- a/ui/pages/swaps/swaps-footer/swaps-footer.test.js
+++ b/ui/pages/swaps/swaps-footer/swaps-footer.test.js
@@ -1,6 +1,6 @@
import React from 'react';
-import { renderWithProvider } from '../../../../test/jest';
+import { renderWithProvider, fireEvent } from '../../../../test/jest';
import SwapsFooter from '.';
const createProps = (customProps = {}) => {
@@ -25,4 +25,15 @@ describe('SwapsFooter', () => {
expect(getByText('Terms of service')).toBeInTheDocument();
expect(container).toMatchSnapshot();
});
+
+ it('clicks on a block explorer link', () => {
+ global.platform = { openTab: jest.fn() };
+ const props = createProps();
+ const { getByText } = renderWithProvider(
);
+ expect(getByText(props.submitText)).toBeInTheDocument();
+ fireEvent.click(getByText('Terms of service'));
+ expect(global.platform.openTab).toHaveBeenCalledWith({
+ url: 'https://metamask.io/terms.html',
+ });
+ });
});
diff --git a/ui/pages/swaps/swaps.util.test.js b/ui/pages/swaps/swaps.util.test.js
index e1e103874..7941f2e80 100644
--- a/ui/pages/swaps/swaps.util.test.js
+++ b/ui/pages/swaps/swaps.util.test.js
@@ -34,6 +34,8 @@ import {
getSwapsLivenessForNetwork,
countDecimals,
showRemainingTimeInMinAndSec,
+ getFeeForSmartTransaction,
+ formatSwapsValueForDisplay,
} from './swaps.util';
jest.mock('../../../shared/lib/storage-helpers', () => ({
@@ -534,6 +536,10 @@ describe('Swaps Util', () => {
shouldEnableDirectWrapping(CHAIN_IDS.MAINNET, WETH_CONTRACT_ADDRESS),
).toBe(false);
});
+
+ it('returns false if source and destination tokens are undefined', () => {
+ expect(shouldEnableDirectWrapping(CHAIN_IDS.MAINNET)).toBe(false);
+ });
});
describe('showRemainingTimeInMinAndSec', () => {
@@ -551,9 +557,48 @@ describe('Swaps Util', () => {
});
describe('getFeeForSmartTransaction', () => {
- it('returns estimated for for STX', () => {
- // TODO: Implement tests for this function.
- expect(true).toBe(true);
+ it('returns estimated fee for STX', () => {
+ const expected = {
+ feeInUsd: '0.02',
+ feeInFiat: '$0.02',
+ feeInEth: '0.00323 ETH',
+ rawEthFee: '0.00323',
+ };
+ const actual = getFeeForSmartTransaction({
+ chainId: CHAIN_IDS.MAINNET,
+ currentCurrency: 'usd',
+ conversionRate: 5,
+ USDConversionRate: 5,
+ nativeCurrencySymbol: 'ETH',
+ feeInWeiDec: 3225623412028924,
+ });
+ expect(actual).toMatchObject(expected);
+ });
+
+ it('returns estimated fee for STX for JPY currency', () => {
+ const expected = {
+ feeInUsd: '0.02',
+ feeInFiat: '£0.02',
+ feeInEth: '0.00323 ETH',
+ rawEthFee: '0.00323',
+ };
+ const actual = getFeeForSmartTransaction({
+ chainId: CHAIN_IDS.MAINNET,
+ currentCurrency: 'gbp',
+ conversionRate: 5,
+ USDConversionRate: 5,
+ nativeCurrencySymbol: 'ETH',
+ feeInWeiDec: 3225623412028924,
+ });
+ expect(actual).toMatchObject(expected);
+ });
+ });
+
+ describe('formatSwapsValueForDisplay', () => {
+ it('gets swaps value for display', () => {
+ expect(formatSwapsValueForDisplay('39.6493201125465000000')).toBe(
+ '39.6493201125',
+ );
});
});
diff --git a/ui/pages/swaps/view-on-block-explorer/view-on-block-explorer.test.js b/ui/pages/swaps/view-on-block-explorer/view-on-block-explorer.test.js
index e2917a68f..9112bc398 100644
--- a/ui/pages/swaps/view-on-block-explorer/view-on-block-explorer.test.js
+++ b/ui/pages/swaps/view-on-block-explorer/view-on-block-explorer.test.js
@@ -1,6 +1,6 @@
import React from 'react';
-import { renderWithProvider } from '../../../../test/jest';
+import { renderWithProvider, fireEvent } from '../../../../test/jest';
import ViewOnBlockExplorer from '.';
const createProps = (customProps = {}) => {
@@ -20,4 +20,17 @@ describe('ViewOnBlockExplorer', () => {
expect(getByText('View Swap at etherscan.io')).toBeInTheDocument();
expect(container).toMatchSnapshot();
});
+
+ it('clicks on the block explorer link', () => {
+ global.platform = { openTab: jest.fn() };
+ const { getByText } = renderWithProvider(
+
,
+ );
+ const link = getByText('View Swap at etherscan.io');
+ expect(link).toBeInTheDocument();
+ fireEvent.click(link);
+ expect(global.platform.openTab).toHaveBeenCalledWith({
+ url: 'https://etherscan.io',
+ });
+ });
});
diff --git a/ui/pages/swaps/view-quote/__snapshots__/view-quote.test.js.snap b/ui/pages/swaps/view-quote/__snapshots__/view-quote.test.js.snap
index c0c5a47b6..b317d3cbf 100644
--- a/ui/pages/swaps/view-quote/__snapshots__/view-quote.test.js.snap
+++ b/ui/pages/swaps/view-quote/__snapshots__/view-quote.test.js.snap
@@ -38,6 +38,7 @@ exports[`ViewQuote renders the component with EIP-1559 enabled 2`] = `
DAI
@@ -54,6 +55,7 @@ exports[`ViewQuote renders the component with EIP-1559 enabled 2`] = `