Skip to content

Commit

Permalink
test(e2e): add new account creation test for new tab and cloud backup (
Browse files Browse the repository at this point in the history
…#5142)

### Description

Renames existing NewAccountOnboarding test to NewAccountOnboardingDrawer
and updates NewAccountOnboarding to run against tab navigator and cloud
backup

### Test plan

CI

### Related issues

- Part of ACT-1113

### Backwards compatibility

N/A

### Network scalability

N/A
  • Loading branch information
satish-ravi committed Mar 22, 2024
1 parent c718c7f commit 2b93dde
Show file tree
Hide file tree
Showing 6 changed files with 247 additions and 62 deletions.
2 changes: 2 additions & 0 deletions e2e/src/AccountSetup.spec.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import NewAccountOnboarding from './usecases/NewAccountOnboarding'
import NewAccountOnboardingDrawer from './usecases/NewAccountOnboardingDrawer'
import RestoreAccountOnboarding from './usecases/RestoreAccountOnboarding'

describe('Account Setup', () => {
describe('New Account', NewAccountOnboarding)
describe('New Account Drawer', NewAccountOnboardingDrawer)
describe('Restore', RestoreAccountOnboarding)
})
57 changes: 32 additions & 25 deletions e2e/src/usecases/NewAccountOnboarding.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@ import {
scrollIntoView,
sleep,
waitForElementId,
waitForElementByIdAndTap,
navigateToSettings,
} from '../utils/utils'

import jestExpect from 'expect'

const quickEducation = async () => {
await element(by.id('DrawerItem/Recovery Phrase')).tap()
const startBackupFromNotifications = async () => {
await element(by.id('WalletHome/NotificationBell')).tap()
await element(by.text('Back up now')).tap()
await enterPinUi()
await waitForElementByIdAndTap('WalletSecurityPrimer/GetStarted')
await waitForElementByIdAndTap('keylessBackupIntro/RecoveryPhrase')
await element(by.id('SetUpAccountKey')).tap()

// Go through education
Expand All @@ -30,13 +35,6 @@ const arriveAtHomeScreen = async () => {
await expect(element(by.id('HomeAction-Send'))).toBeVisible()
}

const openHamburger = async () => {
// Able to open the drawer - testing https://github.com/valora-inc/wallet/issues/3043
await waitForElementId('Hamburger')
await element(by.id('Hamburger')).tap()
await waitForElementId('Drawer/Header')
}

export default NewAccountOnboarding = () => {
let testRecoveryPhrase, testAccountAddress
beforeAll(async () => {
Expand All @@ -45,6 +43,9 @@ export default NewAccountOnboarding = () => {
await launchApp({
delete: true,
permissions: { notifications: 'YES', contacts: 'YES' },
launchArgs: {
statsigGateOverrides: `use_tab_navigator=true,show_cloud_account_backup_setup=true,show_cloud_account_backup_restore=true`,
},
})
await sleep(5000)
})
Expand Down Expand Up @@ -74,12 +75,14 @@ export default NewAccountOnboarding = () => {
// Arrived to Home screen
await arriveAtHomeScreen()

// Able to open the drawer
await openHamburger()
// Able to open the profile / menu
await waitForElementByIdAndTap('WalletHome/AccountCircle')
await waitForElementId('ProfileMenu/Settings')
await element(by.id('Times')).tap()
})

it('Should be able to exit recovery phrase flow', async () => {
await quickEducation()
await startBackupFromNotifications()
await waitFor(element(by.text('Cancel')))
.toBeVisible()
.withTimeout(10 * 1000)
Expand All @@ -96,8 +99,7 @@ export default NewAccountOnboarding = () => {
})

it('Setup Recovery Phrase', async () => {
await openHamburger()
await quickEducation()
await startBackupFromNotifications()

const attributes = await element(by.id('AccountKeyWordsContainer')).getAttributes()
testRecoveryPhrase = attributes.label
Expand All @@ -120,21 +122,23 @@ export default NewAccountOnboarding = () => {
.withTimeout(10 * 1000)
})

it('Account Address shown in drawer menu', async () => {
await waitForElementId('Hamburger')
await element(by.id('Hamburger')).tap()
it('Account Address shown in profile / menu', async () => {
await waitForElementByIdAndTap('WalletHome/AccountCircle')
await scrollIntoView('Account Address', 'SettingsScrollView')
const accountAddressElement = await element(by.id('AccountNumber')).getAttributes()
const accountAddressText = accountAddressElement.text.replace(/\s/g, '')
testAccountAddress = accountAddressText
jestExpect(testAccountAddress).toMatch(/0x[0-9a-fA-F]{40}/)
await element(by.id('Times')).tap()
})

// After quiz completion recovery phrase should only be shown in settings
// After quiz completion recovery phrase should only be shown in settings and
// not in notifications
it('Recovery phrase only shown in settings', async () => {
await expect(element(by.id('DrawerItem/Recovery Phrase'))).not.toExist()
await waitForElementId('DrawerItem/Settings')
await element(by.id('DrawerItem/Settings')).tap()
await element(by.id('WalletHome/NotificationBell')).tap()
await expect(element(by.text('Back up now'))).not.toExist()
await element(by.id('BackChevron')).tap()
await navigateToSettings('tab')
await waitForElementId('RecoveryPhrase')
await element(by.id('RecoveryPhrase')).tap()
await enterPinUi()
Expand All @@ -153,10 +157,13 @@ export default NewAccountOnboarding = () => {
it('Should be able to restore newly created account', async () => {
await device.uninstallApp()
await device.installApp()
await launchApp()
await quickOnboarding(testRecoveryPhrase)
await waitForElementId('Hamburger')
await element(by.id('Hamburger')).tap()
await launchApp({
launchArgs: {
statsigGateOverrides: `use_tab_navigator=true,show_cloud_account_backup_setup=true,show_cloud_account_backup_restore=true`,
},
})
await quickOnboarding(testRecoveryPhrase, true)
await waitForElementByIdAndTap('WalletHome/AccountCircle')
await scrollIntoView('Account Address', 'SettingsScrollView')
const addressString = '0x ' + getAddressChunks(testAccountAddress).join(' ')
await expect(element(by.text(addressString))).toBeVisible()
Expand Down
164 changes: 164 additions & 0 deletions e2e/src/usecases/NewAccountOnboardingDrawer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import { getAddressChunks } from '@celo/utils/lib/address'
import { EXAMPLE_NAME } from '../utils/consts'
import { launchApp } from '../utils/retries'
import {
completeProtectWalletScreen,
enterPinUi,
quickOnboarding,
scrollIntoView,
sleep,
waitForElementId,
} from '../utils/utils'

import jestExpect from 'expect'

const quickEducation = async () => {
await element(by.id('DrawerItem/Recovery Phrase')).tap()
await enterPinUi()
await element(by.id('SetUpAccountKey')).tap()

// Go through education
for (let i = 0; i < 4; i++) {
await element(by.id('Education/progressButton')).tap()
}

await expect(element(by.id('AccountKeyWordsContainer'))).toBeVisible()
}

const arriveAtHomeScreen = async () => {
// Arrived to Home screen
await expect(element(by.id('HomeAction-Send'))).toBeVisible()
}

const openHamburger = async () => {
// Able to open the drawer - testing https://github.com/valora-inc/wallet/issues/3043
await waitForElementId('Hamburger')
await element(by.id('Hamburger')).tap()
await waitForElementId('Drawer/Header')
}

export default NewAccountOnboarding = () => {
let testRecoveryPhrase, testAccountAddress
beforeAll(async () => {
await device.terminateApp()
await sleep(5000)
await launchApp({
delete: true,
permissions: { notifications: 'YES', contacts: 'YES' },
})
await sleep(5000)
})

it('Create a new account', async () => {
await element(by.id('CreateAccountButton')).tap()

// Accept Terms
await element(by.id('scrollView')).scrollTo('bottom')
await expect(element(by.id('AcceptTermsButton'))).toBeVisible()
await element(by.id('AcceptTermsButton')).tap()

// Set name and number
await element(by.id('NameEntry')).replaceText(EXAMPLE_NAME)
await element(by.id('NameAndPictureContinueButton')).tap()

// Set & Verify pin
await enterPinUi()
await enterPinUi()

// Protect Wallet screen
await completeProtectWalletScreen()

// Skip Phone Number verification
await element(by.id('PhoneVerificationSkipHeader')).tap()

// Arrived to Home screen
await arriveAtHomeScreen()

// Able to open the drawer
await openHamburger()
})

it('Should be able to exit recovery phrase flow', async () => {
await quickEducation()
await waitFor(element(by.text('Cancel')))
.toBeVisible()
.withTimeout(10 * 1000)
await element(by.text('Cancel')).tap()

// Cancel modal is shown
await waitFor(element(by.text('Set Up Later')))
.toBeVisible()
.withTimeout(10 * 1000)
await element(by.text('Set Up Later')).tap()

// App doesn't crash and we arrive at the home screen
await arriveAtHomeScreen()
})

it('Setup Recovery Phrase', async () => {
await openHamburger()
await quickEducation()

const attributes = await element(by.id('AccountKeyWordsContainer')).getAttributes()
testRecoveryPhrase = attributes.label

await element(by.id('backupKeySavedSwitch')).longPress()
await element(by.id('backupKeyContinue')).tap()
for (const word of testRecoveryPhrase.split(' ')) {
await element(by.id(`backupQuiz/${word}`)).tap()
}
await element(by.id('QuizSubmit')).tap()

// Backup complete screen is served
await waitFor(element(by.id('BackupComplete')))
.toBeVisible()
.withTimeout(10 * 1000)

// Navigated to Home screen
await waitFor(element(by.id('HomeAction-Send')))
.toBeVisible()
.withTimeout(10 * 1000)
})

it('Account Address shown in drawer menu', async () => {
await waitForElementId('Hamburger')
await element(by.id('Hamburger')).tap()
await scrollIntoView('Account Address', 'SettingsScrollView')
const accountAddressElement = await element(by.id('AccountNumber')).getAttributes()
const accountAddressText = accountAddressElement.text.replace(/\s/g, '')
testAccountAddress = accountAddressText
jestExpect(testAccountAddress).toMatch(/0x[0-9a-fA-F]{40}/)
})

// After quiz completion recovery phrase should only be shown in settings
it('Recovery phrase only shown in settings', async () => {
await expect(element(by.id('DrawerItem/Recovery Phrase'))).not.toExist()
await waitForElementId('DrawerItem/Settings')
await element(by.id('DrawerItem/Settings')).tap()
await waitForElementId('RecoveryPhrase')
await element(by.id('RecoveryPhrase')).tap()
await enterPinUi()
await waitForElementId('AccountKeyWordsContainer')
})

// Based off the flag set in src/firebase/remoteConfigValuesDefaults.e2e.ts
// We can only test one path 12 or 24 words as we cannot flip the flag after the build step
it('Recovery phrase has 12 words', async () => {
const recoveryPhraseContainer = await element(by.id('AccountKeyWordsContainer')).getAttributes()
const recoveryPhraseText = recoveryPhraseContainer.label
jestExpect(recoveryPhraseText.split(' ').length).toBe(12)
jestExpect(recoveryPhraseText).toBe(testRecoveryPhrase)
})

it('Should be able to restore newly created account', async () => {
await device.uninstallApp()
await device.installApp()
await launchApp()
await quickOnboarding(testRecoveryPhrase)
await waitForElementId('Hamburger')
await element(by.id('Hamburger')).tap()
await scrollIntoView('Account Address', 'SettingsScrollView')
const addressString = '0x ' + getAddressChunks(testAccountAddress).join(' ')
await expect(element(by.text(addressString))).toBeVisible()
})
}
4 changes: 3 additions & 1 deletion e2e/src/utils/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ export function quote(s) {
return device.getPlatform() === 'ios' ? s : `"${s}"`
}

export async function quickOnboarding(mnemonic = SAMPLE_BACKUP_KEY) {
export async function quickOnboarding(mnemonic = SAMPLE_BACKUP_KEY, cloudBackupEnabled = false) {
try {
// Tap Restore Account
await element(by.id('RestoreAccountButton')).tap()
Expand All @@ -175,6 +175,8 @@ export async function quickOnboarding(mnemonic = SAMPLE_BACKUP_KEY) {
// Verify pin
await enterPinUi()

if (cloudBackupEnabled) await waitForElementByIdAndTap('ImportSelect/Mnemonic')

// Restore existing wallet
await waitFor(element(by.id('connectingToCelo')))
.not.toBeVisible()
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-native": "^4.0.0",
"ethers": "^5.7.2",
"expect": "^29.7.0",
"husky": "^3.0.0",
"jest": "^29.6.2",
"jest-circus": "^29.6.2",
Expand Down
Loading

0 comments on commit 2b93dde

Please sign in to comment.