AbsoluteJS

Testing on Emulators and Devices

AbsoluteJS installs the emulators, boots them, and tests your app inside its real WebView on Android emulators, iOS simulators and iPhones. It can install the exact signed build you are about to ship, launch it with the network off, and hand you a report that becomes release evidence.

#Toolchain in one command

You do not need Android Studio. mobile doctor checks everything native development needs, and --fix installs what is missing. bun dev offers the same install the first time it finds the toolchain missing.

BASH
bunx absolute mobile doctor                 # every check, both platforms
bunx absolute mobile doctor android --fix   # install the SDK, emulator and Java 21
bunx absolute mobile doctor ios --fix       # on a Mac: download an iOS Simulator runtime
bunx absolute mobile doctor ios --remote studio-mac   # check a paired Mac
What --fix sets upDetails
Android SDK locationANDROID_HOME or ANDROID_SDK_ROOT when set; otherwise ~/.absolutejs/android-sdk, or %LOCALAPPDATA%\AbsoluteJS\Android\Sdk on Windows and WSL
Command-line toolsGoogle’s pinned release, downloaded and checked against its SHA-256 before it is unpacked
SDK packagesplatform-tools, emulator, Android API 36 and build-tools 36.0.0, after you review the SDK licenses
EmulatorAn AVD named AbsoluteJS_API_36 built from the Google APIs system image for your CPU
JavaJava 21: Temurin through winget on Windows and WSL or Homebrew on macOS, OpenJDK through apt, dnf or pacman on Linux
iOS SimulatorOn a Mac with Xcode, --fix downloads the current iOS Simulator runtime
LinuxThe emulator runs with KVM acceleration. Doctor warns when /dev/kvm is missing or your user cannot open it.
WSLThe Android SDK lives on Windows, where the emulator runs fastest, and WSL drives it through adb.exe. Doctor confirms the bridge works.
macOSAndroid and iOS side by side. iOS tools are found with xcrun and xcodebuild.
Windows and Linux, for iOSAndroid runs locally; iOS runs on a Mac you pair once with absolute mobile pair mac. Doctor checks that Mac with --remote, read-only.

#Emulators and simulators

With mobile configured, bun dev starts your app on an Android emulator and, on a Mac or through a paired one, an iOS simulator, next to the web server. Every target goes through the same steps:

1
Find or boot a target
bun dev finds the AbsoluteJS emulator or a booted simulator, and boots one if none is running, waiting until the OS reports boot completed.
2
Connect it to your dev server
On Android, adb reverse maps the dev server’s port onto the emulator, so the app reaches your machine at localhost. With dev HTTPS on, the target is set up to trust your development certificate.
3
Build only when native code changed
The native project is fingerprinted. When nothing native changed, the installed build is reused and Gradle and Xcode are skipped.
4
Install, launch and stream logs
The app launches with HMR connected, and its native logs stream into your terminal. bun dev prints how long each phase took.

Physical devices use the same loop with --android-device and --ios-device. Development covers them and the Remote Mac.

#Three ways to test

The browser preview is the fastest loop for layout, routes, offline states and Back. It runs your real page in an iOS- or Android-shaped frame, but it is not a WebView, so plugins, permissions, OAuth callbacks and secure storage need a real target. Use all three: the preview while you build, mobile test on the running app, and --release before you ship.

FeatureBrowser previewRunning appRelease
What it runs againstYour page in a browser frameThe debug app on the emulator, simulator or deviceThe signed AAB or IPA you will ship
Native WebView, plugins and permissions
Offline launch proven
Produces certification evidence
How/__absolute/mobile-previewmobile test android|iosmobile test android|ios --release

#Test the running app

With bun dev running, mobile test android drives the app on the emulator through the same debugging protocol Chrome uses. List the routes that matter; each one is opened inside the app and checked.

BASH
# Terminal 1: web plus the app on the emulator
bun dev

# Terminal 2: open each route in the app's real WebView
bunx absolute mobile test android --route / --route /account --route /orders/42
The app is attached over Chrome DevTools, in its own WebView, not a desktop browser
Each --route is opened and must render text, with the request reaching your dev server’s origin and path
The page’s HMR client must be connected and identify itself as the Capacitor Android target
A page showing the AbsoluteJS error overlay fails the check
With --wait-for-hmr, the run waits for you to save an edit and reports the server and client time to apply it

On iOS, mobile test ios launches the installed app on the booted simulator, waits for it to connect to your dev server and takes a screenshot. The simulator opens mobile.entry, so iOS does not take --route. --wait-for-hmr works on both:

BASH
bunx absolute mobile test android --wait-for-hmr
bunx absolute mobile test ios --wait-for-hmr

To test a physical iPhone, start bun dev on it and pass the same device to the test. It relaunches the app and confirms it reconnects to your HTTPS dev server.

BASH
bunx absolute dev --ios-device "Test iPhone"
bunx absolute mobile test ios --device "Test iPhone" --report
Expo apps
Testing the running app is available for Capacitor apps. Expo apps use release testing, below, which works for both engines as long as mobile.entry is a web route. Expo has the rest.

#Test the exact release

--release tests the signed App Bundle that mobile build android produced, not a debug build. It proves the app installs and starts from what is inside it, with no network.

BASH
bunx absolute mobile build android
bunx absolute mobile test android \
  --release .absolutejs/mobile/releases/android/<release-id> \
  --report
1
Verify the release
The release must match mobile.appId and the configured engine, and its recorded SHA-256 must still match the file.
2
Pick an emulator
Uses a running emulator, or starts AbsoluteJS_API_36 and waits up to 180 seconds for it to boot.
3
Install the AAB the way the store does
Bundletool turns that exact AAB into a universal APK set and installs it. The installed versionCode must match the release. Bundletool is a pinned, checksum-verified download, fetched after you agree or with --yes.
4
Launch twice with no network
Wi-Fi and mobile data are switched off. The app is cold-launched, must render its embedded content, then is stopped and launched again.
5
Restore the emulator
Wi-Fi and mobile data go back to how they were, even when the run fails.
bunx absolute mobile test android --release <release-dir>
$ bunx absolute mobile test android --release <release-dir>
✓ Installed immutable capacitor release <release-id> with Bundletool in <time>. ✓ Embedded web content booted offline in <time> and relaunched in <time>.

#iOS: simulator, iPhone, TestFlight

iOS release testing runs at three levels, each closer to what your users install. Each launches the app twice and checks it renders its embedded content. On an iPhone, the test asks you to turn on Airplane Mode and turn off Wi-Fi first; --yes confirms you have. From Windows or Linux, add --remote and the run happens on your paired Mac.

BASH
# Simulator, on this Mac or a paired one
bunx absolute mobile test ios --release <release-dir> --report

# A registered iPhone, from the same archive
bunx absolute mobile build ios --registered-device-artifact
bunx absolute mobile test ios --release <release-dir> --device <udid> --report

# The TestFlight build Apple delivered to that iPhone
bunx absolute mobile test ios --release <release-dir> --device <udid> --testflight --report
LevelWhat is installedEvidence
SimulatorA Release build from the same project and version, run in the iOS Simulatorsimulator
Registered iPhone (--device)The IPA exported from the same archive with --registered-device-artifactdevice
TestFlight (--device --testflight)The build Apple processed and TestFlight installed on the iPhonestore

#Reports and artifacts

Every test prints its result and exits non-zero on failure. Add --report to keep a record:

Reportreport.json and report.md, written to .absolutejs/mobile/test-reports/<platform>-<timestamp>, or the directory you pass to --report.
Automated checksPass or fail for each automated check, with timings, the release ID, size and SHA-256 for release runs, and the host, Bun, AbsoluteJS, adb or Xcode versions.
Manual checklistStartup timing, safe areas, rotation with the keyboard open, offline and reconnect, system bars, navigation and device features, each NOT_RUN until you mark it PASS, FAIL or SKIPPED.
ScreenshotA screenshot of the app on the target, such as android-emulator.png, android-release.png or ios-simulator.png.
Failure diagnosticsOn failure, a JSON diagnostic and, when the app was attached, a screenshot, in .absolutejs/mobile/test-artifacts (or --artifacts). The error message names the file.
PrivacyReports stay on your machine. Tokens, cookies, passwords, query strings and coordinates are redacted before they are written.

#From report to certification

A release report is evidence for mobile certify, which binds it to that exact release. An Android release report counts as installed; iOS reports count as simulator, device or store, by the level above. Publishing checks the certification your release policy requires.

BASH
bunx absolute mobile certify <release-dir> \
  --evidence .absolutejs/mobile/test-reports/android-<timestamp> \
  --require installed

Release covers certification policies and publishing.

#In CI

Release tests run unattended: --yes approves the Bundletool download, --json prints a machine-readable result, and the exit code fails the job. absolute mobile ci github generates a workflow that builds, tests and certifies for you; Release walks through it.

BASH
bunx absolute mobile test android --release <release-dir> --yes --json --report

#Flags

FlagApplies toWhat it does
--route <path>Android, developmentA route to check; repeat it for more. Defaults to mobile.entry.
--wait-for-hmrAndroid and iOS, developmentWait for a saved edit to reach the app and report how long it took
--port <n> [--https]DevelopmentThe dev server to use when more than one is running for the project
--timeout <ms>DevelopmentHow long each check may take. Default 30000.
--serial <id>AndroidThe adb target. Defaults to the first ready emulator.
--udid <id>iOSThe booted simulator to use
--device <id>iOSA physical iPhone: the one running bun dev --ios-device, or the one to install a release on
--testflightiOS releaseTest the TestFlight build installed on --device
--remote <name>iOSRun on a paired Mac: release runs, or a device session started through it
--release <dir>Android and iOSTest an installed release: its directory or its release.json
--report [dir]Android and iOSWrite report.json, report.md and a screenshot
--artifacts <dir>Android and iOSWhere failure diagnostics go; must be inside the project
--yesRelease runsApprove the Bundletool download, or confirm an iPhone is offline
--jsonAndroid and iOSPrint the result as JSON; progress goes to stderr

Every absolute mobile command is in the CLI reference.

#Troubleshooting

No running AbsoluteJS dev server was found for this projectThe test attaches to the app bun dev started. Start bun dev, wait until the target reports it is ready, then run the test again.
Multiple dev servers are running for this projectMore than one bun dev is running in this project. Choose one with --port.
No ready Android emulator was foundNo emulator has finished booting. Let bun dev start one, or pass --serial for a connected device.
Android Debug Bridge is unavailableThe SDK is missing or incomplete. Run absolute mobile doctor android --fix.
Could not attach to a debuggable WebViewThe app is not open, or it is a release build, which cannot be inspected. Open the debug app that bun dev installed.
Loaded with the AbsoluteJS error overlay visibleThe page threw while rendering. The failure screenshot shows the overlay and the diagnostic JSON has the console output.
Requires an Android emulatorRelease acceptance switches the network off, which only an emulator allows. Drop --serial or point it at an emulator.
Release app ID does not match mobile.appIdThe release was built before mobile.appId or the engine changed. Build it again.
This release has no same-archive registered-device IPABuild again with absolute mobile build ios --registered-device-artifact to export an IPA for registered devices from the same archive.
The selected physical iOS device is unavailablePair the iPhone in Xcode, trust this Mac, unlock the phone and turn on Developer Mode.
Physical iOS acceptance requires dev.https: trueTesting a physical iPhone needs dev.https: true in absolute.config.ts, so the report shows the app trusted your dev server.
iOS release acceptance requires macOS or a paired Remote MaciOS testing runs on macOS. On Windows or Linux, pair a Mac with absolute mobile pair mac and use --remote.