From 7b15964dad6d116116917392dcbe521a65de54b5 Mon Sep 17 00:00:00 2001 From: salimtb Date: Tue, 11 Jun 2024 18:39:53 +0200 Subject: [PATCH] feat: network verifecation messages --- app/_locales/en/messages.json | 22 ++ .../tests/network/custom-rpc-history.spec.js | 2 +- ui/helpers/utils/network-helper.test.ts | 55 +++- ui/helpers/utils/network-helper.ts | 16 + .../add-network-modal.test.js.snap | 8 +- .../add-network-modal.test.js | 28 +- .../networks-form/networks-form.js | 281 ++++++++++++++++-- .../networks-form/networks-form.test.js | 18 +- .../networks-tab-content.test.js | 12 +- .../networks-tab/networks-tab.test.js | 9 + 10 files changed, 420 insertions(+), 31 deletions(-) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 981aaa22ba34..62e4d5c929bd 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1737,6 +1737,12 @@ "etherscanViewOn": { "message": "View on Etherscan" }, + "existingChainId": { + "message": "You already have a network with the same Chain ID and RPC URL. Enter a new chain ID or RPC URL." + }, + "existingRpcUrl": { + "message": "This URL is associated with another chain ID" + }, "expandView": { "message": "Expand view" }, @@ -1791,6 +1797,10 @@ "message": "File import not working? Click here!", "description": "Helps user import their account from a JSON file" }, + "findTheRightChainId": { + "message": "Find the right one on:" + }, + "flaskWelcomeUninstall": { "message": "you should uninstall this extension", "description": "This request is shown on the Flask Welcome screen. It is intended for non-developers, and will be bolded." @@ -5135,6 +5145,9 @@ "submitted": { "message": "Submitted" }, + "suggestedTokenName": { + "message": "Suggested name:" + }, "suggestedTokenSymbol": { "message": "Suggested ticker symbol:" }, @@ -5970,6 +5983,9 @@ "message": "U2F", "description": "A name on an API for the browser to interact with devices that support the U2F protocol. On some browsers we use it to connect MetaMask to Ledger devices." }, + "unMatchedChain": { + "message": "According to our records, this URL does not match a known provider for this chain ID." + }, "unapproved": { "message": "Unapproved" }, @@ -6242,6 +6258,12 @@ "whatsThis": { "message": "What's this?" }, + "wrongChainId": { + "message": "This chain ID doesn’t match the network name." + }, + "wrongNetworkName": { + "message": "According to our records, the network name may not correctly match this chain ID." + }, "xOfYPending": { "message": "$1 of $2 pending", "description": "$1 and $2 are intended to be two numbers, where $2 is a total number of pending confirmations, and $1 is a count towards that total" diff --git a/test/e2e/tests/network/custom-rpc-history.spec.js b/test/e2e/tests/network/custom-rpc-history.spec.js index 7df8746a2e62..99601928efd2 100644 --- a/test/e2e/tests/network/custom-rpc-history.spec.js +++ b/test/e2e/tests/network/custom-rpc-history.spec.js @@ -143,7 +143,7 @@ describe('Custom RPC history', function () { await chainIdInput.clear(); await chainIdInput.sendKeys(duplicateChainId); await driver.findElement({ - text: 'This Chain ID is currently used by the mainnet network.', + text: 'You already have a network with the same Chain ID and RPC URL. Enter a new chain ID or RPC URL.', tag: 'h6', }); diff --git a/ui/helpers/utils/network-helper.test.ts b/ui/helpers/utils/network-helper.test.ts index fef6711dbd93..4cea6406b562 100644 --- a/ui/helpers/utils/network-helper.test.ts +++ b/ui/helpers/utils/network-helper.test.ts @@ -1,4 +1,8 @@ -import { getMatchedChain, getMatchedSymbols } from './network-helper'; +import { + getMatchedChain, + getMatchedNames, + getMatchedSymbols, +} from './network-helper'; describe('netwotkHelper', () => { describe('getMatchedChain', () => { @@ -76,4 +80,53 @@ describe('netwotkHelper', () => { expect(result).toEqual([]); }); }); + + describe('getMatchedName', () => { + it('should return an array of symbols that match the given decimalChainId', () => { + const chains = [ + { + chainId: '1', + name: 'test', + nativeCurrency: { symbol: 'ETH', name: 'Ethereum' }, + }, + { + chainId: '3', + name: 'test', + nativeCurrency: { symbol: 'tETH', name: 'tEthereum' }, + }, + { + chainId: '1', + name: 'test', + nativeCurrency: { symbol: 'WETH', name: 'WEthereum' }, + }, + ]; + const decimalChainId = '1'; + const expected = ['Ethereum', 'WEthereum']; + + const result = getMatchedNames(decimalChainId, chains); + + expect(result).toEqual(expect.arrayContaining(expected)); + expect(result.length).toBe(expected.length); + }); + + it('should return an empty array if no symbols match the given decimalChainId', () => { + const chains = [ + { + chainId: '1', + name: 'test', + nativeCurrency: { symbol: 'ETH', name: 'Ethereum' }, + }, + { + chainId: '3', + name: 'test', + nativeCurrency: { symbol: 'tETH', name: 'tEthereum' }, + }, + ]; + const decimalChainId = '2'; // No matching chainId + + const result = getMatchedNames(decimalChainId, chains); + + expect(result).toEqual([]); + }); + }); }); diff --git a/ui/helpers/utils/network-helper.ts b/ui/helpers/utils/network-helper.ts index 840dc8dfbf8a..3c96764cf1de 100644 --- a/ui/helpers/utils/network-helper.ts +++ b/ui/helpers/utils/network-helper.ts @@ -26,3 +26,19 @@ export const getMatchedSymbols = ( return accumulator; }, []); }; + +export const getMatchedNames = ( + decimalChainId: string, + safeChainsList: { + chainId: string; + name: string; + nativeCurrency: { symbol: string; name: string }; + }[], +): string[] => { + return safeChainsList.reduce((accumulator, currentNetwork) => { + if (currentNetwork.chainId.toString() === decimalChainId) { + accumulator.push(currentNetwork.nativeCurrency?.name); + } + return accumulator; + }, []); +}; diff --git a/ui/pages/onboarding-flow/add-network-modal/__snapshots__/add-network-modal.test.js.snap b/ui/pages/onboarding-flow/add-network-modal/__snapshots__/add-network-modal.test.js.snap index ace866477762..f42a9bd79292 100644 --- a/ui/pages/onboarding-flow/add-network-modal/__snapshots__/add-network-modal.test.js.snap +++ b/ui/pages/onboarding-flow/add-network-modal/__snapshots__/add-network-modal.test.js.snap @@ -67,6 +67,12 @@ exports[`Add Network Modal should render 1`] = ` + + Suggested name: +
@@ -240,5 +246,3 @@ exports[`Add Network Modal should render 1`] = `
`; - -exports[`Add Network Modal should render 2`] = `
`; diff --git a/ui/pages/onboarding-flow/add-network-modal/add-network-modal.test.js b/ui/pages/onboarding-flow/add-network-modal/add-network-modal.test.js index e0c31cb0bf78..e460dff2a1f4 100644 --- a/ui/pages/onboarding-flow/add-network-modal/add-network-modal.test.js +++ b/ui/pages/onboarding-flow/add-network-modal/add-network-modal.test.js @@ -11,6 +11,10 @@ jest.mock('../../../store/actions', () => ({ hideModal: () => mockHideModal, })); +jest.mock('../../../helpers/utils/feature-flags', () => ({ + getLocalNetworkMenuRedesignFeatureFlag: jest.fn(() => false), +})); + describe('Add Network Modal', () => { // Set the environment variable before tests run beforeEach(() => { @@ -23,7 +27,13 @@ describe('Add Network Modal', () => { }); it('should render', async () => { const mockStore = configureMockStore([])({ - metamask: { useSafeChainsListValidation: true }, + metamask: { + useSafeChainsListValidation: true, + orderedNetworkList: { + chainId: '0x1', + rpcUrl: 'http://test.com', + }, + }, }); const { container } = renderWithProvider( @@ -38,7 +48,13 @@ describe('Add Network Modal', () => { it('should handle callback', async () => { const mockStore = configureMockStore([thunk])({ - metamask: { useSafeChainsListValidation: true }, + metamask: { + useSafeChainsListValidation: true, + orderedNetworkList: { + chainId: '0x1', + rpcUrl: 'http://test.com', + }, + }, }); const { queryByText } = renderWithProvider( @@ -56,7 +72,13 @@ describe('Add Network Modal', () => { it('should not render the new network flow modal', async () => { const mockStore = configureMockStore([thunk])({ - metamask: { useSafeChainsListValidation: true }, + metamask: { + useSafeChainsListValidation: true, + orderedNetworkList: { + chainId: '0x1', + rpcUrl: 'http://test.com', + }, + }, }); const { queryByText } = renderWithProvider( diff --git a/ui/pages/settings/networks-tab/networks-form/networks-form.js b/ui/pages/settings/networks-tab/networks-form/networks-form.js index 07f629068dbb..8adda3fafd53 100644 --- a/ui/pages/settings/networks-tab/networks-form/networks-form.js +++ b/ui/pages/settings/networks-tab/networks-form/networks-form.js @@ -10,6 +10,8 @@ import React, { useState, } from 'react'; import { useDispatch, useSelector } from 'react-redux'; +import { ORIGIN_METAMASK } from '@metamask/approval-controller'; +import { ApprovalType } from '@metamask/controller-utils'; import { isWebUrl } from '../../../../../app/scripts/lib/util'; import { MetaMetricsEventCategory, @@ -18,6 +20,7 @@ import { } from '../../../../../shared/constants/metametrics'; import { BUILT_IN_NETWORKS, + CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP, CHAIN_IDS, CHAINLIST_CURRENCY_SYMBOLS_MAP_NETWORK_COLLISION, FEATURED_RPCS, @@ -37,9 +40,13 @@ import { MetaMetricsContext } from '../../../../contexts/metametrics'; import { getNetworkLabelKey } from '../../../../helpers/utils/i18n-helper'; import { useI18nContext } from '../../../../hooks/useI18nContext'; import { usePrevious } from '../../../../hooks/usePrevious'; -import { useSafeChainsListValidationSelector } from '../../../../selectors'; +import { + getOrderedNetworksList, + useSafeChainsListValidationSelector, +} from '../../../../selectors'; import { editAndSetNetworkConfiguration, + requestUserApproval, setNewNetworkAdded, setSelectedNetworkConfigurationId, showDeprecatedNetworkModal, @@ -54,6 +61,7 @@ import { ButtonPrimarySize, HelpText, HelpTextSeverity, + IconName, Text, } from '../../../../components/component-library'; import { FormTextField } from '../../../../components/component-library/form-text-field/deprecated'; @@ -68,8 +76,10 @@ import { } from '../../../../helpers/constants/design-system'; import { getMatchedChain, + getMatchedNames, getMatchedSymbols, } from '../../../../helpers/utils/network-helper'; +import { getLocalNetworkMenuRedesignFeatureFlag } from '../../../../helpers/utils/feature-flags'; /** * Attempts to convert the given chainId to a decimal string, for display @@ -117,6 +127,8 @@ const NetworksForm = ({ const t = useI18nContext(); const dispatch = useDispatch(); const DEFAULT_SUGGESTED_TICKER = []; + const DEFAULT_SUGGESTED_NAME = []; + const CHAIN_LIST_URL = 'https://chainid.network/'; const { label, labelKey, viewOnly, rpcPrefs } = selectedNetwork; const selectedNetworkName = label || (labelKey && t(getNetworkLabelKey(labelKey))); @@ -127,6 +139,7 @@ const NetworksForm = ({ const [suggestedTicker, setSuggestedTicker] = useState( DEFAULT_SUGGESTED_TICKER, ); + const [suggestedNames, setSuggestedNames] = useState(DEFAULT_SUGGESTED_NAME); const [blockExplorerUrl, setBlockExplorerUrl] = useState( selectedNetwork?.blockExplorerUrl || '', ); @@ -144,6 +157,11 @@ const NetworksForm = ({ const useSafeChainsListValidation = useSelector( useSafeChainsListValidationSelector, ); + const networkMenuRedesign = useSelector( + getLocalNetworkMenuRedesignFeatureFlag, + ); + const orderedNetworksList = useSelector(getOrderedNetworksList); + const safeChainsList = useRef([]); useEffect(() => { @@ -195,6 +213,7 @@ const NetworksForm = ({ setErrors({}); setWarnings({}); setSuggestedTicker([]); + setSuggestedNames([]); setIsSubmitting(false); setIsEditing(false); setPreviousNetwork(selectedNetwork); @@ -316,6 +335,32 @@ const NetworksForm = ({ setSuggestedTicker([...matchedSymbol]); }, []); + const autoSuggestName = useCallback((formChainId) => { + const decimalChainId = getDisplayChainId(formChainId); + if (decimalChainId.trim() === '' || safeChainsList.current.length === 0) { + setSuggestedNames([]); + return; + } + const matchedChain = safeChainsList.current?.find( + (chain) => chain.chainId.toString() === decimalChainId, + ); + + const matchedNames = safeChainsList.current?.reduce( + (accumulator, currentNetwork) => { + if (currentNetwork.chainId.toString() === decimalChainId) { + accumulator.push(currentNetwork.nativeCurrency?.name); + } + return accumulator; + }, + [], + ); + + if (matchedChain === undefined) { + setSuggestedNames([]); + return; + } + setSuggestedNames([...matchedNames]); + }, []); const hasErrors = () => { return Object.keys(errors).some((key) => { const error = errors[key]; @@ -358,6 +403,22 @@ const NetworksForm = ({ let radix = 10; let hexChainId = formChainId; + if ( + Object.values(orderedNetworksList).some( + (network) => + getDisplayChainId(chainArg) === + parseInt(network.networkId, 16).toString(10), + ) && + addNewNetwork + ) { + return { + error: { + key: 'existingChainId', + msg: t('existingChainId'), + }, + }; + } + if (!hexChainId.startsWith('0x')) { try { hexChainId = `0x${decimalToHex(hexChainId)}`; @@ -402,20 +463,15 @@ const NetworksForm = ({ } let endpointChainId; - let providerError; try { endpointChainId = await jsonRpcRequest(rpcUrl, 'eth_chainId'); } catch (err) { log.warn('Failed to fetch the chainId from the endpoint.', err); - providerError = err; } if (rpcUrl && formChainId) { - if (providerError || typeof endpointChainId !== 'string') { - errorKey = 'failedToFetchChainId'; - errorMessage = t('failedToFetchChainId'); - } else if (hexChainId !== endpointChainId) { + if (hexChainId !== endpointChainId) { // Here, we are in an error state. The endpoint should always return a // hexadecimal string. If the user entered a decimal string, we attempt // to convert the endpoint's return value to decimal before rendering it @@ -432,11 +488,6 @@ const NetworksForm = ({ } errorKey = 'endpointReturnedDifferentChainId'; - errorMessage = t('endpointReturnedDifferentChainId', [ - endpointChainId.length <= 12 - ? endpointChainId - : `${endpointChainId.slice(0, 9)}...`, - ]); } } if (errorKey) { @@ -456,9 +507,17 @@ const NetworksForm = ({ }; } autoSuggestTicker(formChainId); + autoSuggestName(formChainId); return null; }, - [rpcUrl, networksToRender, t], + [ + rpcUrl, + networksToRender, + t, + autoSuggestTicker, + orderedNetworksList, + autoSuggestName, + ], ); /** @@ -518,8 +577,61 @@ const NetworksForm = ({ [t], ); + const validateNetworkName = useCallback( + async (formChainId, formName) => { + let warningKey; + let warningMessage; + const decimalChainId = getDisplayChainId(formChainId); + + if (!decimalChainId || !formName) { + setSuggestedNames([]); + return null; + } + + if (safeChainsList.current.length === 0) { + warningKey = 'failedToFetchTickerSymbolData'; + warningMessage = t('failedToFetchTickerSymbolData'); + } else { + const matchedChain = getMatchedChain( + decimalChainId, + safeChainsList.current, + ); + + const matchedNames = getMatchedNames( + decimalChainId, + safeChainsList.current, + ); + setSuggestedNames([...matchedNames]); + + if (matchedChain === undefined) { + warningKey = 'failedToFetchTickerSymbolData'; + warningMessage = t('failedToFetchTickerSymbolData'); + } else if ( + !matchedNames.some( + (name) => name.toLowerCase() === formName.toLowerCase(), + ) + ) { + warningKey = 'wrongNetworkName'; + warningMessage = t('wrongNetworkName'); + } + } + + if (warningKey) { + return { + key: warningKey, + msg: warningMessage, + }; + } + + return null; + }, + [t], + ); + const validateRPCUrl = useCallback( - (url) => { + async (url, formChainId) => { + const decimalChainId = getDisplayChainId(formChainId); + const [ { rpcUrl: matchingRPCUrl = null, @@ -529,6 +641,22 @@ const NetworksForm = ({ ] = networksToRender.filter((e) => e.rpcUrl === url); const { rpcUrl: selectedNetworkRpcUrl } = selectedNetwork; + if ( + Object.values(orderedNetworksList).some( + (network) => url === network.networkRpcUrl, + ) && + addNewNetwork + ) { + return { + key: 'existingRpcUrl', + msg: t('existingRpcUrl'), + }; + } + + if (!url || !decimalChainId) { + return null; + } + if (url?.length > 0 && !isWebUrl(url)) { if (isWebUrl(`https://${url}`)) { return { @@ -548,15 +676,40 @@ const NetworksForm = ({ ]), }; } + + let endpointChainId; + let providerError; + + try { + endpointChainId = await jsonRpcRequest(rpcUrl, 'eth_chainId'); + } catch (err) { + log.warn('Failed to fetch the chainId from the endpoint.', err); + providerError = err; + } + + if (providerError || typeof endpointChainId !== 'string') { + return { + key: 'failedToFetchChainId', + msg: t('unMatchedChain'), + }; + } return null; }, - [selectedNetwork, networksToRender, t], + [ + selectedNetwork, + networksToRender, + t, + orderedNetworksList, + rpcUrl, + addNewNetwork, + ], ); // validation effect const previousRpcUrl = usePrevious(rpcUrl); const previousChainId = usePrevious(chainId); const previousTicker = usePrevious(ticker); + const previousName = usePrevious(networkName); const previousBlockExplorerUrl = usePrevious(blockExplorerUrl); useEffect(() => { if (viewOnly) { @@ -567,6 +720,7 @@ const NetworksForm = ({ previousRpcUrl === rpcUrl && previousChainId === chainId && previousTicker === ticker && + previousName === networkName && previousBlockExplorerUrl === blockExplorerUrl ) { return; @@ -575,8 +729,9 @@ const NetworksForm = ({ const { error: chainIdError, warning: chainIdWarning } = (await validateChainId(chainId)) || {}; const tickerWarning = await validateTickerSymbol(chainId, ticker); + const nameWarning = await validateNetworkName(chainId, networkName); const blockExplorerError = validateBlockExplorerURL(blockExplorerUrl); - const rpcUrlError = validateRPCUrl(rpcUrl); + const rpcUrlError = await validateRPCUrl(rpcUrl, chainId); setErrors({ ...errors, blockExplorerUrl: blockExplorerError, @@ -587,6 +742,7 @@ const NetworksForm = ({ ...warnings, chainId: chainIdWarning, ticker: tickerWarning, + networkName: nameWarning, }); } @@ -597,21 +753,48 @@ const NetworksForm = ({ rpcUrl, chainId, ticker, + networkName, blockExplorerUrl, viewOnly, label, previousRpcUrl, previousChainId, previousTicker, + previousName, previousBlockExplorerUrl, validateBlockExplorerURL, validateChainId, validateTickerSymbol, validateRPCUrl, + validateNetworkName, ]); const onSubmit = async () => { setIsSubmitting(true); + if (networkMenuRedesign) { + dispatch(toggleNetworkMenu()); + await dispatch( + requestUserApproval({ + origin: ORIGIN_METAMASK, + type: ApprovalType.AddEthereumChain, + requestData: { + chainId: prefixChainId(chainId), + rpcUrl, + ticker, + imageUrl: + CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP[prefixChainId(chainId)] ?? '', + chainName: networkName, + rpcPrefs: { + ...rpcPrefs, + blockExplorerUrl: blockExplorerUrl || rpcPrefs?.blockExplorerUrl, + }, + referrer: ORIGIN_METAMASK, + source: MetaMetricsNetworkEventSource.NewAddNetworkFlow, + }, + }), + ); + return; + } try { const formChainId = chainId.trim().toLowerCase(); const prefixedChainId = prefixChainId(formChainId); @@ -769,6 +952,45 @@ const NetworksForm = ({ disabled={viewOnly} dataTestId="network-form-network-name" /> + {warnings.networkName?.msg ? ( + + {warnings.networkName?.msg} + + ) : null} + {suggestedNames && + !suggestedNames.some( + (nameSuggested) => nameSuggested === networkName, + ) ? ( + + {t('suggestedTokenName')} + {suggestedNames.map((suggestedName, i) => ( + { + setNetworkName(suggestedName); + }} + paddingLeft={1} + paddingRight={1} + style={{ verticalAlign: 'baseline' }} + key={i} + > + {suggestedName} + + ))} + + ) : null} { @@ -794,6 +1016,27 @@ const NetworksForm = ({ tooltipText={viewOnly ? null : t('networkSettingsChainIdDescription')} dataTestId="network-form-chain-id" /> + {errors.chainId?.key === 'endpointReturnedDifferentChainId' ? ( + + + {t('wrongChainId')} + + + {t('findTheRightChainId')}{' '} + ({})} + href={CHAIN_LIST_URL} + endIconName={IconName.Export} + > + chainid.network + + + + ) : null} + { onSubmit(); - dispatch(toggleNetworkMenu()); + if (!networkMenuRedesign) { + dispatch(toggleNetworkMenu()); + } }} size={ButtonPrimarySize.Lg} width={BlockSize.Full} alignItems={AlignItems.center} > - {t('save')} + {networkMenuRedesign ? t('next') : t('save')} ) : ( diff --git a/ui/pages/settings/networks-tab/networks-form/networks-form.test.js b/ui/pages/settings/networks-tab/networks-form/networks-form.test.js index a491dee64184..aa7f35dce70c 100644 --- a/ui/pages/settings/networks-tab/networks-form/networks-form.test.js +++ b/ui/pages/settings/networks-tab/networks-form/networks-form.test.js @@ -13,11 +13,21 @@ import NetworksForm from '.'; const renderComponent = (props) => { const store = configureMockStore([])({ - metamask: { useSafeChainsListValidation: true }, + metamask: { + useSafeChainsListValidation: true, + orderedNetworkList: { + networkId: '0x1', + networkRpcUrl: 'https://mainnet.infura.io/v3/', + }, + }, }); return renderWithProvider(, store); }; +jest.mock('../../../../helpers/utils/feature-flags', () => ({ + getLocalNetworkMenuRedesignFeatureFlag: jest.fn(() => false), +})); + const defaultNetworks = defaultNetworksData.map((network) => ({ ...network, viewOnly: true, @@ -168,6 +178,9 @@ describe('NetworkForm Component', () => { await fireEvent.change(rpcUrlField, { target: { value: 'test' }, }); + await fireEvent.change(screen.getByRole('textbox', { name: 'Chain ID' }), { + target: { value: '1' }, + }); expect( await screen.findByText( 'URLs require the appropriate HTTP/HTTPS prefix.', @@ -243,8 +256,7 @@ describe('NetworkForm Component', () => { target: { value: 'https://bsc-dataseed.binance.org/' }, }); - const expectedWarning = - 'The RPC URL you have entered returned a different chain ID (56). Please update the Chain ID to match the RPC URL of the network you are trying to add.'; + const expectedWarning = 'This chain ID doesn’t match the network name.'; expect(await screen.findByText(expectedWarning)).toBeInTheDocument(); expect(screen.getByText('Save')).toBeDisabled(); diff --git a/ui/pages/settings/networks-tab/networks-tab-content/networks-tab-content.test.js b/ui/pages/settings/networks-tab/networks-tab-content/networks-tab-content.test.js index 17c87e63262d..c9a764e53358 100644 --- a/ui/pages/settings/networks-tab/networks-tab-content/networks-tab-content.test.js +++ b/ui/pages/settings/networks-tab/networks-tab-content/networks-tab-content.test.js @@ -15,9 +15,17 @@ const mockState = { ticker: 'ETH', type: 'localhost', }, + orderedNetworkList: { + chainId: '0x539', + rpcUrl: 'http://localhost:8545', + }, }, }; +jest.mock('../../../../helpers/utils/feature-flags', () => ({ + getLocalNetworkMenuRedesignFeatureFlag: jest.fn(() => false), +})); + const renderComponent = (props) => { const store = configureMockStore([])(mockState); return renderWithProvider(, store); @@ -89,9 +97,7 @@ describe('NetworksTabContent Component', () => { }); expect( - await screen.findByText( - 'Could not fetch chain ID. Is your RPC URL correct?', - ), + await screen.findByText('This chain ID doesn’t match the network name.'), ).toBeInTheDocument(); }); }); diff --git a/ui/pages/settings/networks-tab/networks-tab.test.js b/ui/pages/settings/networks-tab/networks-tab.test.js index fe985de9ebe4..f86ff26832bb 100644 --- a/ui/pages/settings/networks-tab/networks-tab.test.js +++ b/ui/pages/settings/networks-tab/networks-tab.test.js @@ -3,6 +3,10 @@ import configureMockStore from 'redux-mock-store'; import { renderWithProvider } from '../../../../test/jest/rendering'; import NetworksTab from '.'; +jest.mock('../../../helpers/utils/feature-flags', () => ({ + getLocalNetworkMenuRedesignFeatureFlag: jest.fn(() => false), +})); + const mockState = { metamask: { providerConfig: { @@ -14,7 +18,12 @@ const mockState = { type: 'localhost', }, networkConfigurations: {}, + orderedNetworkList: { + chainId: '0x539', + rpcUrl: 'http://localhost:8545', + }, }, + appState: { networksTabSelectedRpcUrl: 'http://localhost:8545', },