Run the same five e2e tests on a hosted iOS simulator and Android emulator with Limrun. This repository includes a SwiftUI app, a Jetpack Compose app, and their shared test suite. Limrun builds both apps remotely, so you need no local Xcode, Gradle, simulator, or emulator. The tests use locators and need no AI key.
Prerequisites
- Node.js 22.22.3+, 24.8+, or 26+, with npm.
- A Limrun account and an API key that can create and control iOS, Android, Xcode, and Gradle instances and manage assets. Builds and devices use your account's credits or plan minutes.
- For Android, Android SDK Platform-Tools
with
adbon yourPATH. Check withadb version. - Git and
tar. The shell commands below use Bash or Zsh.
Build and run
-
Clone the example and install its pinned dependencies:
Terminal git clone https://github.com/limrun-inc/testerarmy-e2e-limrun.git cd testerarmy-e2e-limrun npm ci -
Set your API key in the current terminal:
Terminal export LIMRUN_API_KEY='your-limrun-api-key'The build scripts and test provider use this same key.
-
Build both apps on Limrun and download them into
build/:Terminal npm run buildThe build scripts upload temporary assets that expire after 24 hours. Each build sandbox shuts down after one minute without activity.
-
Run the suite with video recording:
Terminal npm test -- --videoExpect five passing tests per platform. The provider creates and installs each target's device, reuses it for that target's tests, and releases it when the run exits. Abandoned devices have a one-hour lifetime limit. Reports, screenshots, and videos are saved under
.e2e/.
To build and test just one platform:
npm run build:ios
npm test -- --target ios --videonpm run build:android
npm test -- --target android --videoWhat the tests cover
Both apps show the same greeting form. tests/greeting.e2e.ts checks these flows on both platforms:
| Flow | Expected result |
|---|---|
| Open the app | The heading, name field, and submit button appear. |
| Correct an empty submission | An error appears, then a valid name replaces it with a greeting. |
| Enter a name with surrounding spaces | The greeting trims the spaces. |
| Submit a second name | The new greeting replaces the previous one. |
| Restart the app | The form resets and an empty submission requires a name again. |
The tests select controls by their shared name and greet test IDs.
For example:
import { expect } from 'e2e';
import { test } from '@e2e-dev/mobile';
test('greets the entered name', async ({ app, screen }) => {
await app.open();
await screen.getByTestId('name').fill('Ada');
await screen.getByTestId('greet').click();
await expect(screen.getByText('Hello, Ada!', { exact: true })).toBeVisible();
});The suite captures the successful greeting on both hosted devices:

Test your own app
In e2e.config.ts, change each target's app.bundleId and
app.appPath to match your builds. iOS needs a simulator .app; Android
needs an APK. You can also set GREETING_IOS_APP and GREETING_ANDROID_APP
to override the artifact paths while keeping these sample apps' bundle IDs.
Replace the greeting assertions with your app's flows. Use test IDs or accessible names that both platforms expose. The sample submits by tapping the button, so it does not depend on keyboard Enter support. Restarting preserves persisted app data; these sample apps store the form in memory.
See the e2e Limrun integration guide for provider options and the Limrun documentation for remote builds.
Run in GitHub Actions
The repository checks TypeScript on pushes and pull requests. To run the
hosted devices from your fork, add a repository secret named
LIMRUN_API_KEY, then run the Mobile tests workflow from the Actions
tab. It builds both apps on Limrun, runs the tests on an Ubuntu runner, and
uploads the test reports and recordings. This workflow uses your Limrun
account's credits or plan minutes.
Maintenance and license
Last checked on October 28, 2026 with e2e 0.21.3, mobile 0.12.4, the Limrun provider 0.2.2, Limrun SDK 0.66.0, and Limrun CLI 0.48.0. All ten tests passed on hosted iOS and Android devices with video recording.
The npm overrides select patched Undici and Zod releases while the upstream packages pin older versions.
Limrun maintains this example. Open an issue
for a broken setup or test. Before submitting a change, run
npm run typecheck and the affected platform's suite.
The apps and tests are adapted from TesterArmy's examples. Code is licensed under Apache-2.0; see NOTICE for attribution and the bundled font directories for their licenses.