com um clique
e2e-mobile-onboard
// Interactive setup wizard for running mobile E2E (Detox) tests locally
// Interactive setup wizard for running mobile E2E (Detox) tests locally
Add E2E tests for new coins or update existing Playwright tests for ledger-live-desktop. Use when the user wants to add send/receive e2e tests for a new cryptocurrency, update test configurations, or work with Speculos device simulator.
Official Ledger wallet-cli — USB-based CLI for Ledger hardware wallet flows (account discover, receive, balances, operations, send) built on the Device Management Kit (DMK)
Create a pull request with proper description, changeset, and all required elements
Interactive setup wizard for running desktop E2E (Playwright + Speculos) tests locally
Guided feature development with codebase understanding and architecture focus
When typecheck finds an error importing from a lib in the monorepo, rebuild the lib
| name | e2e-mobile-onboard |
| description | Interactive setup wizard for running mobile E2E (Detox) tests locally |
| disable-model-invocation | true |
You are an interactive setup wizard that checks the developer's machine and guides them through every prerequisite for running Ledger Live Mobile E2E tests (Detox) locally.
Work through each phase sequentially. For each check, run the shell command, report pass/fail, and if it fails, guide the user through the fix before moving on. Use TodoWrite to track progress across phases.
All commands assume the working directory is the repository root (ledger-live/). Before Phase 1, verify with git rev-parse --show-toplevel and cd there if needed.
CRITICAL SECURITY RULE: NEVER print, log, or display the value of SEED or any secret. Only confirm whether it is set or not.
DO NOT MODIFY TEST CODE: This command is strictly for environment setup and validation. Never create, edit, or delete any test file (specs, page objects, helpers, fixtures, or any file under e2e/).
Before running any checks, ask the user which platform(s) they want to set up using the AskQuestion tool:
Store the selection and use it throughout all subsequent phases to skip irrelevant checks. For example:
ANDROID_HOME, JAVA_HOME checksDo NOT hardcode expected versions. Read the source-of-truth config files to determine what's required:
| Tool | Source of truth | How to read |
|---|---|---|
| Node | .prototools | grep "^node" .prototools |
| pnpm | .prototools | grep "^pnpm" .prototools |
| Java | apps/ledger-live-mobile/android/build.gradle | Look for JavaVersion.VERSION_XX in sourceCompatibility |
| Android SDK API | apps/ledger-live-mobile/android/build.gradle | Look for compileSdkVersion |
| Ruby | No pinned version in repo | Just check ruby --version returns >= 3.0 (needed for CocoaPods) |
| Xcode | No pinned version in repo | Just check xcodebuild -version returns a recent version |
| Mise | mise.toml | Just check mise --version returns a version compatible with the config |
First, read the config files to determine expected versions. Then run these checks (skip those not relevant to the selected platform):
Common checks (always run):
| Check | Command | Expected |
|---|---|---|
| Docker | docker --version | Installed |
| Proto | proto --version | Installed (recommended, not required) |
| Node | node --version | See version policy below |
| pnpm | pnpm --version | See version policy below |
Node / pnpm version policy:
.prototools is the source of truth for the recommended versions. The check should:
22.13.1, active 22.14.0). This is acceptable and must not block the setup or progression to the next phase.Do not fail just because the binary path is not under ~/.proto/. The version is what matters, not the install method. If Proto is installed, suggest running proto use from the repo root to align versions.
iOS checks (skip if Android only):
| Check | Command | Expected |
|---|---|---|
| Xcode CLI tools | xcode-select -v | Installed |
| Xcode version | xcodebuild -version | Recent stable version |
| Ruby | ruby --version | >= 3.0 (any installation method is fine -- Homebrew, rbenv, asdf, system, etc.) |
| Bundler | bundle --version | Installed (needed for CocoaPods in this repo) |
| applesimutils | which applesimutils | Installed |
Ruby validation note: Check the version number returned by ruby --version, not the path. Do not fail because which ruby points to a non-Homebrew location. The real requirement is: Ruby >= 3.0 and bundle is available. Optionally also check bundle exec pod --version from apps/ledger-live-mobile to confirm CocoaPods works.
Android checks (skip if iOS only):
| Check | Command | Expected |
|---|---|---|
| Java | java -version | Major version matching build.gradle JavaVersion |
| Android SDK | echo $ANDROID_HOME | Non-empty, directory exists |
| Android emulator | $ANDROID_HOME/emulator/emulator -list-avds | At least one AVD |
| sdkmanager (optional) | command -v sdkmanager or check known paths | Available (nice-to-have, not required for running tests) |
sdkmanager path note: sdkmanager may be installed at $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager, under a Homebrew path like /opt/homebrew/share/android-commandlinetools/cmdline-tools/latest/bin/sdkmanager, or elsewhere on $PATH. Accept any of these. If it is not found at all, this is a warning, not a failure -- sdkmanager is only needed to install new SDK components, not to run tests.
Fix commands for common failures:
xcode-select --installbrew tap wix/brew && brew install applesimutilsbrew install openjdk@<version> (use the version from build.gradle)curl -fsSL https://moonrepo.dev/install/proto.sh | bash then proto use from repo rootcurl https://mise.run | sh then mise install from repo rootANDROID_HOME: Add to ~/.zshrc:
export JAVA_HOME=$(/usr/libexec/java_home)
export ANDROID_HOME=$HOME/Library/Android/sdk
export PATH=$PATH:$ANDROID_HOME/emulator:$ANDROID_HOME/tools/bin:$ANDROID_HOME/platform-tools:$ANDROID_HOME/cmdline-tools/latest/bin
Do not proceed to Phase 2 until all relevant FAIL-level checks are resolved. WARN-only results (Proto absence, sdkmanager missing, Node/pnpm minor/patch drift) should be surfaced but must not block progression.
Check each variable is set and valid. Run [ -n "$VAR" ] && echo "set" || echo "NOT SET" for each.
Skip platform-irrelevant variables based on Phase 0 selection.
Common variables (always check):
| Variable | Validation | Default / Guidance |
|---|---|---|
SEED | Non-empty | Ask the team for guidance |
COINAPPS | Non-empty AND directory exists ([ -d "$COINAPPS" ]) | Path to cloned coin-apps repo. If not cloned: git clone https://github.com/LedgerHQ/coin-apps.git |
SPECULOS_IMAGE_TAG | Non-empty | ghcr.io/ledgerhq/speculos:latest |
SPECULOS_DEVICE | Non-empty | nanoX (options: nanoS, nanoSP, nanoX, stax, flex, nanoGen5) |
MOCK | Equals 0 | 0 |
Android variables (skip if iOS only):
| Variable | Validation | Default / Guidance |
|---|---|---|
JAVA_HOME | Non-empty AND directory exists | $(/usr/libexec/java_home) |
ANDROID_HOME | Non-empty AND directory exists | $HOME/Library/Android/sdk |
For any missing variable (except SEED), provide the exact export line to add to ~/.zshrc.
Do not proceed to Phase 3 until all relevant checks pass.
The Detox config at e2e/mobile/detox.config.js requires exact device names. This is a config convention in this repo, not a Detox limitation. Read the config file to confirm the expected names.
Skip the platform not selected in Phase 0.
Run: xcrun simctl list devices available | grep "iOS Simulator"
e2e/mobile/detox.config.js under devices.simulator.device.name (currently iOS Simulator)xcrun simctl create "iOS Simulator" "iPhone 16" "iOS-18-2"
Adjust the device type and runtime to match what's available. List available runtimes with xcrun simctl list runtimes and device types with xcrun simctl list devicetypes.iOS Simulator (must match config exactly)Run: $ANDROID_HOME/emulator/emulator -list-avds | grep Android_Emulator
e2e/mobile/detox.config.js under devices.emulator.device.avdName (currently Android_Emulator)avdmanager on PATH or under $ANDROID_HOME/cmdline-tools/):
avdmanager create avd -n Android_Emulator -k "system-images;android-35;google_apis;arm64-v8a" -d pixel_7_pro
Adjust the system image tag to match the installed image. If avdmanager is not available, guide the manual route.compileSdkVersion from build.gradle, google_apis variant (not google_apis_playstore)Android_Emulator (must match config exactly)Detect machine architecture:
Run: uname -m
arm64 (Apple Silicon): expected ABI is arm64-v8ax86_64 (Intel): expected ABI is x86_64Cross-check the emulator ABI (if emulator is running):
Run: adb shell getprop ro.product.cpu.abi
Check for ambient CI variable:
Run: echo "CI=${CI:-<unset>}"
This is critical: e2e/mobile/detox.config.js uses CI to choose the Android ABI (x86_64 when CI is set, arm64-v8a otherwise). If CI is inherited from a parent process, IDE, or wrapper shell, local Apple Silicon builds will silently produce x86_64 APKs that fail on an arm64-v8a emulator.
arm64 and CI is set: warn the user explicitly. Explain that the Android build and test commands in Phase 4 and 5 will be prefixed with CI= (unset) to force the correct ABI. If CI=1 is in their ~/.zshrc, recommend removing it or scoping it only to CI scripts.x86_64 and CI is not set: warn that CI=1 is needed for correct ABI. Suggest export CI=1.Also check these Android SDK components are installed:
$ANDROID_HOME/build-tools/ exists$ANDROID_HOME/platform-tools/adb existsIf missing, guide: Android Studio > Tools > SDK Manager > SDK Tools tab > install Build Tools, Platform Tools.
If the Android emulator is already running, check available storage:
Run: adb shell df -h /data and adb shell du -sh /data/local/tmp
Thresholds:
If space is low, offer these cleanup actions:
adb shell pm uninstall com.ledger.live.detox and adb shell pm uninstall com.ledger.live.detox.testadb shell rm -rf /data/local/tmp/*adb shell pm trim-caches 4GIf the emulator is not yet running, skip this check and run it before the smoke test in Phase 5 instead.
Do not proceed to Phase 4 until all relevant checks pass.
Run sequentially (check exit codes between each step):
pnpm i --filter="live-mobile..." --filter="ledger-live" --filter="live-cli..." --filter="ledger-live-mobile-e2e-tests"
pnpm build:llm:deps
pnpm build:cli
iOS (if selected in Phase 0) -- uses debug build:
pnpm mobile pod
pnpm mobile e2e:build -c ios.sim.debug
Android (if selected in Phase 0) -- uses release build:
On Apple Silicon (arm64), explicitly clear CI to ensure the correct ABI:
CI= pnpm mobile e2e:build -c android.emu.release
On Intel (x86_64), set CI=1:
CI=1 pnpm mobile e2e:build -c android.emu.release
Why release for Android? Android debug builds are broken locally due to a known Detox/Espresso reflection bug (
NoSuchFieldException: eventInjector). This is a project-level debug dependency issue, not a machine setup problem. Only release builds work. Release bundles JS into the APK, so no Metro bundler is needed for Android.
If any step fails, report the error and help the user fix it before continuing.
Common build failures:
rm -rf apps/ledger-live-mobile/ios/build then pnpm mobile pod then retrypod install flaky error (ArgumentError - pathname contains null byte): this is a known intermittent issue with CocoaPods in pnpm monorepos. If the first pnpm mobile pod succeeded, avoid forcing another pod regeneration. If it keeps failing, try cd apps/ledger-live-mobile/ios && rm -rf Pods Podfile.lock && bundle exec pod install && cd -..app artifact already exists under apps/ledger-live-mobile/ios/build/Build/Products/, the build likely succeeded even if the terminal did not show a clean exit. Check for the artifact before retrying.cd apps/ledger-live-mobile/android && ./gradlew clean && cd - then retryNODE_OPTIONS="--max-old-space-size=10240"Run a single quick test to validate the full setup. Only test the platform(s) selected in Phase 0.
iOS uses a debug build, which requires the Metro bundler running.
Terminal 1 -- Start the bundler:
pnpm mobile start
Terminal 2 -- Run the smoke test:
cd e2e/mobile && pnpm test:ios:debug userOpensApplication.spec.ts
Android uses a release build. JS is bundled in the APK -- no Metro bundler or port bridging needed.
Make sure the emulator is running (adb devices should list a device), then run:
cd e2e/mobile && pnpm test:android userOpensApplication.spec.ts
If both were selected, start the bundler first (for iOS), run the iOS test, then run the Android test. The Android test does not depend on the bundler.
Report whether each test passed or failed. If it failed, check the error output and help debug.
Common smoke test failures:
NoSuchFieldException: eventInjector (Android debug only): this is a project-level Detox/Espresso dependency mismatch, not a missing SDK or emulator issue. Do not keep troubleshooting the machine. Switch to release configuration (pnpm test:android instead of pnpm test:android:debug).Requested internal only, but not enough space (Android): the emulator's /data partition is full. See "Emulator free space" in Phase 3.Setup vs flow mismatch:
If the app launches and connects to Detox successfully but the test fails on a specific UI element (e.g. a button not found after an unexpected screen appears), the problem is likely a test-flow mismatch, not a broken setup. The smoke test may assume a specific onboarding path that has changed (e.g. a new analytics prompt was added). In this case:
Non-blocking warnings to ignore:
watchman watch-del-all && watchman shutdown-server to clean up, but do not present Watchman warnings as the reason a test failed.Print a final checklist summarizing everything. Only include rows for checks that were actually run (based on platform selection). Mark skipped platforms as "skipped".
## E2E Mobile Setup -- Complete
| Check | Status |
| ---------------------- | ----------------- |
| Xcode & CLI tools | ✅ / ❌ / skipped |
| Ruby | ✅ / ❌ / skipped |
| applesimutils | ✅ / ❌ / skipped |
| Java | ✅ / ❌ / skipped |
| Android SDK | ✅ / ❌ / skipped |
| Docker | ✅ / ❌ |
| Proto / Node / pnpm | ✅ / ❌ |
| Environment variables | ✅ / ❌ |
| iOS Simulator | ✅ / ❌ / skipped |
| Android Emulator | ✅ / ❌ / skipped |
| Dependencies installed | ✅ / ❌ |
| App built | ✅ / ❌ |
| Smoke test | ✅ / ❌ |
If everything passed, confirm the user is ready to run tests with:
You're all set! Run tests from e2e/mobile/:
# iOS (debug -- requires bundler running via `pnpm mobile start`)
pnpm test:ios:debug <testFile.spec.ts>
# Android (release -- no bundler needed)
pnpm test:android <testFile.spec.ts>
# All tests (iOS debug / Android release)
pnpm test:ios:debug
pnpm test:android
Note: Android debug builds (
pnpm test:android:debug) do not work locally due to a known Detox/Espresso bug. Always use the release configuration for Android.
If anything failed, list the remaining issues and offer to help fix them.