Skip to content
Asia/Kolkata
ProjectsJuly 7, 2026

Cross-Platform Mobile E2E Testing with mobilewright

image
A complete mobile E2E test suite for a React Native cross-platform app using mobilewright, the mobile-native fork of Playwright. The test suite covers 11 app screens across 19 test files, all passing on both iOS Release simulator and Android Release APK builds. The project also identified and fixed two upstream bugs in mobilewright itself. The suite tests the following screens in a React Native application (ProfileConnect): | Screen | Tests | Key Validations | |---|---|---| | Login | 7 | Form submit, field validation, error banners, register flow, duplicate email | | Profile | 3 | Edit/save, notification toggles, logout flow | | Alerts | 1 | Navigate and screen presence | | Animation | 1 | Navigate and screen presence | | Calendar | 1 | Navigate and screen presence | | FormControls | 1 | Form submission | | Gestures | 1 | Navigate and screen presence | | Lists | 1 | Search functionality | | Media | 1 | File navigation and search | | Signature | 1 | Navigate and screen presence |
  • 100% Pass Rate — All 19 tests pass on both iOS and Android when run individually on fresh boots
  • Multi-Project Config — Separate ios and android projects in mobilewright.config.ts with per-platform bundle IDs, device selectors, and build paths
  • Platform-Aware Locators — Uses getByTestId primarily with getByText fallback; conditional scroll logic for Android (off-screen elements not in accessibility tree)
  • App Launch Handling — Proper keyboard-initialization delay (tap() + 500ms before fill()) on Android to prevent dropped first character
  • Release Builds — Tests run against iOS Release simulator .app (Hermes, no Metro) and Android Release .apk with bundled JS
Bug: actionTimeout, appLaunchTimeout, and installTimeout set in a project's use block were ignored because connectDevice was called before merging project-level config into the top-level use. Fix: Moved the merge of project-level use before connectDevice, ensuring per-project timeouts are respected. Status: Open at mobile-next/mobilewright#220 Bug: swipeDirectionToReveal calculated the swipe endpoint using the element's center Y instead of its bottom Y, causing the scroll to stop short of the target. Fix: Changed the Y calculation to use boundingBox.y + boundingBox.height (bottom) instead of boundingBox.y + boundingBox.height / 2 (center). Status: Open at mobile-next/mobilewright#221
Typescript
export default defineConfig({
  use: { actionTimeout: 20000, appLaunchTimeout: 60000 },
  projects: [
    {
      name: 'ios',
      use: {
        platform: 'ios',
        bundleId: 'org.reactjs.native.example.TestApplication',
        deviceName: /iPhone 16 Pro/,
        installApps: './builds/TestApp-v26.zip',
      },
    },
    {
      name: 'android',
      use: {
        platform: 'android',
        bundleId: 'com.profileconnect',
        deviceName: /Medium Phone API/,
        installApps: './builds/app-release.apk',
      },
      retries: 2,
    },
  ],
});
Typescript
// helpers.ts — reusable across all tests
export async function login(page) {
  await page.getByTestId('emailInput').tap();
  await page.waitForTimeout(500); // keyboard init
  await page.getByTestId('emailInput').fill('test@example.com');
  await page.getByTestId('passwordInput').fill('123456');
  await page.getByTestId('signInButton').tap();
}

export async function navigateTo(page, testId) {
  if ((await page.getByTestId(testId).count()) === 0) {
    await page.swipe('up');
  }
  await page.getByTestId(testId).tap();
}
  • mobilewright (@mobilewright/test) — Mobile-native Playwright fork for iOS/Android E2E testing
  • React Native — The app under test (ProfileConnect)
  • Xcode — iOS Release simulator builds via xcodebuild
  • Android Studio / Gradle — Android Release APK builds
  • DeviceKit — Device management layer (mobilecli + devicekit agent)
  • FlakeIQ — Companion flake tracker (separate project integrated via custom reporter)
Emulator Memory Pressure: The Android API 36 emulator reaches ~86% CPU after ~50–70 device.dump.ui calls in a batch run, causing ANR dialogs and test timeouts. This was addressed by running individual test files on fresh emulator boots and documenting the constraint. Platform Tree Differences: iOS includes off-screen elements in the accessibility tree with isVisible: false, while Android omits them entirely. This required a count() === 0 check before attempting swipe('up') on Android. TouchableOpacity Limitation: React Native's TouchableOpacity does not expose testID as accessibilityIdentifier on iOS, making it invisible to mobilewright. Pressable with testID + role="button" is the fix, requiring app source changes. Config Scoping: The framework bug where project-level timeouts were silently ignored cost significant debugging time before the root cause was identified and patched. The test suite provides reliable regression coverage for all major app screens on both platforms. The two upstream PRs fix real framework bugs that affect all mobilewright users. The platform-specific learnings around tree differences, memory pressure, and keyboard initialization are documented for the team and captured in reusable test helpers.
More work

Related projects

FlakeIQ — Flake Tracking and LLM-Powered Failure Classification

FlakeIQ — Flake Tracking and LLM-Powered Failure Classification

Built a flake analysis pipeline for mobile E2E tests that captures test context at runtime, classifies failures via Ollama (llama3.2), and visualizes trends in a real-time Chart.js dashboard.

Adya — From SwiftUI Prototype to Cross-Platform Rewrite

A minimal daily task manager, first validated as a native SwiftUI/iOS prototype, then rebuilt from scratch in Expo/React Native (New Architecture) to ship one codebase across iOS and Android.

QuantForge — Multi-Agent Market Intelligence & Algorithmic Trading Platform

A multi-agent market intelligence platform for Indian markets (NSE/BSE) built on Zerodha Kite Connect — 13 independent AI agents surface probabilistic signals, with a Risk Agent holding veto power and every strategy required to clear a Backtest → Out-of-Sample → Paper Trading → Risk Review gate before it can touch capital.