diff --git a/app/components/UI/LoginOptionsSwitch/LoginOptionsSwitch.tsx b/app/components/UI/LoginOptionsSwitch/LoginOptionsSwitch.tsx index b7b0c218048..7994da523e7 100644 --- a/app/components/UI/LoginOptionsSwitch/LoginOptionsSwitch.tsx +++ b/app/components/UI/LoginOptionsSwitch/LoginOptionsSwitch.tsx @@ -51,7 +51,7 @@ const LoginOptionsSwitch = ({ // if both are disabled then this component returns null if (shouldRenderBiometricOption !== null) { return ( - + {strings( `biometrics.enable_${shouldRenderBiometricOption.toLowerCase()}`, @@ -67,12 +67,13 @@ const LoginOptionsSwitch = ({ }} thumbColor={colors.white} ios_backgroundColor={colors.border.muted} + testID={LOGIN_WITH_BIOMETRICS_SWITCH} /> ); } else if (shouldRenderBiometricOption === null && allowLoginWithRememberMe) { return ( - + {strings(`choose_password.remember_me`)} @@ -86,6 +87,7 @@ const LoginOptionsSwitch = ({ }} thumbColor={colors.white} ios_backgroundColor={colors.border.muted} + testID={LOGIN_WITH_REMEMBER_ME_SWITCH} /> ); diff --git a/app/components/UI/SecurityOptionToggle/SecurityOptionToggle.tsx b/app/components/UI/SecurityOptionToggle/SecurityOptionToggle.tsx index dde3483d93b..dd1805a67eb 100644 --- a/app/components/UI/SecurityOptionToggle/SecurityOptionToggle.tsx +++ b/app/components/UI/SecurityOptionToggle/SecurityOptionToggle.tsx @@ -35,11 +35,12 @@ const SecurityOptionToggle = ({ [onOptionUpdated], ); return ( - + {title} {description ? {description} : null} handleOnValueChange(newValue)} trackColor={{ diff --git a/app/components/Views/Settings/SecuritySettings/Sections/RememberMeOptionSection.tsx b/app/components/Views/Settings/SecuritySettings/Sections/RememberMeOptionSection.tsx index d6b78398027..c502905e166 100644 --- a/app/components/Views/Settings/SecuritySettings/Sections/RememberMeOptionSection.tsx +++ b/app/components/Views/Settings/SecuritySettings/Sections/RememberMeOptionSection.tsx @@ -7,6 +7,8 @@ import { setAllowLoginWithRememberMe } from '../../../../../actions/security'; import { useNavigation } from '@react-navigation/native'; import { createTurnOffRememberMeModalNavDetails } from '../../../..//UI/TurnOffRememberMeModal/TurnOffRememberMeModal'; +import { REMEMBER_ME_TOGGLE_ON_SETTINGS_AND_PRIVACY } from '../../../../../constants/test-ids'; + const RememberMeOptionSection = () => { const { navigate } = useNavigation(); const allowLoginWithRememberMe = useSelector( @@ -46,6 +48,7 @@ const RememberMeOptionSection = () => { description={strings(`remember_me.enable_remember_me_description`)} value={allowLoginWithRememberMe} onOptionUpdated={(value) => onValueChanged(value)} + testId={REMEMBER_ME_TOGGLE_ON_SETTINGS_AND_PRIVACY} /> ); }; diff --git a/app/constants/test-ids.js b/app/constants/test-ids.js index c84f0b8ad41..e07bad2b627 100644 --- a/app/constants/test-ids.js +++ b/app/constants/test-ids.js @@ -86,3 +86,4 @@ export const STACKED_AVATARS_OVERFLOW_COUNTER = export const LOGIN_WITH_BIOMETRICS_SWITCH = 'login-with-biometrics-switch'; export const LOGIN_WITH_REMEMBER_ME_SWITCH = 'login-with-remember-me-switch'; export const TURN_OFF_REMEMBER_ME_MODAL = 'TurnOffRememberMeConfirm'; +export const REMEMBER_ME_TOGGLE_ON_SETTINGS_AND_PRIVACY = 'turn-on-remember-me'; diff --git a/e2e/pages/Drawer/Settings/SecurityAndPrivacy/SecurityAndPrivacyView.js b/e2e/pages/Drawer/Settings/SecurityAndPrivacy/SecurityAndPrivacyView.js index 042fed9538e..ab61add20b7 100644 --- a/e2e/pages/Drawer/Settings/SecurityAndPrivacy/SecurityAndPrivacyView.js +++ b/e2e/pages/Drawer/Settings/SecurityAndPrivacy/SecurityAndPrivacyView.js @@ -4,6 +4,7 @@ import { CHANGE_PASSWORD_BUTTON_ID, CHANGE_PASSWORD_TITLE_ID, BACK_ARROW_BUTTON_ID, + REMEMBER_ME_TOGGLE_ON_SETTINGS_AND_PRIVACY, } from '../../../../../app/constants/test-ids'; const SECURITY_SETTINGS_SCROLL_ID = 'security-settings-scrollview'; @@ -38,7 +39,18 @@ export default class SecurityAndPrivacy { await TestHelpers.swipe(SECURITY_SETTINGS_SCROLL_ID, 'up', 'fast'); await TestHelpers.delay(1000); } else { - await TestHelpers.swipe(CHANGE_PASSWORD_TITLE_ID, 'up', 'fast', 0.8); + await TestHelpers.swipe(CHANGE_PASSWORD_TITLE_ID, 'up', 'fast', 0.9); + } + //await TestHelpers.swipe(PRIVACY_MODE_SECTION_ID, 'up', 'fast'); + } + + static async scrollToTurnOnRememberMe() { + // Scroll to the bottom + if (device.getPlatform() === 'android') { + await TestHelpers.swipe(SECURITY_SETTINGS_SCROLL_ID, 'up', 'slow'); + await TestHelpers.delay(1000); + } else { + await TestHelpers.swipe(CHANGE_PASSWORD_TITLE_ID, 'up', 'slow', 0.6); } //await TestHelpers.swipe(PRIVACY_MODE_SECTION_ID, 'up', 'fast'); } @@ -51,6 +63,10 @@ export default class SecurityAndPrivacy { await TestHelpers.tap(METAMETRICS_SWITCH_ID); } + static async tapTurnOnRememberMeToggle() { + await TestHelpers.tap(REMEMBER_ME_TOGGLE_ON_SETTINGS_AND_PRIVACY); + } + static async isMetaMetricsToggleOn() { await TestHelpers.checkIfToggleIsOn(METAMETRICS_SWITCH_ID); } @@ -59,6 +75,17 @@ export default class SecurityAndPrivacy { await TestHelpers.checkIfToggleIsOff(METAMETRICS_SWITCH_ID); } + static async isRememberMeToggleOn() { + await TestHelpers.checkIfToggleIsOn( + REMEMBER_ME_TOGGLE_ON_SETTINGS_AND_PRIVACY, + ); + } + + static async isRememberMeToggleOff() { + await TestHelpers.checkIfToggleIsOff( + REMEMBER_ME_TOGGLE_ON_SETTINGS_AND_PRIVACY, + ); + } static async isChangePasswordSectionVisible() { await TestHelpers.checkIfVisible(CHANGE_PASSWORD_TITLE_ID); } diff --git a/e2e/pages/LoginView.js b/e2e/pages/LoginView.js index 03f639ec8b7..43e2e0d06c0 100644 --- a/e2e/pages/LoginView.js +++ b/e2e/pages/LoginView.js @@ -4,6 +4,7 @@ import { RESET_WALLET_ID, LOGIN_CONTAINER_ID, LOGIN_PASSWORD_ERROR, + LOGIN_WITH_REMEMBER_ME_SWITCH, } from '../../app/constants/test-ids'; export default class LoginView { static async enterPassword(password) { @@ -12,6 +13,9 @@ export default class LoginView { static async tapResetWalletButton() { await TestHelpers.tap(RESET_WALLET_ID); } + static async toggleRememberMe() { + await TestHelpers.tap(LOGIN_WITH_REMEMBER_ME_SWITCH); + } static async isVisible() { await TestHelpers.checkIfVisible(LOGIN_CONTAINER_ID); diff --git a/e2e/specs/browser-tests.spec.js b/e2e/specs/browser-tests.spec.js index bff2f7c423a..4999bdded05 100644 --- a/e2e/specs/browser-tests.spec.js +++ b/e2e/specs/browser-tests.spec.js @@ -19,7 +19,7 @@ import WhatsNewModal from '../pages/modals/WhatsNewModal'; const ENS_Example = 'https://brunobarbieri.eth'; const ENS_TLD = 'https://inbox.mailchain.xyz'; -const UNISWAP = 'https://uniswap.exchange'; +const SUSHI_SWAP = 'https://app.sushi.com/swap'; const PASSWORD = '12345678'; const PHISHING_SITE = 'http://www.empowr.com/FanFeed/Home.aspx'; const INVALID_URL = 'https://quackquakc.easq'; @@ -116,18 +116,18 @@ describe('Browser Tests', () => { } }); - it('should go to uniswap', async () => { + it('should go to sushi swap', async () => { await TestHelpers.delay(3000); // Tap on search in bottom navbar await Browser.tapBrowser(); - await Browser.navigateToURL(UNISWAP); + await Browser.navigateToURL(SUSHI_SWAP); // Wait for page to load await Browser.waitForBrowserPageToLoad(); if (device.getPlatform() === 'android') { // Check that the dapp title is correct - await TestHelpers.checkIfElementWithTextIsVisible('app.uniswap.org', 0); + await TestHelpers.checkIfElementWithTextIsVisible('app.sushi.com', 0); } await TestHelpers.delay(5000); await ConnectModal.tapCancelButton(); @@ -140,7 +140,7 @@ describe('Browser Tests', () => { await Browser.isVisible(); }); - it('should add uniswap to favorites', async () => { + it('should add sushi swap to favorites', async () => { // Check that we are still on the browser screen await Browser.isVisible(); // Tap on options @@ -160,7 +160,7 @@ describe('Browser Tests', () => { await Browser.isVisible(); }); - it('should tap on Uniswap in favorites', async () => { + it('should tap on sushi swap in favorites', async () => { if (device.getPlatform() === 'ios') { // Tapping on favourite tap await TestHelpers.tapAtPoint(BROWSER_SCREEN_ID, { x: 174, y: 281 }); @@ -174,6 +174,9 @@ describe('Browser Tests', () => { // Wait for connect prompt to display await TestHelpers.delay(5000); await ConnectModal.tapConnectButton(); + + await TestHelpers.tapAtPoint(BROWSER_SCREEN_ID, { x: 20, y: 130 }); // tapping to dismiss keyboard + await Browser.isVisible(); }); diff --git a/e2e/specs/deeplinks.spec.js b/e2e/specs/deeplinks.spec.js index 2f60098fb09..991444a4294 100644 --- a/e2e/specs/deeplinks.spec.js +++ b/e2e/specs/deeplinks.spec.js @@ -17,8 +17,11 @@ import { Browser } from '../pages/Drawer/Browser'; import DrawerView from '../pages/Drawer/DrawerView'; import NetworkView from '../pages/Drawer/Settings/NetworksView'; import SettingsView from '../pages/Drawer/Settings/SettingsView'; - +import LoginView from '../pages/LoginView'; import TransactionConfirmationView from '../pages/TransactionConfirmView'; + +import SecurityAndPrivacy from '../pages/Drawer/Settings/SecurityAndPrivacy/SecurityAndPrivacyView'; + import WalletView from '../pages/WalletView'; const SECRET_RECOVERY_PHRASE = @@ -35,10 +38,14 @@ const POLYGON_DEEPLINK_URL = const ETHEREUM_DEEPLINK_URL = 'https://metamask.app.link/send/0x1FDb169Ef12954F20A15852980e1F0C122BfC1D6@1?value=1e13'; -const RINKEBY_DEEPLINK_URL = - 'https://metamask.app.link/send/0x1FDb169Ef12954F20A15852980e1F0C122BfC1D6@4?value=1e13'; +const GOERLI_DEEPLINK_URL = + 'https://metamask.app.link/send/0x1FDb169Ef12954F20A15852980e1F0C122BfC1D6@5?value=1e13'; -const DAPP_DEEPLINK_URL = 'https://metamask.app.link/dapp/app.uniswap.org'; +const DAPP_DEEPLINK_URL = 'https://metamask.app.link/dapp/app.sushi.com'; + +const networkNotFoundText = 'Network not found'; +const networkErrorBodyMessage = + 'Network with chain id 56 not found in your wallet. Please add the network first.'; describe('Deep linking Tests', () => { beforeEach(() => { @@ -59,12 +66,11 @@ describe('Deep linking Tests', () => { }); it('should attempt to import wallet with invalid secret recovery phrase', async () => { - await ImportWalletView.toggleRememberMe(); + //await ImportWalletView.toggleRememberMe(); await ImportWalletView.enterSecretRecoveryPhrase(SECRET_RECOVERY_PHRASE); await ImportWalletView.enterPassword(PASSWORD); await ImportWalletView.reEnterPassword(PASSWORD); await WalletView.isVisible(); - /// }); it('should tap on the close button in the whats new modal', async () => { @@ -89,11 +95,38 @@ describe('Deep linking Tests', () => { // } }); - it('should deep link to the send flow with a custom network not added to wallet', async () => { - const networkNotFoundText = 'Network not found'; - const networkErrorBodyMessage = - 'Network with chain id 56 not found in your wallet. Please add the network first.'; + it('should go to the Privacy and settings view', async () => { + await WalletView.tapDrawerButton(); // tapping burger menu + + await DrawerView.isVisible(); + await DrawerView.tapSettings(); + + await SettingsView.tapSecurityAndPrivacy(); + + await SecurityAndPrivacy.scrollToTurnOnRememberMe(); + TestHelpers.delay(3000); + }); + + it('should enable remember me', async () => { + await SecurityAndPrivacy.isRememberMeToggleOff(); + await SecurityAndPrivacy.tapTurnOnRememberMeToggle(); + await SecurityAndPrivacy.isRememberMeToggleOn(); + + TestHelpers.delay(1500); + }); + + it('should relaunch the app then enable remember me', async () => { + // Relaunch app + await TestHelpers.relaunchApp(); + await LoginView.isVisible(); + await LoginView.toggleRememberMe(); + + await LoginView.enterPassword(PASSWORD); + await WalletView.isVisible(); + }); + + it('should deep link to Binance Smart Chain & show a network not found error message', async () => { await TestHelpers.openDeepLink(BINANCE_DEEPLINK_URL); await TestHelpers.delay(3000); await TestHelpers.checkIfElementWithTextIsVisible(networkNotFoundText); @@ -169,14 +202,16 @@ describe('Deep linking Tests', () => { await TransactionConfirmationView.isNetworkNameVisible('BNB Smart Chain'); }); - it('should deep link to the send flow on Rinkeby and submit the transaction', async () => { - await TestHelpers.openDeepLink(RINKEBY_DEEPLINK_URL); + it('should deep link to the send flow on Goerli and submit the transaction', async () => { + await TestHelpers.openDeepLink(GOERLI_DEEPLINK_URL); await TestHelpers.delay(4500); await TransactionConfirmationView.isVisible(); await TransactionConfirmationView.isNetworkNameVisible( - 'Rinkeby Test Network', + 'Goerli Test Network', + ); + await TransactionConfirmationView.isTransactionTotalCorrect( + '0.00001 GoerliETH', ); - await TransactionConfirmationView.isTransactionTotalCorrect('0.00001 ETH'); // Tap on the Send CTA await TransactionConfirmationView.tapConfirmButton(); // Check that we are on the wallet screen @@ -194,14 +229,14 @@ describe('Deep linking Tests', () => { await TransactionConfirmationView.tapCancelButton(); }); - it('should deep link to a dapp (Uniswap)', async () => { + it('should deep link to a dapp (Sushi swap)', async () => { await TestHelpers.openDeepLink(DAPP_DEEPLINK_URL); await TestHelpers.delay(4500); await ConnectModal.isVisible(); await ConnectModal.tapConnectButton(); - await TestHelpers.checkIfElementWithTextIsVisible('app.uniswap.org', 0); + await TestHelpers.checkIfElementWithTextIsVisible('app.sushi.com', 0); await Browser.isVisible(); await ConnectModal.isNotVisible(); diff --git a/e2e/specs/onboarding-wizard-opt-in.spec.js b/e2e/specs/onboarding-wizard-opt-in.spec.js index 087949175c4..8c0d016c80c 100644 --- a/e2e/specs/onboarding-wizard-opt-in.spec.js +++ b/e2e/specs/onboarding-wizard-opt-in.spec.js @@ -97,6 +97,7 @@ describe('Onboarding wizard opt-in, metametrics opt out from settings', () => { await SettingsView.tapSecurityAndPrivacy(); await SecurityAndPrivacy.scrollToBottomOfView(); + TestHelpers.delay(2000); await SecurityAndPrivacy.isMetaMetricsToggleOn(); TestHelpers.delay(1500); diff --git a/e2e/specs/wallet-tests.spec.js b/e2e/specs/wallet-tests.spec.js index 7a2c4532c2d..3f9b8c50198 100644 --- a/e2e/specs/wallet-tests.spec.js +++ b/e2e/specs/wallet-tests.spec.js @@ -28,6 +28,7 @@ const SECRET_RECOVERY_PHRASE = const PASSWORD = `12345678`; const TEST_PUBLIC_ADDRESS = '0xd3B9Cbea7856AECf4A6F7c3F4E8791F79cBeeD62'; const RINKEBY = 'Rinkeby Test Network'; +const GOERLI = 'Goerli Test Network'; const ETHEREUM = 'Ethereum Main Network'; const COLLECTIBLE_CONTRACT_ADDRESS = '0x16baf0de678e52367adc69fd067e5edd1d33e3bf'; @@ -280,11 +281,17 @@ describe('Wallet Tests', () => { await WalletView.isTokenVisibleInWallet('0 BLT'); }); - it('should switch back to Rinkeby network', async () => { + it('should switch to Goerli network', async () => { await WalletView.tapNetworksButtonOnNavBar(); await NetworkListModal.isVisible(); - await NetworkListModal.changeNetwork(RINKEBY); - await WalletView.isNetworkNameVisible(RINKEBY); + await NetworkListModal.changeNetwork(GOERLI); + await WalletView.isNetworkNameVisible(GOERLI); + }); + + it('should dismiss network education modal', async () => { + await NetworkEducationModal.isVisible(); + await NetworkEducationModal.tapGotItButton(); + await NetworkEducationModal.isNotVisible(); }); it('should input a valid address', async () => { @@ -320,7 +327,9 @@ describe('Wallet Tests', () => { it('should send ETH to Account 2', async () => { // Check that the amount is correct - await TransactionConfirmationView.isTransactionTotalCorrect('0.00004 ETH'); + await TransactionConfirmationView.isTransactionTotalCorrect( + '0.00004 GoerliETH', + ); // Tap on the Send CTA await TransactionConfirmationView.tapConfirmButton(); // Check that we are on the wallet screen diff --git a/package.json b/package.json index d19e8134dbb..9c76ed71797 100644 --- a/package.json +++ b/package.json @@ -293,7 +293,7 @@ "babel-jest": "^26.6.3", "babel-loader": "^8.2.3", "concat-cli": "4.0.0", - "detox": "19.6.5", + "detox": "19.7.1", "enzyme": "3.9.0", "enzyme-adapter-react-16": "1.10.0", "enzyme-to-json": "3.3.5", diff --git a/yarn.lock b/yarn.lock index fce70acdb2a..c0d91bbc6ab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6996,10 +6996,10 @@ detect-node-es@^1.1.0: resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493" integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ== -detox@19.6.5: - version "19.6.5" - resolved "https://registry.yarnpkg.com/detox/-/detox-19.6.5.tgz#a4b0a5f574589762dc58eb75a8dd0df1005171bd" - integrity sha512-4r0fU65cvUzLcvrfZUbVNO8UrG0iqRI3m+v/QN8nLOw/jRVViI222az+LcWhDRE2bUwsyQ690k+W4F3wc21wjA== +detox@19.7.1: + version "19.7.1" + resolved "https://registry.yarnpkg.com/detox/-/detox-19.7.1.tgz#1c4dfebbb024426118dfae97a0189a25021479fa" + integrity sha512-V0XwiaFX1LvIjLl+G4tzMZ0M4YqenQXAdTsw9kO2dVo6NC9RuYqOIsmT9M3CRN9PF22TKJ8pFdA6onYhH/zkiQ== dependencies: ajv "^8.6.3" bunyan "^1.8.12" @@ -7025,6 +7025,7 @@ detox@19.6.5: which "^1.3.1" ws "^7.0.0" yargs "^16.0.3" + yargs-parser "^20.2.2" yargs-unparser "^2.0.0" dezalgo@^1.0.0: