import nock from 'nock'; import configureMockStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import { MOCKS, createSwapsMockStore } from '../../../test/jest'; import { setSwapsLiveness, setSwapsFeatureFlags } from '../../store/actions'; import { CHAIN_IDS } from '../../../shared/constants/network'; import { setStorageItem } from '../../../shared/lib/storage-helpers'; import swapsReducer, * as swaps from './swaps'; const middleware = [thunk]; jest.mock('../../store/actions.ts', () => ({ setSwapsLiveness: jest.fn(), setSwapsFeatureFlags: jest.fn(), fetchSmartTransactionsLiveness: jest.fn(), getTransactions: jest.fn(() => { return []; }), })); const providerConfigState = { chainId: '0x1', nickname: '', rpcPrefs: {}, rpcUrl: '', ticker: 'ETH', type: 'mainnet', }; describe('Ducks - Swaps', () => { afterEach(() => { nock.cleanAll(); }); describe('fetchSwapsLivenessAndFeatureFlags', () => { const cleanFeatureFlagApiCache = () => { setStorageItem( 'cachedFetch:https://swap.metaswap.codefi.network/featureFlags', null, ); }; afterEach(() => { cleanFeatureFlagApiCache(); }); const mockFeatureFlagsApiResponse = ({ featureFlagsResponse, replyWithError = false, } = {}) => { const apiNock = nock('https://swap.metaswap.codefi.network').get( '/featureFlags', ); if (replyWithError) { return apiNock.replyWithError({ message: 'Server error. Try again later', code: 'serverSideError', }); } return apiNock.reply(200, featureFlagsResponse); }; const createGetState = () => { return () => ({ metamask: { providerConfig: { ...providerConfigState }, from: '0x64a845a5b02460acf8a3d84503b0d68d028b4bb4', }, }); }; it('checks that Swaps for ETH are enabled and can use new API', async () => { const mockDispatch = jest.fn(); const expectedSwapsLiveness = { swapsFeatureIsLive: true, }; const featureFlagsResponse = MOCKS.createFeatureFlagsResponse(); const featureFlagApiNock = mockFeatureFlagsApiResponse({ featureFlagsResponse, }); const swapsLiveness = await swaps.fetchSwapsLivenessAndFeatureFlags()( mockDispatch, createGetState(), ); expect(featureFlagApiNock.isDone()).toBe(true); expect(mockDispatch).toHaveBeenCalledTimes(4); expect(setSwapsLiveness).toHaveBeenCalledWith(expectedSwapsLiveness); expect(setSwapsFeatureFlags).toHaveBeenCalledWith(featureFlagsResponse); expect(swapsLiveness).toMatchObject(expectedSwapsLiveness); }); it('checks that Swaps for ETH are disabled for API v2 and enabled for API v1', async () => { const mockDispatch = jest.fn(); const expectedSwapsLiveness = { swapsFeatureIsLive: true, }; const featureFlagsResponse = MOCKS.createFeatureFlagsResponse(); featureFlagsResponse.ethereum.extensionActive = false; const featureFlagApiNock = mockFeatureFlagsApiResponse({ featureFlagsResponse, }); const swapsLiveness = await swaps.fetchSwapsLivenessAndFeatureFlags()( mockDispatch, createGetState(), ); expect(featureFlagApiNock.isDone()).toBe(true); expect(mockDispatch).toHaveBeenCalledTimes(4); expect(setSwapsLiveness).toHaveBeenCalledWith(expectedSwapsLiveness); expect(setSwapsFeatureFlags).toHaveBeenCalledWith(featureFlagsResponse); expect(swapsLiveness).toMatchObject(expectedSwapsLiveness); }); it('checks that Swaps for ETH are disabled for API v1 and v2', async () => { const mockDispatch = jest.fn(); const expectedSwapsLiveness = { swapsFeatureIsLive: false, }; const featureFlagsResponse = MOCKS.createFeatureFlagsResponse(); featureFlagsResponse.ethereum.extensionActive = false; featureFlagsResponse.ethereum.fallbackToV1 = false; const featureFlagApiNock = mockFeatureFlagsApiResponse({ featureFlagsResponse, }); const swapsLiveness = await swaps.fetchSwapsLivenessAndFeatureFlags()( mockDispatch, createGetState(), ); expect(featureFlagApiNock.isDone()).toBe(true); expect(mockDispatch).toHaveBeenCalledTimes(4); expect(setSwapsLiveness).toHaveBeenCalledWith(expectedSwapsLiveness); expect(setSwapsFeatureFlags).toHaveBeenCalledWith(featureFlagsResponse); expect(swapsLiveness).toMatchObject(expectedSwapsLiveness); }); it('checks that Swaps for ETH are disabled if the /featureFlags API call throws an error', async () => { const mockDispatch = jest.fn(); const expectedSwapsLiveness = { swapsFeatureIsLive: false, }; const featureFlagApiNock = mockFeatureFlagsApiResponse({ replyWithError: true, }); const swapsLiveness = await swaps.fetchSwapsLivenessAndFeatureFlags()( mockDispatch, createGetState(), ); expect(featureFlagApiNock.isDone()).toBe(true); expect(mockDispatch).toHaveBeenCalledTimes(2); expect(setSwapsLiveness).toHaveBeenCalledWith(expectedSwapsLiveness); expect(swapsLiveness).toMatchObject(expectedSwapsLiveness); }); it('only calls the API once and returns response from cache for the second call', async () => { const mockDispatch = jest.fn(); const expectedSwapsLiveness = { swapsFeatureIsLive: true, }; const featureFlagsResponse = MOCKS.createFeatureFlagsResponse(); const featureFlagApiNock = mockFeatureFlagsApiResponse({ featureFlagsResponse, }); await swaps.fetchSwapsLivenessAndFeatureFlags()( mockDispatch, createGetState(), ); expect(featureFlagApiNock.isDone()).toBe(true); const featureFlagApiNock2 = mockFeatureFlagsApiResponse({ featureFlagsResponse, }); const swapsLiveness = await swaps.fetchSwapsLivenessAndFeatureFlags()( mockDispatch, createGetState(), ); expect(featureFlagApiNock2.isDone()).toBe(false); // Second API call wasn't made, cache was used instead. expect(mockDispatch).toHaveBeenCalledTimes(8); expect(setSwapsLiveness).toHaveBeenCalledWith(expectedSwapsLiveness); expect(setSwapsFeatureFlags).toHaveBeenCalledWith(featureFlagsResponse); expect(swapsLiveness).toMatchObject(expectedSwapsLiveness); }); }); describe('getCustomMaxPriorityFeePerGas', () => { it('returns "customMaxPriorityFeePerGas"', () => { const state = createSwapsMockStore(); const customMaxPriorityFeePerGas = '3'; state.metamask.swapsState.customMaxPriorityFeePerGas = customMaxPriorityFeePerGas; expect(swaps.getCustomMaxPriorityFeePerGas(state)).toBe( customMaxPriorityFeePerGas, ); }); }); describe('getAggregatorMetadata', () => { it('returns agg metadata', () => { const state = createSwapsMockStore(); expect(swaps.getAggregatorMetadata(state)).toBe( state.swaps.aggregatorMetadata, ); }); }); describe('getBalanceError', () => { it('returns a balance error', () => { const state = createSwapsMockStore(); state.swaps.balanceError = 'balanceError'; expect(swaps.getBalanceError(state)).toBe(state.swaps.balanceError); }); }); describe('getFromToken', () => { it('returns fromToken', () => { const state = createSwapsMockStore(); expect(swaps.getFromToken(state)).toBe(state.swaps.fromToken); }); }); describe('getFromTokenError', () => { it('returns fromTokenError', () => { const state = createSwapsMockStore(); state.swaps.fromTokenError = 'fromTokenError'; expect(swaps.getFromTokenError(state)).toBe(state.swaps.fromTokenError); }); }); describe('getFromTokenInputValue', () => { it('returns fromTokenInputValue', () => { const state = createSwapsMockStore(); expect(swaps.getFromTokenInputValue(state)).toBe( state.swaps.fromTokenInputValue, ); }); }); describe('getIsFeatureFlagLoaded', () => { it('returns isFeatureFlagLoaded', () => { const state = createSwapsMockStore(); expect(swaps.getIsFeatureFlagLoaded(state)).toBe( state.swaps.isFeatureFlagLoaded, ); }); }); describe('getSwapsSTXLoading', () => { it('returns swapsSTXLoading', () => { const state = createSwapsMockStore(); expect(swaps.getSwapsSTXLoading(state)).toBe(state.swaps.swapsSTXLoading); }); }); describe('getMaxSlippage', () => { it('returns maxSlippage', () => { const state = createSwapsMockStore(); expect(swaps.getMaxSlippage(state)).toBe(state.swaps.maxSlippage); }); }); describe('getTopAssets', () => { it('returns topAssets', () => { const state = createSwapsMockStore(); expect(swaps.getTopAssets(state)).toBe(state.swaps.topAssets); }); }); describe('getToToken', () => { it('returns toToken', () => { const state = createSwapsMockStore(); expect(swaps.getToToken(state)).toBe(state.swaps.toToken); }); }); describe('getFetchingQuotes', () => { it('returns fetchingQuotes', () => { const state = createSwapsMockStore(); expect(swaps.getFetchingQuotes(state)).toBe(state.swaps.fetchingQuotes); }); }); describe('getQuotesFetchStartTime', () => { it('returns quotesFetchStartTime', () => { const state = createSwapsMockStore(); expect(swaps.getQuotesFetchStartTime(state)).toBe( state.swaps.quotesFetchStartTime, ); }); }); describe('getReviewSwapClickedTimestamp', () => { it('returns reviewSwapClickedTimestamp', () => { const state = createSwapsMockStore(); expect(swaps.getReviewSwapClickedTimestamp(state)).toBe( state.swaps.reviewSwapClickedTimestamp, ); }); }); describe('getSwapsCustomizationModalPrice', () => { it('returns customGas.price', () => { const state = createSwapsMockStore(); expect(swaps.getSwapsCustomizationModalPrice(state)).toBe( state.swaps.customGas.price, ); }); }); describe('getSwapsCustomizationModalLimit', () => { it('returns customGas.limit', () => { const state = createSwapsMockStore(); expect(swaps.getSwapsCustomizationModalLimit(state)).toBe( state.swaps.customGas.limit, ); }); }); describe('swapGasPriceEstimateIsLoading', () => { it('returns true for swapGasPriceEstimateIsLoading', () => { const state = createSwapsMockStore(); state.swaps.customGas.loading = swaps.GAS_PRICES_LOADING_STATES.LOADING; expect(swaps.swapGasPriceEstimateIsLoading(state)).toBe(true); }); }); describe('swapGasEstimateLoadingHasFailed', () => { it('returns true for swapGasEstimateLoadingHasFailed', () => { const state = createSwapsMockStore(); state.swaps.customGas.loading = swaps.GAS_PRICES_LOADING_STATES.INITIAL; expect(swaps.swapGasEstimateLoadingHasFailed(state)).toBe(true); }); }); describe('getSwapGasPriceEstimateData', () => { it('returns customGas.priceEstimates', () => { const state = createSwapsMockStore(); expect(swaps.getSwapGasPriceEstimateData(state)).toBe( state.swaps.customGas.priceEstimates, ); }); }); describe('getSwapsFallbackGasPrice', () => { it('returns customGas.fallBackPrice', () => { const state = createSwapsMockStore(); expect(swaps.getSwapsFallbackGasPrice(state)).toBe( state.swaps.customGas.fallBackPrice, ); }); }); describe('getCurrentSmartTransactionsError', () => { it('returns currentSmartTransactionsError', () => { const state = createSwapsMockStore(); state.swaps.currentSmartTransactionsError = 'currentSmartTransactionsError'; expect(swaps.getCurrentSmartTransactionsError(state)).toBe( state.swaps.currentSmartTransactionsError, ); }); }); describe('shouldShowCustomPriceTooLowWarning', () => { it('returns false for showCustomPriceTooLowWarning', () => { const state = createSwapsMockStore(); expect(swaps.shouldShowCustomPriceTooLowWarning(state)).toBe(false); }); }); describe('getSwapsFeatureIsLive', () => { it('returns true for "swapsFeatureIsLive"', () => { const state = createSwapsMockStore(); const swapsFeatureIsLive = true; state.metamask.swapsState.swapsFeatureIsLive = swapsFeatureIsLive; expect(swaps.getSwapsFeatureIsLive(state)).toBe(swapsFeatureIsLive); }); it('returns false for "swapsFeatureIsLive"', () => { const state = createSwapsMockStore(); const swapsFeatureIsLive = false; state.metamask.swapsState.swapsFeatureIsLive = swapsFeatureIsLive; expect(swaps.getSwapsFeatureIsLive(state)).toBe(swapsFeatureIsLive); }); }); describe('getSmartTransactionsError', () => { it('returns smartTransactionsError', () => { const state = createSwapsMockStore(); state.appState.smartTransactionsError = 'stxError'; expect(swaps.getSmartTransactionsError(state)).toBe( state.appState.smartTransactionsError, ); }); }); describe('getSmartTransactionsErrorMessageDismissed', () => { it('returns smartTransactionsErrorMessageDismissed', () => { const state = createSwapsMockStore(); state.appState.smartTransactionsErrorMessageDismissed = true; expect(swaps.getSmartTransactionsErrorMessageDismissed(state)).toBe( state.appState.smartTransactionsErrorMessageDismissed, ); }); }); describe('getSmartTransactionsEnabled', () => { it('returns true if feature flag is enabled, not a HW and is Ethereum network', () => { const state = createSwapsMockStore(); expect(swaps.getSmartTransactionsEnabled(state)).toBe(true); }); it('returns false if feature flag is disabled, not a HW and is Ethereum network', () => { const state = createSwapsMockStore(); state.metamask.swapsState.swapsFeatureFlags.smartTransactions.extensionActive = false; expect(swaps.getSmartTransactionsEnabled(state)).toBe(false); }); it('returns false if feature flag is enabled, not a HW, STX liveness is false and is Ethereum network', () => { const state = createSwapsMockStore(); state.metamask.smartTransactionsState.liveness = false; expect(swaps.getSmartTransactionsEnabled(state)).toBe(false); }); it('returns false if feature flag is enabled, is a HW and is Ethereum network', () => { const state = createSwapsMockStore(); state.metamask.keyrings[0].type = 'Trezor Hardware'; expect(swaps.getSmartTransactionsEnabled(state)).toBe(false); }); it('returns false if feature flag is enabled, not a HW and is Polygon network', () => { const state = createSwapsMockStore(); state.metamask.providerConfig.chainId = CHAIN_IDS.POLYGON; expect(swaps.getSmartTransactionsEnabled(state)).toBe(false); }); it('returns false if feature flag is enabled, not a HW and is BSC network', () => { const state = createSwapsMockStore(); state.metamask.providerConfig.chainId = CHAIN_IDS.BSC; expect(swaps.getSmartTransactionsEnabled(state)).toBe(false); }); it('returns true if feature flag is enabled, not a HW and is Goerli network', () => { const state = createSwapsMockStore(); state.metamask.providerConfig.chainId = CHAIN_IDS.GOERLI; expect(swaps.getSmartTransactionsEnabled(state)).toBe(true); }); it('returns false if feature flag is missing', () => { const state = createSwapsMockStore(); state.metamask.swapsState.swapsFeatureFlags = {}; expect(swaps.getSmartTransactionsEnabled(state)).toBe(false); }); }); describe('getCurrentSmartTransactionsEnabled', () => { it('returns true if STX are enabled and there is no current STX error', () => { const state = createSwapsMockStore(); expect(swaps.getCurrentSmartTransactionsEnabled(state)).toBe(true); }); it('returns false if STX are enabled and there is an current STX error', () => { const state = createSwapsMockStore(); state.swaps.currentSmartTransactionsError = 'currentSmartTransactionsError'; expect(swaps.getCurrentSmartTransactionsEnabled(state)).toBe(false); }); }); describe('getSwapsQuoteRefreshTime', () => { it('returns swapsQuoteRefreshTime', () => { const state = createSwapsMockStore(); expect(swaps.getSwapsQuoteRefreshTime(state)).toBe( state.metamask.swapsState.swapsQuoteRefreshTime, ); }); }); describe('getSwapsQuotePrefetchingRefreshTime', () => { it('returns swapsQuotePrefetchingRefreshTime', () => { const state = createSwapsMockStore(); expect(swaps.getSwapsQuotePrefetchingRefreshTime(state)).toBe( state.metamask.swapsState.swapsQuotePrefetchingRefreshTime, ); }); }); describe('getBackgroundSwapRouteState', () => { it('returns routeState', () => { const state = createSwapsMockStore(); expect(swaps.getBackgroundSwapRouteState(state)).toBe( state.metamask.swapsState.routeState, ); }); }); describe('getCustomSwapsGas', () => { it('returns "customMaxGas"', () => { const state = createSwapsMockStore(); const customMaxGas = '29000'; state.metamask.swapsState.customMaxGas = customMaxGas; expect(swaps.getCustomSwapsGas(state)).toBe(customMaxGas); }); }); describe('getCustomSwapsGasPrice', () => { it('returns customGasPrice', () => { const state = createSwapsMockStore(); expect(swaps.getCustomSwapsGasPrice(state)).toBe( state.metamask.swapsState.customGasPrice, ); }); }); describe('getCustomMaxFeePerGas', () => { it('returns "customMaxFeePerGas"', () => { const state = createSwapsMockStore(); const customMaxFeePerGas = '20'; state.metamask.swapsState.customMaxFeePerGas = customMaxFeePerGas; expect(swaps.getCustomMaxFeePerGas(state)).toBe(customMaxFeePerGas); }); }); describe('getSwapsUserFeeLevel', () => { it('returns swapsUserFeeLevel', () => { const state = createSwapsMockStore(); expect(swaps.getSwapsUserFeeLevel(state)).toBe( state.metamask.swapsState.swapsUserFeeLevel, ); }); }); describe('getFetchParams', () => { it('returns fetchParams', () => { const state = createSwapsMockStore(); expect(swaps.getFetchParams(state)).toBe( state.metamask.swapsState.fetchParams, ); }); }); describe('getQuotes', () => { it('returns quotes for Swaps', () => { const state = createSwapsMockStore(); expect(swaps.getQuotes(state)).toBe(state.metamask.swapsState.quotes); }); }); describe('getQuotesLastFetched', () => { it('returns quotesLastFetched', () => { const state = createSwapsMockStore(); expect(swaps.getQuotesLastFetched(state)).toBe( state.metamask.swapsState.quotesLastFetched, ); }); }); describe('getSelectedQuote', () => { it('returns selected quote', () => { const state = createSwapsMockStore(); expect(swaps.getSelectedQuote(state)).toBe( state.metamask.swapsState.quotes.TEST_AGG_2, ); }); }); describe('getSwapsErrorKey', () => { it('returns errorKey', () => { const state = createSwapsMockStore(); expect(swaps.getSwapsErrorKey(state)).toBe( state.metamask.swapsState.errorKey, ); }); }); describe('getShowQuoteLoadingScreen', () => { it('returns showQuoteLoadingScreen', () => { const state = createSwapsMockStore(); expect(swaps.getShowQuoteLoadingScreen(state)).toBe( state.swaps.showQuoteLoadingScreen, ); }); }); describe('getSwapsTokens', () => { it('returns tokens', () => { const state = createSwapsMockStore(); expect(swaps.getSwapsTokens(state)).toBe( state.metamask.swapsState.tokens, ); }); }); describe('getSwapsWelcomeMessageSeenStatus', () => { it('returns', () => { const state = createSwapsMockStore(); expect(swaps.getSwapsWelcomeMessageSeenStatus(state)).toBe( state.metamask.swapsState.swapsWelcomeMessageHasBeenShown, ); }); }); describe('getTopQuote', () => { it('returns a top quote', () => { const state = createSwapsMockStore(); expect(swaps.getTopQuote(state)).toBe( state.metamask.swapsState.quotes.TEST_AGG_BEST, ); }); }); describe('getApproveTxId', () => { it('returns approveTxId', () => { const state = createSwapsMockStore(); expect(swaps.getApproveTxId(state)).toBe( state.metamask.swapsState.approveTxId, ); }); }); describe('getTradeTxId', () => { it('returns tradeTxId', () => { const state = createSwapsMockStore(); expect(swaps.getTradeTxId(state)).toBe( state.metamask.swapsState.tradeTxId, ); }); }); describe('getUsedQuote', () => { it('returns selected quote', () => { const state = createSwapsMockStore(); expect(swaps.getUsedQuote(state)).toMatchObject( state.metamask.swapsState.quotes.TEST_AGG_2, ); }); it('returns best quote', () => { const state = createSwapsMockStore(); state.metamask.swapsState.selectedAggId = null; expect(swaps.getUsedQuote(state)).toMatchObject( state.metamask.swapsState.quotes.TEST_AGG_BEST, ); }); }); describe('getDestinationTokenInfo', () => { it('returns destinationTokenInfo', () => { const state = createSwapsMockStore(); expect(swaps.getDestinationTokenInfo(state)).toBe( state.metamask.swapsState.fetchParams.metaData.destinationTokenInfo, ); }); }); describe('getUsedSwapsGasPrice', () => { it('returns customGasPrice', () => { const state = createSwapsMockStore(); state.metamask.swapsState.customGasPrice = 5; expect(swaps.getUsedSwapsGasPrice(state)).toBe( state.metamask.swapsState.customGasPrice, ); }); }); describe('getApproveTxParams', () => { it('returns approveTxParams', () => { const state = createSwapsMockStore(); state.metamask.swapsState.quotes.TEST_AGG_2.approvalNeeded = { data: '0x095ea7b300000000000000000000000095e6f48254609a6ee006f7d493c8e5fb97094cef0000000000000000000000000000000000000000004a817c7ffffffdabf41c00', to: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', value: '0x0', from: '0x2369267687A84ac7B494daE2f1542C40E37f4455', gas: '0x12', gasPrice: '0x34', }; expect(swaps.getApproveTxParams(state)).toMatchObject({ ...state.metamask.swapsState.quotes.TEST_AGG_2.approvalNeeded, gasPrice: 5, }); }); }); describe('getSmartTransactionsOptInStatus', () => { it('returns STX opt in status', () => { const state = createSwapsMockStore(); expect(swaps.getSmartTransactionsOptInStatus(state)).toBe(true); }); }); describe('getCurrentSmartTransactions', () => { it('returns current smart transactions', () => { const state = createSwapsMockStore(); expect(swaps.getCurrentSmartTransactions(state)).toMatchObject( state.metamask.smartTransactionsState.smartTransactions[ CHAIN_IDS.MAINNET ], ); }); }); describe('getPendingSmartTransactions', () => { it('returns pending smart transactions', () => { const state = createSwapsMockStore(); const pendingSmartTransactions = swaps.getPendingSmartTransactions(state); expect(pendingSmartTransactions).toHaveLength(1); expect(pendingSmartTransactions[0].uuid).toBe('uuid2'); expect(pendingSmartTransactions[0].status).toBe('pending'); }); }); describe('getSmartTransactionFees', () => { it('returns unsigned transactions and estimates', () => { const state = createSwapsMockStore(); const smartTransactionFees = swaps.getSmartTransactionFees(state); expect(smartTransactionFees).toMatchObject( state.metamask.smartTransactionsState.fees, ); }); }); describe('getSmartTransactionEstimatedGas', () => { it('returns unsigned transactions and estimates', () => { const state = createSwapsMockStore(); const smartTransactionFees = swaps.getSmartTransactionEstimatedGas(state); expect(smartTransactionFees).toBe( state.metamask.smartTransactionsState.estimatedGas, ); }); }); describe('getSwapsNetworkConfig', () => { it('returns Swaps network config', () => { const state = createSwapsMockStore(); const { swapsQuoteRefreshTime, swapsQuotePrefetchingRefreshTime, swapsStxGetTransactionsRefreshTime, swapsStxBatchStatusRefreshTime, swapsStxStatusDeadline, swapsStxMaxFeeMultiplier, } = state.metamask.swapsState; const swapsNetworkConfig = swaps.getSwapsNetworkConfig(state); expect(swapsNetworkConfig).toMatchObject({ quoteRefreshTime: swapsQuoteRefreshTime, quotePrefetchingRefreshTime: swapsQuotePrefetchingRefreshTime, stxGetTransactionsRefreshTime: swapsStxGetTransactionsRefreshTime, stxBatchStatusRefreshTime: swapsStxBatchStatusRefreshTime, stxStatusDeadline: swapsStxStatusDeadline, stxMaxFeeMultiplier: swapsStxMaxFeeMultiplier, }); }); }); describe('actions + reducers', () => { const store = configureMockStore(middleware)(createSwapsMockStore()); afterEach(() => { store.clearActions(); }); describe('clearSwapsState', () => { it('calls the "swaps/clearSwapsState" action', () => { store.dispatch(swaps.clearSwapsState()); const actions = store.getActions(); expect(actions).toHaveLength(1); expect(actions[0].type).toBe('swaps/clearSwapsState'); }); }); describe('setAggregatorMetadata', () => { it('calls the "swaps/setAggregatorMetadata" action', () => { const state = store.getState().swaps; const actionPayload = { name: 'agg1', }; store.dispatch(swaps.setAggregatorMetadata(actionPayload)); const actions = store.getActions(); expect(actions[0].type).toBe('swaps/setAggregatorMetadata'); const newState = swapsReducer(state, actions[0]); expect(newState.aggregatorMetadata).toBe(actionPayload); }); }); describe('setBalanceError', () => { it('calls the "swaps/setBalanceError" action', () => { const state = store.getState().swaps; const actionPayload = 'balanceError'; store.dispatch(swaps.setBalanceError(actionPayload)); const actions = store.getActions(); expect(actions[0].type).toBe('swaps/setBalanceError'); const newState = swapsReducer(state, actions[0]); expect(newState.balanceError).toBe(actionPayload); }); }); describe('setFetchingQuotes', () => { it('calls the "swaps/setFetchingQuotes" action', () => { const state = store.getState().swaps; const actionPayload = true; store.dispatch(swaps.setFetchingQuotes(actionPayload)); const actions = store.getActions(); expect(actions[0].type).toBe('swaps/setFetchingQuotes'); const newState = swapsReducer(state, actions[0]); expect(newState.fetchingQuotes).toBe(actionPayload); }); }); describe('setSwapsFromToken', () => { it('calls the "swaps/setFromToken" action', () => { const state = store.getState().swaps; const actionPayload = 'ETH'; store.dispatch(swaps.setSwapsFromToken(actionPayload)); const actions = store.getActions(); expect(actions[0].type).toBe('swaps/setFromToken'); const newState = swapsReducer(state, actions[0]); expect(newState.fromToken).toBe(actionPayload); }); }); describe('setFromTokenError', () => { it('calls the "swaps/setFromTokenError" action', () => { const state = store.getState().swaps; const actionPayload = 'fromTokenError'; store.dispatch(swaps.setFromTokenError(actionPayload)); const actions = store.getActions(); expect(actions[0].type).toBe('swaps/setFromTokenError'); const newState = swapsReducer(state, actions[0]); expect(newState.fromTokenError).toBe(actionPayload); }); }); describe('setFromTokenInputValue', () => { it('calls the "swaps/setFromTokenInputValue" action', () => { const state = store.getState().swaps; const actionPayload = '5'; store.dispatch(swaps.setFromTokenInputValue(actionPayload)); const actions = store.getActions(); expect(actions[0].type).toBe('swaps/setFromTokenInputValue'); const newState = swapsReducer(state, actions[0]); expect(newState.fromTokenInputValue).toBe(actionPayload); }); }); describe('setIsFeatureFlagLoaded', () => { it('calls the "swaps/setIsFeatureFlagLoaded" action', () => { const state = store.getState().swaps; const actionPayload = true; store.dispatch(swaps.setIsFeatureFlagLoaded(actionPayload)); const actions = store.getActions(); expect(actions[0].type).toBe('swaps/setIsFeatureFlagLoaded'); const newState = swapsReducer(state, actions[0]); expect(newState.isFeatureFlagLoaded).toBe(actionPayload); }); }); describe('setMaxSlippage', () => { it('calls the "swaps/setMaxSlippage" action', () => { const state = store.getState().swaps; const actionPayload = 3; store.dispatch(swaps.setMaxSlippage(actionPayload)); const actions = store.getActions(); expect(actions[0].type).toBe('swaps/setMaxSlippage'); const newState = swapsReducer(state, actions[0]); expect(newState.maxSlippage).toBe(actionPayload); }); }); describe('setSwapQuotesFetchStartTime', () => { it('calls the "swaps/setQuotesFetchStartTime" action', () => { const state = store.getState().swaps; const actionPayload = '1664461886'; store.dispatch(swaps.setSwapQuotesFetchStartTime(actionPayload)); const actions = store.getActions(); expect(actions[0].type).toBe('swaps/setQuotesFetchStartTime'); const newState = swapsReducer(state, actions[0]); expect(newState.quotesFetchStartTime).toBe(actionPayload); }); }); describe('setReviewSwapClickedTimestamp', () => { it('calls the "swaps/setReviewSwapClickedTimestamp" action', () => { const state = store.getState().swaps; const actionPayload = '1664461886'; store.dispatch(swaps.setReviewSwapClickedTimestamp(actionPayload)); const actions = store.getActions(); expect(actions[0].type).toBe('swaps/setReviewSwapClickedTimestamp'); const newState = swapsReducer(state, actions[0]); expect(newState.reviewSwapClickedTimestamp).toBe(actionPayload); }); }); describe('setTopAssets', () => { it('calls the "swaps/setTopAssets" action', () => { const state = store.getState().swaps; const actionPayload = { '0x514910771af9ca656af840dff83e8264ecf986ca': { index: '0', }, '0x04fa0d235c4abf4bcf4787af4cf447de572ef828': { index: '1', }, '0x0bc529c00c6401aef6d220be8c6ea1667f6ad93e': { index: '2', }, }; store.dispatch(swaps.setTopAssets(actionPayload)); const actions = store.getActions(); expect(actions[0].type).toBe('swaps/setTopAssets'); const newState = swapsReducer(state, actions[0]); expect(newState.topAssets).toBe(actionPayload); }); }); describe('setSwapToToken', () => { it('calls the "swaps/setToToken" action', () => { const state = store.getState().swaps; const actionPayload = 'USDC'; store.dispatch(swaps.setSwapToToken(actionPayload)); const actions = store.getActions(); expect(actions[0].type).toBe('swaps/setToToken'); const newState = swapsReducer(state, actions[0]); expect(newState.toToken).toBe(actionPayload); }); }); describe('swapCustomGasModalPriceEdited', () => { it('calls the "swaps/swapCustomGasModalPriceEdited" action', () => { const state = store.getState().swaps; const actionPayload = 5; store.dispatch(swaps.swapCustomGasModalPriceEdited(actionPayload)); const actions = store.getActions(); expect(actions[0].type).toBe('swaps/swapCustomGasModalPriceEdited'); const newState = swapsReducer(state, actions[0]); expect(newState.customGas.price).toBe(actionPayload); }); }); describe('swapCustomGasModalLimitEdited', () => { it('calls the "swaps/swapCustomGasModalLimitEdited" action', () => { const state = store.getState().swaps; const actionPayload = 100; store.dispatch(swaps.swapCustomGasModalLimitEdited(actionPayload)); const actions = store.getActions(); expect(actions[0].type).toBe('swaps/swapCustomGasModalLimitEdited'); const newState = swapsReducer(state, actions[0]); expect(newState.customGas.limit).toBe(actionPayload); }); }); describe('swapCustomGasModalClosed', () => { it('calls the "swaps/swapCustomGasModalClosed" action', () => { const state = store.getState().swaps; store.dispatch(swaps.swapCustomGasModalClosed()); const actions = store.getActions(); expect(actions[0].type).toBe('swaps/swapCustomGasModalClosed'); const newState = swapsReducer(state, actions[0]); expect(newState.customGas.price).toBe(null); expect(newState.customGas.limit).toBe(null); }); }); describe('getSwapRedesignEnabled', () => { it('returns true if feature flags are not returned from backend yet', () => { const state = createSwapsMockStore(); delete state.metamask.swapsState.swapsFeatureFlags.swapRedesign; expect(swaps.getSwapRedesignEnabled(state)).toBe(true); }); it('returns false if the extension feature flag for swaps redesign is false', () => { const state = createSwapsMockStore(); state.metamask.swapsState.swapsFeatureFlags.swapRedesign.extensionActive = false; expect(swaps.getSwapRedesignEnabled(state)).toBe(false); }); it('returns true if the extension feature flag for swaps redesign is true', () => { const state = createSwapsMockStore(); expect(swaps.getSwapRedesignEnabled(state)).toBe(true); }); }); }); });