Skip to content

Conversation

@tobi-legan
Copy link

Description

This PR adds E2E testing infrastructure using WebdriverIO and Appium for the React Native wallet app.

Key Changes:

  • Added E2E testing setup with WebdriverIO v9 and Appium
  • Created test structure with page objects pattern (e2e/pageObjects/)
  • Added initial onboarding test (e2e/test/specs/onboarding.e2e.ts)
  • Moved all E2E-related scripts to e2e/package.json for better organization
  • Configured WebdriverIO with TypeScript support
  • Added E2E-specific TypeScript configuration

Files Added:

  • e2e/package.json - E2E dependencies and scripts (build-apk, appium, check-devices, etc.)
  • e2e/wdio.conf.ts - WebdriverIO configuration
  • e2e/tsconfig.json - TypeScript config for E2E tests
  • e2e/pageObjects/home-onboarding-screen.ts - Page object for onboarding screen
  • e2e/test/specs/onboarding.e2e.ts - Initial E2E test
  • e2e/README.md - E2E testing documentation

Scripts Added to e2e/package.json:

  • build-apk - Build standalone release APK for testing
  • build-ios - Build iOS app for testing
  • appium - Start Appium server
  • check-devices - Check connected Android devices
  • check-ios-devices - Check iOS simulators
  • test - Run E2E tests

Short video of the test added:
https://jam.dev/c/43c4b354-600d-4926-be8f-f83692219bbc

Motivation and Context

Problem:

  • No automated E2E testing infrastructure for the wallet app
  • Manual testing is time-consuming and error-prone
  • Need to verify app functionality across different devices/emulators
  • Want to catch regressions before release

Solution:

  • Implemented WebdriverIO + Appium for cross-platform E2E testing
  • Created reusable page objects for maintainable tests
  • Set up standalone APK builds for testing without Metro bundler
  • Organized all E2E scripts in dedicated e2e/ directory

Benefits:

  • Automated testing of critical user flows (onboarding, wallet creation)
  • Faster feedback on app functionality
  • Consistent testing across different Android devices
  • Foundation for expanding test coverage

Related Issue

N/A - This is a new feature addition (E2E testing infrastructure)

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

- Introduced E2E testing framework in the `e2e` directory, including configuration files and test scripts.
- Added `HomeOnboardingScreen` page object for managing onboarding screen interactions.
- Implemented initial test for wallet app onboarding, verifying UI elements and welcome messages.
- Updated `.gitignore` to exclude E2E test artifacts and configuration files.
- Modified `app.json` to disable development client for production builds.
- Added `package-lock.json` and `package.json` for E2E testing dependencies.
Copy link

@ignaciolarranaga ignaciolarranaga left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My main comments @tobi-legan (but want to hear from @jonathunne) are:

  • I think you should not generate another project (i.e. another package.json to be specific) but to enhance the current one. E2E is part of the lifecycle of the app,
  • I think you need to connect with Qase already, because we automate that suite

Later inside some opinionated comments.

I'm not sure why are you shipping this empty file also?: e2e/data/wallet-details-for-test.ts

From project root:

```bash
npm run e2e:build-apk

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not they way it should happen, if there is a build command it should be npm run build in the main project or similar (you do not build for the e2es, you build because you need to build as part of the CI/CD, e2es are just part of the life cycle)

Then run tests:

```bash
npm test

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

npm test:e2e I would suggest, a project might have multiple types of tests

├── tsconfig.json # TypeScript config
├── package.json # Dependencies
├── test/
│ └── specs/

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems too many levels isn't it?, but mainly related to my previous comment of I don't think you really need a project inside the other project. It seems more like e2e/*.test.ts or e2e/*.spec.ts & e2e/utils/*.ts for the utilities or similar.

@jonathunne might have a different vision though

@@ -0,0 +1,24 @@
{
"name": "wdk-starter-react-native-e2e",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need to extend the main project rather than creating a new one. @jonathunne WDYT?

I would expect this workflow at the root:

  • npm install
  • npm run build
  • npm test:e2e

Unless there is something I might be missing?

timeout: 60000,
},

//

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll remove all the commented code unless you are really defining something

paymasterToken: {
address: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
},
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this was unintended right?

@@ -0,0 +1,80 @@
# E2E Tests

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll probably recommend to add the relevant sections to the main README.md


const homeOnboardingScreen = new HomeOnboardingScreen();

describe('Wallet App E2E Tests', () => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

describe('Onboarding', () => { isn't it?

const homeOnboardingScreen = new HomeOnboardingScreen();

describe('Wallet App E2E Tests', () => {
it('should launch the standalone app and verify the create wallet button', async () => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You must link to an exiting test case in the suite (or may be multiple ones: https://app.qase.io/project/TW) as well as introduce the connection to Qase.

@tobi-legan
Copy link
Author

My main comments @tobi-legan (but want to hear from @jonathunne) are:

  • I think you should not generate another project (i.e. another package.json to be specific) but to enhance the current one. E2E is part of the lifecycle of the app,
  • I think you need to connect with Qase already, because we automate that suite

Later inside some opinionated comments.

I'm not sure why are you shipping this empty file also?: e2e/data/wallet-details-for-test.ts

So Let me explain this , and why this our case is a bit tricky and this will even also affect the type of tests that i will write if for this , this is just a couple of things to discuss and consider

Again Thanks for the feedback. The separate package.json structure is actually about managing test-specific wallet data and build configuration that can't live in the public repo. Here's why this matters:

The Core Issue: Test Data & Build Configuration

E2E tests require the app to be built with specific wallet/network details embedded. This creates several challenges:

  1. Test Wallet Data: Tests need predefined wallet states, seed phrases, and network configs that:

    • Can't be committed to the public repo
    • Must be injected at build time
    • Can't override the project's existing wallet configuration
  2. Build Scripts Needed: We'll need a script to set up test details before each build so we don't override the current project details. This script needs to:

    • Configure test wallet data before building
    • Keep test config separate from app config
    • Work locally (since we agreed to run E2E tests locally for now, no CI/CD yet)
  3. Team Decision Required: We need to decide:

    • Should everyone use our shared test wallet data? (Requires private config management)
    • Or should each developer use their own? (Will cause test failures if they don't update test data accordingly)

The separate e2e/package.json was part of keeping this test infrastructure isolated, but I understand the preference for a single package.json.

Proposed Approach

I'm happy to merge E2E scripts and dependencies into root package.json. However, we still need to solve the test data management problem:

  • Option A: Merge everything to root, use environment variables or gitignored config files for test data
  • Option B: Merge scripts/deps to root, keep test data setup infrastructure in e2e/ directory (gitignored)
  • Option C: Keep current structure until we finalize test data strategy

The empty e2e/data/wallet-details-for-test.ts file is a placeholder for this test data system—it's empty because we haven't decided on the approach yet.

Qase Integration

I haven't integrated with Qase yet. I can connect with the team to understand the existing setup and integrate WebdriverIO with Qase for test reporting/management.

Next Steps

  1. Merge E2E scripts/dependencies to root package.json (if we agree on approach)
  2. Decide on test data strategy (private config, env vars, or separate repo)
  3. Create test data setup script (to configure wallet details before builds)
  4. Integrate with Qase
  5. Remove empty file once we finalize approach

Happy to adjust based on team preferences.


docs

#i am ignoring this file for now so that my changes to the config file don't get pushed, since they are config changes, will remove it after
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this?

describe('Wallet App E2E Tests', () => {
it('should launch the standalone app and verify the create wallet button', async () => {
// Wait for app to load
await driver.pause(3000);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer explicit waits for elements instead of pauses.

e.g. await homeOnboardingScreen.getCreateWalletButton().waitForDisplayed({ timeout: 10000 });

await driver.pause(3000);

// Verify driver session exists
const sessionId = (driver as any).sessionId;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does driver have a type or do we have to use any here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete this empty file?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants