Skip to content

Commit

Permalink
test(e2e): set up tests on mainnet (#6229)
Browse files Browse the repository at this point in the history
### Description

- Moves E2E testing to mainnet.
- Removes `Verify.spec` & `FiatConnectTransferOut.spec.js`.
- Moves secret management from GH to GCP.
- Adjusts the `waitForElementByText` util function to take an object
param.
- Wraps all use cases with a `e2e/src/*.spec.js`, use cases changed:
  -  `e2e/src/usecases/ChooseYourAdventure.js`
  -  `e2e/src/usecases/HomeFeed.js`
 
### Test plan

To test locally, populate the `e2e/example.env` and rename for
`e2e/.env`.

- [x] Tested locally on iOS & Android
- [x] Tested CI on iOS and on Android

### Related issues

- Fixes ACT-1419

### Backwards compatibility

Yes

### Network scalability

Yes

---------

Co-authored-by: Joe Bergeron <jbergero@alum.mit.edu>
Co-authored-by: Satish Ravi <satish.ravi@valoraapp.com>
  • Loading branch information
3 people authored Nov 28, 2024
1 parent f39abe8 commit e2346ec
Show file tree
Hide file tree
Showing 48 changed files with 354 additions and 831 deletions.
2 changes: 1 addition & 1 deletion .env.test
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
DEFAULT_TESTNET=alfajores
DEFAULT_TESTNET=mainnet
SMS_RETRIEVER_APP_SIGNATURE=TODO
DEV_SETTINGS_ACTIVE_INITIALLY=true
# Disable firebase b.c. google-services.json files are missing in CI
Expand Down
36 changes: 33 additions & 3 deletions .github/workflows/e2e-android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ on:

jobs:
android:
env:
# `if` conditions can't directly access secrets, so we use a workaround
# See https://docs.github.com/en/actions/security-guides/encrypted-secrets#using-encrypted-secrets-in-a-workflow
SECRETS_AVAILABLE: ${{ secrets.SECRETS_AVAILABLE }}
BASH_ENV: ~/.profile
name: Android (SDK ${{ inputs.android-api-level }})
runs-on:
- nscloud-ubuntu-22.04-amd64-16x64-with-cache
Expand All @@ -17,6 +22,25 @@ jobs:
# If it takes longer it usually fails, so no need to pay for more
timeout-minutes: 25
steps:
- uses: google-github-actions/auth@v2
if: ${{ env.SECRETS_AVAILABLE }}
with:
project_id: celo-mobile-mainnet
credentials_json: ${{ secrets.MAINNET_SERVICE_ACCOUNT_KEY }}
- name: Google Secrets
if: ${{ env.SECRETS_AVAILABLE }}
id: google-secrets
uses: google-github-actions/get-secretmanager-secrets@v2.1.4
with:
secrets: |-
E2E_WALLET_CONNECT_PROJECT_ID:projects/1027349420744/secrets/E2E_WALLET_CONNECT_PROJECT_ID
E2E_DEFAULT_RECIPIENT_MNEMONIC:projects/1027349420744/secrets/E2E_DEFAULT_RECIPIENT_MNEMONIC
E2E_DEFAULT_RECIPIENT_PRIVATE_KEY:projects/1027349420744/secrets/E2E_DEFAULT_RECIPIENT_PRIVATE_KEY
E2E_WALLET_MNEMONIC:projects/1027349420744/secrets/E2E_WALLET_MNEMONIC
E2E_WALLET_PRIVATE_KEY:projects/1027349420744/secrets/E2E_WALLET_PRIVATE_KEY
E2E_WALLET_SINGLE_VERIFIED_MNEMONIC:projects/1027349420744/secrets/E2E_WALLET_SINGLE_VERIFIED_MNEMONIC
E2E_WALLET_MULTIPLE_VERIFIED_MNEMONIC:projects/1027349420744/secrets/E2E_WALLET_MULTIPLE_VERIFIED_MNEMONIC
E2E_WALLET_12_WORDS_MNEMONIC:projects/1027349420744/secrets/E2E_WALLET_12_WORDS_MNEMONIC
- uses: actions/checkout@v4
- name: Set env
run: |
Expand Down Expand Up @@ -74,9 +98,6 @@ jobs:
run: yarn build:ts
- name: Check E2E wallet balance
run: NODE_OPTIONS='--unhandled-rejections=strict' yarn ts-node ./e2e/scripts/check-e2e-wallet-balance.ts
- name: Create Android E2E .env File
working-directory: e2e
run: echo WALLET_CONNECT_PROJECT_ID_E2E=${{ secrets.WALLET_CONNECT_PROJECT_ID_E2E }} >> .env
- name: Create Detox Build
run: CELO_TEST_CONFIG=e2e yarn detox build -c android.release
- name: Run Detox
Expand All @@ -94,6 +115,15 @@ jobs:
--headless
--retries 3
--device-boot-args="-snapshot ci_boot"
env:
E2E_WALLET_CONNECT_PROJECT_ID: ${{ steps.google-secrets.outputs.E2E_WALLET_CONNECT_PROJECT_ID }}
E2E_DEFAULT_RECIPIENT_MNEMONIC: ${{ steps.google-secrets.outputs.E2E_DEFAULT_RECIPIENT_MNEMONIC }}
E2E_DEFAULT_RECIPIENT_PRIVATE_KEY: ${{ steps.google-secrets.outputs.E2E_DEFAULT_RECIPIENT_PRIVATE_KEY }}
E2E_WALLET_MNEMONIC: ${{ steps.google-secrets.outputs.E2E_WALLET_MNEMONIC }}
E2E_WALLET_PRIVATE_KEY: ${{ steps.google-secrets.outputs.E2E_WALLET_PRIVATE_KEY }}
E2E_WALLET_SINGLE_VERIFIED_MNEMONIC: ${{ steps.google-secrets.outputs.E2E_WALLET_SINGLE_VERIFIED_MNEMONIC }}
E2E_WALLET_MULTIPLE_VERIFIED_MNEMONIC: ${{ steps.google-secrets.outputs.E2E_WALLET_MULTIPLE_VERIFIED_MNEMONIC }}
E2E_WALLET_12_WORDS_MNEMONIC: ${{ steps.google-secrets.outputs.E2E_WALLET_12_WORDS_MNEMONIC }}
- name: Publish Android JUnit Report
if: always()
uses: mikepenz/action-junit-report@v4
Expand Down
24 changes: 19 additions & 5 deletions .github/workflows/e2e-faucet-balance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,27 @@ jobs:
balance-and-fund:
name: balance-and-fund
runs-on: ubuntu-latest
env:
# `if` conditions can't directly access secrets, so we use a workaround
# See https://docs.github.com/en/actions/security-guides/encrypted-secrets#using-encrypted-secrets-in-a-workflow
SECRETS_AVAILABLE: ${{ secrets.SECRETS_AVAILABLE }}
BASH_ENV: ~/.profile
steps:
- uses: google-github-actions/auth@v2
if: ${{ env.SECRETS_AVAILABLE }}
with:
project_id: celo-mobile-mainnet
credentials_json: ${{ secrets.MAINNET_SERVICE_ACCOUNT_KEY }}
- name: Google Secrets
if: ${{ env.SECRETS_AVAILABLE }}
id: google-secrets
uses: google-github-actions/get-secretmanager-secrets@v2.1.4
with:
secrets: |-
E2E_TEST_FAUCET_SECRET:projects/1027349420744/secrets/E2E_TEST_FAUCET_SECRET
- uses: actions/checkout@v4
- uses: ./.github/actions/yarn-install
- name: Create E2E Fund .env File
env:
TEST_FAUCET_SECRET: ${{ secrets.TEST_FAUCET_SECRET }}
working-directory: e2e
run: echo TEST_FAUCET_SECRET=$TEST_FAUCET_SECRET >> .env
- name: Run Balance and Fund
run: NODE_OPTIONS='--unhandled-rejections=strict' yarn ts-node ./e2e/scripts/fund-e2e-accounts.ts
env:
E2E_TEST_FAUCET_SECRET: ${{ steps.google-secrets.outputs.E2E_TEST_FAUCET_SECRET }}
20 changes: 17 additions & 3 deletions .github/workflows/e2e-ios.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ jobs:
with:
secrets: |-
EMERGE_API_TOKEN:projects/1027349420744/secrets/EMERGE_API_TOKEN
E2E_WALLET_CONNECT_PROJECT_ID:projects/1027349420744/secrets/E2E_WALLET_CONNECT_PROJECT_ID
E2E_DEFAULT_RECIPIENT_MNEMONIC:projects/1027349420744/secrets/E2E_DEFAULT_RECIPIENT_MNEMONIC
E2E_DEFAULT_RECIPIENT_PRIVATE_KEY:projects/1027349420744/secrets/E2E_DEFAULT_RECIPIENT_PRIVATE_KEY
E2E_WALLET_MNEMONIC:projects/1027349420744/secrets/E2E_WALLET_MNEMONIC
E2E_WALLET_PRIVATE_KEY:projects/1027349420744/secrets/E2E_WALLET_PRIVATE_KEY
E2E_WALLET_SINGLE_VERIFIED_MNEMONIC:projects/1027349420744/secrets/E2E_WALLET_SINGLE_VERIFIED_MNEMONIC
E2E_WALLET_MULTIPLE_VERIFIED_MNEMONIC:projects/1027349420744/secrets/E2E_WALLET_MULTIPLE_VERIFIED_MNEMONIC
E2E_WALLET_12_WORDS_MNEMONIC:projects/1027349420744/secrets/E2E_WALLET_12_WORDS_MNEMONIC
- uses: actions/checkout@v4
- uses: ./.github/actions/yarn-install
# Since the e2e runners have access to the Valora branding,
Expand All @@ -46,9 +54,6 @@ jobs:
run: yarn ts-node ./.github/scripts/checkPodfileAndUpdateRenovatePr.ts
- name: Check E2E wallet balance
run: NODE_OPTIONS='--unhandled-rejections=strict' yarn ts-node ./e2e/scripts/check-e2e-wallet-balance.ts
- name: Create iOS E2E .env File
working-directory: e2e
run: echo MOCK_PROVIDER_BASE_URL=${{ secrets.MOCK_PROVIDER_BASE_URL }} >> .env && echo MOCK_PROVIDER_API_KEY=${{ secrets.MOCK_PROVIDER_API_KEY }} >> .env && echo WALLET_CONNECT_PROJECT_ID_E2E=${{ secrets.WALLET_CONNECT_PROJECT_ID_E2E }} >> .env
- name: Create Detox Build
run: |
export CELO_TEST_CONFIG=e2e
Expand Down Expand Up @@ -76,6 +81,15 @@ jobs:
--maxWorkers 6
--retries 3
timeout-minutes: 45
env:
E2E_WALLET_CONNECT_PROJECT_ID: ${{ steps.google-secrets.outputs.E2E_WALLET_CONNECT_PROJECT_ID }}
E2E_DEFAULT_RECIPIENT_MNEMONIC: ${{ steps.google-secrets.outputs.E2E_DEFAULT_RECIPIENT_MNEMONIC }}
E2E_DEFAULT_RECIPIENT_PRIVATE_KEY: ${{ steps.google-secrets.outputs.E2E_DEFAULT_RECIPIENT_PRIVATE_KEY }}
E2E_WALLET_MNEMONIC: ${{ steps.google-secrets.outputs.E2E_WALLET_MNEMONIC }}
E2E_WALLET_PRIVATE_KEY: ${{ steps.google-secrets.outputs.E2E_WALLET_PRIVATE_KEY }}
E2E_WALLET_SINGLE_VERIFIED_MNEMONIC: ${{ steps.google-secrets.outputs.E2E_WALLET_SINGLE_VERIFIED_MNEMONIC }}
E2E_WALLET_MULTIPLE_VERIFIED_MNEMONIC: ${{ steps.google-secrets.outputs.E2E_WALLET_MULTIPLE_VERIFIED_MNEMONIC }}
E2E_WALLET_12_WORDS_MNEMONIC: ${{ steps.google-secrets.outputs.E2E_WALLET_12_WORDS_MNEMONIC }}
- name: Publish iOS JUnit Report
if: always()
uses: mikepenz/action-junit-report@v4
Expand Down
Binary file modified e2e/.env.enc
Binary file not shown.
4 changes: 4 additions & 0 deletions e2e/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ Ensure you have Xcode installed.

Install [AppleSimulatorUtils](https://github.com/wix/AppleSimulatorUtils#installing) which is used in e2e scripts to launch the iOS simulator.

### Setting up secrets for local runs

An `.env` example is present at `e2e/env.example` rename this file to `.env` and populate the secrets from Google Cloud Platform. Do not commit the newly created `e2e/.env` file.

## Running the tests

```sh
Expand Down
9 changes: 9 additions & 0 deletions e2e/env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
E2E_TEST_FAUCET_SECRET=""
E2E_WALLET_CONNECT_PROJECT_ID=""
E2E_DEFAULT_RECIPIENT_MNEMONIC=""
E2E_DEFAULT_RECIPIENT_PRIVATE_KEY=""
E2E_WALLET_MNEMONIC=""
E2E_WALLET_PRIVATE_KEY=""
E2E_WALLET_SINGLE_VERIFIED_MNEMONIC=""
E2E_WALLET_MULTIPLE_VERIFIED_MNEMONIC=""
E2E_WALLET_12_WORDS_MNEMONIC=""
1 change: 0 additions & 1 deletion e2e/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,5 @@ beforeAll(async () => {
await device.installApp()
await launchApp({
newInstance: false,
permissions: { notifications: 'YES', contacts: 'YES', camera: 'YES' },
})
})
5 changes: 4 additions & 1 deletion e2e/scripts/check-e2e-wallet-balance.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { E2E_TEST_WALLET, E2E_TEST_WALLET_SECURE_SEND } from './consts'
import { E2E_TEST_FAUCET, E2E_TEST_WALLET, E2E_TEST_WALLET_SECURE_SEND } from './consts'
import { checkBalance, getCeloTokensBalance } from './utils'
;(async () => {
console.log(`E2E_TEST_WALLET: ${E2E_TEST_WALLET}`)
Expand All @@ -8,4 +8,7 @@ import { checkBalance, getCeloTokensBalance } from './utils'
console.log(`E2E_TEST_WALLET_SECURE_SEND: ${E2E_TEST_WALLET_SECURE_SEND}`)
console.table(await getCeloTokensBalance(E2E_TEST_WALLET_SECURE_SEND))
await checkBalance(E2E_TEST_WALLET_SECURE_SEND)

console.log(`E2E_TEST_FACUET: ${E2E_TEST_FAUCET}`)
console.table(await getCeloTokensBalance(E2E_TEST_FAUCET))
})()
6 changes: 3 additions & 3 deletions e2e/scripts/consts.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const E2E_TEST_WALLET = '0x6131a6d616a4be3737b38988847270a64bc10caa'
export const E2E_TEST_WALLET_SECURE_SEND = '0x86b8f44386cb2d457db79c3dab8cf42f9d8a3fc0'
export const E2E_TEST_FAUCET = '0xe5F5363e31351C38ac82DBAdeaD91Fd5a7B08846'
export const E2E_TEST_WALLET = '0xebf95355cc5ea643179a02337f3f943fd8dd2bcb'
export const E2E_TEST_WALLET_SECURE_SEND = '0x06f4b680c6cb1aeec4a3ce12c63ea18acb136aa3'
export const E2E_TEST_FAUCET = '0xa694b396cd6f73e4003da8f97f4b12e498b3f2ec'
export const REFILL_TOKENS = ['CELO', 'cUSD', 'cEUR']
16 changes: 8 additions & 8 deletions e2e/scripts/fund-e2e-accounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ import {
} from './consts'
import { checkBalance, getCeloTokensBalance } from './utils'

const provider = new providers.JsonRpcProvider('https://alfajores-forno.celo-testnet.org')
const provider = new providers.JsonRpcProvider('https://forno.celo.org/')

dotenv.config({ path: `${__dirname}/../.env` })

const valoraTestFaucetSecret = process.env['TEST_FAUCET_SECRET']!
const valoraTestFaucetSecret = process.env['E2E_TEST_FAUCET_SECRET']!

interface Token {
symbol: string
Expand All @@ -25,17 +25,17 @@ interface Token {

const CELO: Token = {
symbol: 'CELO',
address: utils.getAddress('0xf194afdf50b03e69bd7d057c1aa9e10c9954e4c9'),
address: utils.getAddress('0x471ece3750da237f93b8e339c536989b8978a438'),
decimals: 18,
}
const CUSD: Token = {
symbol: 'cUSD',
address: utils.getAddress('0x874069fa1eb16d44d622f2e0ca25eea172369bc1'),
address: utils.getAddress('0x765de816845861e75a25fca122bb6898b8b1282a'),
decimals: 18,
}
const CEUR: Token = {
symbol: 'cEUR',
address: utils.getAddress('0x10c892a6ec43a53e45d0b916b4b7d383b1b78c0f'),
address: utils.getAddress('0xd8763cba276a3738e6de85b4b3bf5fded6d6ca73'),
decimals: 18,
}
const TOKENS_BY_SYMBOL: Record<string, Token> = {
Expand All @@ -53,7 +53,7 @@ const TOKENS_BY_SYMBOL: Record<string, Token> = {
}

const faucetTokenBalances = (await getCeloTokensBalance(E2E_TEST_FAUCET)) ?? {}
console.log('Initial faucet balance:')
console.log(`Initial balance for faucet at: ${E2E_TEST_FAUCET}:`)
console.table(faucetTokenBalances)

// Connect Valora E2E Test Faucet - Private Key Stored in GitHub Secrets
Expand Down Expand Up @@ -216,14 +216,14 @@ const TOKENS_BY_SYMBOL: Record<string, Token> = {
}

// Set Amount To Send
const amountToSend = '100'
const amountToSend = '10'

for (let i = 0; i < walletsToBeFunded.length; i++) {
const walletAddress = walletsToBeFunded[i]
const walletBalance = walletBalances[i]
for (const tokenSymbol of REFILL_TOKENS) {
// @ts-ignore
if (walletBalance && walletBalance[tokenSymbol] < 200) {
if (walletBalance && walletBalance[tokenSymbol] < 20) {
console.log(`Sending ${amountToSend} ${tokenSymbol} to ${walletAddress}`)
await transferToken(TOKENS_BY_SYMBOL[tokenSymbol], amountToSend, walletAddress)
}
Expand Down
14 changes: 7 additions & 7 deletions e2e/scripts/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Address, createPublicClient, erc20Abi, http } from 'viem'
import { celoAlfajores } from 'viem/chains'
import { celo } from 'viem/chains'
import { REFILL_TOKENS } from './consts'

export async function checkBalance(
Expand All @@ -11,7 +11,7 @@ export async function checkBalance(
for (const [tokenSymbol, tokenBalance] of Object.entries(balance)) {
if (tokenSymbols.includes(tokenSymbol) && tokenBalance < minBalance) {
throw new Error(
`${balance} balance of ${address} is below ${minBalance}. Please refill from the faucet https://celo.org/developers/faucet or run ./fund-e2e-accounts.ts if a Valora Dev.`
`${balance} balance of ${address} is below ${minBalance}. Please refill from the faucet or run ./fund-e2e-accounts.ts if a Valora Dev.`
)
}
}
Expand All @@ -20,15 +20,15 @@ export async function checkBalance(
export async function getCeloTokensBalance(walletAddress: Address) {
try {
const supportedTokenAddresses: Address[] = [
'0x874069fa1eb16d44d622f2e0ca25eea172369bc1',
'0x10c892a6ec43a53e45d0b916b4b7d383b1b78c0f',
'0xf194afdf50b03e69bd7d057c1aa9e10c9954e4c9',
'0xe4d517785d091d3c54818832db6094bcc2744545',
'0x765de816845861e75a25fca122bb6898b8b1282a',
'0xd8763cba276a3738e6de85b4b3bf5fded6d6ca73',
'0x471ece3750da237f93b8e339c536989b8978a438',
'0xe8537a3d056da446677b9e9d6c5db704eaab4787',
] // cUSD, cEUR, CELO, cREAL
const supportedTokenSymbols: string[] = ['cUSD', 'cEUR', 'CELO', 'cREAL']

const celoClient = createPublicClient({
chain: celoAlfajores,
chain: celo,
transport: http(),
})

Expand Down
2 changes: 0 additions & 2 deletions e2e/src/AccountSetup.spec.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import ChooseYourAdventure from './usecases/ChooseYourAdventure'
import NewAccountOnboarding from './usecases/NewAccountOnboarding'
import RestoreAccountOnboarding from './usecases/RestoreAccountOnboarding'

describe('Account Setup', () => {
describe('New Account', NewAccountOnboarding)
describe('Restore', RestoreAccountOnboarding)
describe('Choose Your Adventure', ChooseYourAdventure)
})
3 changes: 1 addition & 2 deletions e2e/src/CeloPage.spec.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import CeloEducation from './usecases/CeloEducation'
import PriceChart from './usecases/PriceChart'
import CeloNews from './usecases/CeloNews'
import PriceChart from './usecases/PriceChart'
import { quickOnboarding } from './utils/utils'
import { launchApp } from './utils/retries'

describe('Celo page', () => {
beforeAll(async () => {
Expand Down
3 changes: 3 additions & 0 deletions e2e/src/ChooseYourAdventure.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import ChooseYourAdventure from './usecases/ChooseYourAdventure'

describe('Choose your adventure', ChooseYourAdventure)
9 changes: 3 additions & 6 deletions e2e/src/Discover.spec.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import { quickOnboarding, waitForElementByIdAndTap, scrollIntoView } from './utils/utils'
import { launchApp } from './utils/retries'
import DappListDisplay from './usecases/DappListDisplay'
import { launchApp } from './utils/retries'
import { quickOnboarding, scrollIntoView, waitForElementByIdAndTap } from './utils/utils'

describe('Discover tab', () => {
beforeAll(async () => {
await quickOnboarding()
// Relaunch app to ensure dapp list loads
// Needed for e2e tests otherwise dapp list is not loaded on first pass
await launchApp({
newInstance: true,
permissions: { notifications: 'YES', contacts: 'YES', camera: 'YES' },
})
await launchApp()
await waitForElementByIdAndTap('Tab/Discover')

await scrollIntoView('View All', 'DiscoverScrollView')
Expand Down
27 changes: 0 additions & 27 deletions e2e/src/FiatConnectTransferOut.spec.js

This file was deleted.

Loading

0 comments on commit e2346ec

Please sign in to comment.