diff --git a/app/components/UI/Ramp/Views/NetworkSwitcher/NetworkSwitcher.test.tsx b/app/components/UI/Ramp/Views/NetworkSwitcher/NetworkSwitcher.test.tsx index f9921440bd4..5ae44ae8a59 100644 --- a/app/components/UI/Ramp/Views/NetworkSwitcher/NetworkSwitcher.test.tsx +++ b/app/components/UI/Ramp/Views/NetworkSwitcher/NetworkSwitcher.test.tsx @@ -181,6 +181,7 @@ const mockuseRampSDKInitialValues: Partial = { isBuy: true, isSell: false, rampType: RampType.BUY, + setIntent: jest.fn(), }; let mockUseRampSDKValues: Partial = { @@ -275,12 +276,12 @@ describe('NetworkSwitcher View', () => { expect(cancelButtons3.length).toBe(1); }); - it('switches network by calling setProviderType', async () => { + it('switches network by calling setActiveNetwork', async () => { render(NetworkSwitcher); const lineaNetworkText = screen.getByText('Linea Main Network'); fireEvent.press(lineaNetworkText); expect( - (Engine.context.NetworkController.setProviderType as jest.Mock).mock + (Engine.context.NetworkController.setActiveNetwork as jest.Mock).mock .calls, ).toMatchInlineSnapshot(` [ @@ -290,6 +291,7 @@ describe('NetworkSwitcher View', () => { ] `); + jest.clearAllMocks(); render(NetworkSwitcher); const polygonNetworkTest = screen.getByText('Polygon Mainnet'); fireEvent.press(polygonNetworkTest); diff --git a/app/components/UI/Ramp/Views/NetworkSwitcher/NetworkSwitcher.tsx b/app/components/UI/Ramp/Views/NetworkSwitcher/NetworkSwitcher.tsx index bd41a45d241..6dbf9289fb9 100644 --- a/app/components/UI/Ramp/Views/NetworkSwitcher/NetworkSwitcher.tsx +++ b/app/components/UI/Ramp/Views/NetworkSwitcher/NetworkSwitcher.tsx @@ -59,7 +59,7 @@ function NetworkSwitcher() { } = useRampNetworksDetail(); const supportedNetworks = useSelector(getRampNetworks); const [isCurrentNetworkRampSupported] = useRampNetwork(); - const { selectedChainId, isBuy, intent } = useRampSDK(); + const { selectedChainId, isBuy, intent, setIntent } = useRampSDK(); const networkConfigurations = useSelector(selectNetworkConfigurations); const [networkToBeAdded, setNetworkToBeAdded] = useState(); @@ -145,7 +145,7 @@ function NetworkSwitcher() { const switchToMainnet = useCallback( (type: 'mainnet' | 'linea-mainnet') => { const { NetworkController } = Engine.context; - NetworkController.setProviderType(type); + NetworkController.setActiveNetwork(type); navigateToGetStarted(); }, [navigateToGetStarted], @@ -173,13 +173,23 @@ function NetworkSwitcher() { const handleNetworkPress = useCallback( (networkConfiguration) => { + setIntent((prevIntent) => ({ + ...prevIntent, + chainId: networkConfiguration.chainId, + })); + + const networkConfigurationWithHexChainId = { + ...networkConfiguration, + chainId: toHex(networkConfiguration.chainId), + }; + if (networkConfiguration.isAdded) { - switchNetwork(networkConfiguration); + switchNetwork(networkConfigurationWithHexChainId); } else { - setNetworkToBeAdded(networkConfiguration); + setNetworkToBeAdded(networkConfigurationWithHexChainId); } }, - [switchNetwork], + [setIntent, switchNetwork], ); const handleIntentChainId = useCallback( @@ -199,7 +209,8 @@ function NetworkSwitcher() { (networkConfiguration) => { const isAdded = Object.values(networkConfigurations).some( (savedNetwork) => - savedNetwork.chainId === networkConfiguration.chainId, + toHex(savedNetwork.chainId) === + toHex(networkConfiguration.chainId), ); return { ...networkConfiguration, diff --git a/app/components/Views/ErrorBoundary/index.js b/app/components/Views/ErrorBoundary/index.js index a0c7af42270..603ebc4f312 100644 --- a/app/components/Views/ErrorBoundary/index.js +++ b/app/components/Views/ErrorBoundary/index.js @@ -40,7 +40,7 @@ import { } from '../../../components/hooks/useMetrics'; import AppConstants from '../../../core/AppConstants'; import { useSelector } from 'react-redux'; - +import { isTest } from '../../../util/test/utils'; // eslint-disable-next-line import/no-commonjs const WarningIcon = require('./warning-icon.png'); @@ -246,7 +246,6 @@ export const Fallback = (props) => { captureSentryFeedback({ sentryId: props.sentryId, comments: feedback }); Alert.alert(strings('error_screen.bug_report_thanks')); }; - return ( @@ -270,6 +269,14 @@ export const Fallback = (props) => { } /> + + {isTest && ( + + + {strings('error_screen.save_seedphrase_2')} + + + )} {strings('error_screen.error_message')} diff --git a/app/components/Views/Login/__snapshots__/index.test.tsx.snap b/app/components/Views/Login/__snapshots__/index.test.tsx.snap index 4beae542b9e..599cee47dee 100644 --- a/app/components/Views/Login/__snapshots__/index.test.tsx.snap +++ b/app/components/Views/Login/__snapshots__/index.test.tsx.snap @@ -186,6 +186,28 @@ exports[`Login should render correctly 1`] = ` + + + save your Secret Recovery Phrase + + - savedNetwork.chainId === networkConfiguration.chainId, + toHex(savedNetwork.chainId) === toHex(networkConfiguration.chainId), ); return { ...networkConfiguration, diff --git a/e2e/pages/Browser/TestDApp.js b/e2e/pages/Browser/TestDApp.js index 1a1f35cbf51..ec451f5dbe5 100644 --- a/e2e/pages/Browser/TestDApp.js +++ b/e2e/pages/Browser/TestDApp.js @@ -40,6 +40,12 @@ class TestDApp { TestDappSelectorsWebIDs.APPROVE_ERC_20_TOKENS_BUTTON_ID, ); } + get invalidSignature() { + return Matchers.getElementByWebID( + BrowserViewSelectorsIDs.BROWSER_WEBVIEW_ID, + 'signInvalidType', + ); + } get ApproveERC721TokenButton() { return Matchers.getElementByWebID( @@ -144,7 +150,9 @@ class TestDApp { async tapApproveERC721TokenButton() { await this.tapButton(this.ApproveERC721TokenButton); } - + async tapInvalidSigButton() { + await this.tapButton(this.invalidSignature); + } async tapIncreaseAllowanceButton() { await this.tapButton(this.increaseAllowanceButton); } diff --git a/e2e/pages/ErrorBoundaryView/ErrorBoundaryView.js b/e2e/pages/ErrorBoundaryView/ErrorBoundaryView.js new file mode 100644 index 00000000000..7368f183b15 --- /dev/null +++ b/e2e/pages/ErrorBoundaryView/ErrorBoundaryView.js @@ -0,0 +1,21 @@ +import Matchers from '../../utils/Matchers'; +import Gestures from '../../utils/Gestures'; +import { ErrorBoundarySelectorsText } from '../../selectors/ErrorBoundary/ErrorBoundaryView.selectors'; + +class ErrorBoundaryView { + get title() { + return Matchers.getElementByText(ErrorBoundarySelectorsText.TITLE); + } + + get srpLinkText() { + return Matchers.getElementByText( + ErrorBoundarySelectorsText.SAVE_YOUR_SRP_TEXT, + ); + } + + async tapSRPLinkText() { + await Gestures.waitAndTap(this.srpLinkText); + } +} + +export default new ErrorBoundaryView(); diff --git a/e2e/pages/Network/NetworkApprovalBottomSheet.js b/e2e/pages/Network/NetworkApprovalBottomSheet.js index be0402572d9..ce236d533a5 100644 --- a/e2e/pages/Network/NetworkApprovalBottomSheet.js +++ b/e2e/pages/Network/NetworkApprovalBottomSheet.js @@ -4,7 +4,9 @@ import Gestures from '../../utils/Gestures'; class NetworkApprovalBottomSheet { get container() { - return Matchers.getElementByID(NetworkApprovalBottomSheetSelectorsIDs.CONTAINER); + return Matchers.getElementByID( + NetworkApprovalBottomSheetSelectorsIDs.CONTAINER, + ); } get approvedButton() { @@ -12,6 +14,11 @@ class NetworkApprovalBottomSheet { NetworkApprovalBottomSheetSelectorsIDs.APPROVE_BUTTON, ); } + get cancelButton() { + return Matchers.getElementByID( + NetworkApprovalBottomSheetSelectorsIDs.CANCEL_BUTTON, + ); + } get displayName() { return Matchers.getElementByID( @@ -22,6 +29,9 @@ class NetworkApprovalBottomSheet { async tapApproveButton() { await Gestures.tap(this.approvedButton); } + async tapCancelButton() { + await Gestures.tap(this.cancelButton); + } } export default new NetworkApprovalBottomSheet(); diff --git a/e2e/selectors/ErrorBoundary/ErrorBoundaryView.selectors.js b/e2e/selectors/ErrorBoundary/ErrorBoundaryView.selectors.js new file mode 100644 index 00000000000..fdad2454ec5 --- /dev/null +++ b/e2e/selectors/ErrorBoundary/ErrorBoundaryView.selectors.js @@ -0,0 +1,9 @@ +import enContent from '../../../locales/languages/en.json'; + +export const ErrorBoundarySelectorsIDs = { + CONTAINER: 'error-boundary-container-id', +}; +export const ErrorBoundarySelectorsText = { + SAVE_YOUR_SRP_TEXT: enContent.error_screen.save_seedphrase_2, + TITLE: enContent.error_screen.title, +}; diff --git a/e2e/specs/accounts/error-boundary-srp-backup.spec.js b/e2e/specs/accounts/error-boundary-srp-backup.spec.js new file mode 100644 index 00000000000..667bd1b21a5 --- /dev/null +++ b/e2e/specs/accounts/error-boundary-srp-backup.spec.js @@ -0,0 +1,56 @@ +'use strict'; +import Browser from '../../pages/Browser/BrowserView'; +import TabBarComponent from '../../pages/wallet/TabBarComponent'; +import { loginToApp } from '../../viewHelper'; +import TestDApp from '../../pages/Browser/TestDApp'; +import FixtureBuilder from '../../fixtures/fixture-builder'; +import { + withFixtures, + defaultGanacheOptions, +} from '../../fixtures/fixture-helper'; +import { SmokeAccounts } from '../../tags'; +import TestHelpers from '../../helpers'; +import Assertions from '../../utils/Assertions'; +import RevealSecretRecoveryPhrase from '../../pages/Settings/SecurityAndPrivacy/RevealSecretRecoveryPhrase'; +import ErrorBoundaryView from '../../pages/ErrorBoundaryView/ErrorBoundaryView'; +const PASSWORD = '123123123'; + +describe(SmokeAccounts('Error Boundary Screen'), () => { + beforeAll(async () => { + jest.setTimeout(2500000); + await TestHelpers.reverseServerPort(); + }); + + it('should trigger error boundary screen to reveal SRP', async () => { + await withFixtures( + { + dapp: true, + fixture: new FixtureBuilder() + .withGanacheNetwork() + .withPermissionControllerConnectedToTestDapp() + .build(), + restartDevice: true, + ganacheOptions: defaultGanacheOptions, + }, + async () => { + await loginToApp(); + + await TabBarComponent.tapBrowser(); + await Browser.navigateToTestDApp(); + + await TestDApp.tapInvalidSigButton(); + await Assertions.checkIfVisible(ErrorBoundaryView.title); + await ErrorBoundaryView.tapSRPLinkText(); + + await RevealSecretRecoveryPhrase.enterPasswordToRevealSecretCredential( + PASSWORD, + ); + // If the following step fails, ensure you are using a test build with tap and hold to reveal animation disabled + await RevealSecretRecoveryPhrase.tapToReveal(); + await Assertions.checkIfVisible(RevealSecretRecoveryPhrase.container); + + await Assertions.checkIfTextIsDisplayed(defaultGanacheOptions.mnemonic); + }, + ); + }); +});