This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.
Using e2e by TesterArmy
Edit page
Learn how to test your Expo app with e2e, TesterArmy's open source end-to-end testing framework, on an Android Emulator or iOS Simulator.
e2e is TesterArmy's open source end-to-end (E2E) testing framework. It runs tests on an Android Emulator or iOS Simulator through agent-device. A test can combine two kinds of steps:
- Exact steps to find an element with a locator, act on it, and assert the result, like other E2E frameworks.
- Agent steps to describe a goal in plain language and an AI model decides what to tap. e2e records the actions and replays them on later runs without a model call.
This guide shows how to set up e2e in an Expo project and run it on your computer. e2e does not need a TesterArmy account. To run tests on TesterArmy's hosted platform instead, see Using TesterArmy.
3 requirements
3 requirements
1.
e2e requires Node.js 22.12 or later. On Windows, run e2e in Windows Subsystem for Linux (WSL).
2.
Install the Android SDK with an emulator, or Xcode with an iOS Simulator runtime. Run npx agent-device doctor to check your setup.
3.
A ChatGPT Plus or Pro, GitHub Copilot, or SuperGrok subscription, an API key for a model provider, or a local model. Tests that only use exact steps do not need a model.
Run E2E tests with the e2e framework
1
Build and install a release build
Set android.package and ios.bundleIdentifier in your app config. e2e uses these values to open your app.
Create a release build and install it on an emulator or simulator. A release build includes the JavaScript bundle, so tests do not need a running development server.
The Android build writes the APK to android/app/build/outputs/apk/release/app-release.apk. You can use this path to install the build on a new emulator in a later step.
2
Add e2e to your project
In your project directory, run the setup command:
Then, answer the following prompts:
- For the engine, select Mobile (iOS/Android).
- For the model gateway, select the subscription or provider you use for agent steps. Select None to add a model later.
- Keep the default locations for the agent skill and the Model Context Protocol (MCP) server configuration.
- Confirm the file changes and install the dependencies.
The command adds e2e and @e2e-dev/mobile to your development dependencies and a test:e2e script to package.json. It also creates these files:
- e2e.config.ts: The test configuration.
- tests/example.e2e.ts: An example test that opens the iOS Settings app. Delete it after you add your own tests.
- .agents/skills/e2e/: A skill that tells coding agents how to write and run e2e tests. .claude/skills/e2e/ links to it for Claude Code.
- .mcp.json and .cursor/mcp.json: The e2e MCP server configuration for coding agents.
3
Configure your app
Open e2e.config.ts and add a target for each platform. Set app.bundleId to your package name or bundle identifier, and set device in mobile() to the emulator or simulator to use:
For an Android Emulator, use the name that
npx agent-device devicesshows for the running emulator, such asMedium Phone. The Android Virtual Device (AVD) name with underscores, such asMedium_Phone, fails after the emulator boots.
app.appPath names the build to install. e2e does not install it on its own. On a new emulator or simulator, such as on a CI machine, call await device.installApp() at the start of a test to install the build from app.appPath. When you install the app with npx expo run:android --variant release or npx expo run:ios --configuration Release, it is already on the emulator or simulator.
4
Write a test with exact steps
Create tests/home.e2e.ts. Each test starts with app.open(), which launches the app set in app.bundleId. Without it, a test starts on the screen the previous test left open.
In the above example snippet, these tests use the screens from the default Expo template. For your own app, change the text to match your screens. Then, run the tests on both platforms:
e2e boots the configured emulator or simulator if it is not running, runs each test on each target, and writes the results to .e2e/report.json.
5
Add an agent step
An agent step needs a model, such as one from the subscriptions and providers listed in the prerequisites. If you selected a subscription or provider during setup, e2e.config.ts already has a default agent. To use a subscription, sign in and select your provider:
To use an API key, set the environment variable that your provider needs. If you selected None during setup, add a model to e2e.config.ts by following e2e's model setup. To see the model IDs that your subscriptions can use, run npx e2e models.
Then, create tests/agent.e2e.ts with one goal per agent.act() call, followed by an exact assertion:
Run the test:
On the first run, the agent calls the model to decide each action. The output shows the token count. e2e saves the actions in .e2e/cache. On the next run, e2e replays them without a model call and prints Cache 2 replayed for the two targets. When the screen changes, the agent calls the model again.
6
Read the results
When a test fails, the output names the failing locator and links to the files e2e saved for the attempt in .e2e/artifacts. Each failure includes a screenshot and screen.txt, which lists every element e2e found on the screen with its role and text. Use screen.txt to fix a locator.
To record a video of each test, add --video:
For more options, see e2e's debugging guide.
Tips for Expo apps
- Native tabs: The role that Expo Router native tabs report depends on the platform and the simulator runtime. Use
screen.getByText('Explore')to find a tab on both platforms. - Pressable elements: A
Pressablewithout anaccessibilityRolecombines the labels of its children. For example, a row with a chevron icon and a title has the label "Forward, File-based routing". Use{ exact: false }, or setaccessibilityRoleandaccessibilityLabelon thePressable. - Text styles: Tests match the text that the platform reports. With
textTransform: 'uppercase', match the uppercase text, such as "GET STARTED". - Deep links:
device.openLink()opens a link with your app'sscheme. On iOS, the system asks "Open in [app name]?" until the link is approved once on that simulator, so a test must handle both cases:
Use e2e with a coding agent
The e2e skill in .agents/skills/e2e/ tells coding agents such as Claude Code, Codex, and Cursor how to write and run e2e tests. The e2e mcp server lets an agent open the app and check a locator before it adds the locator to a test. For more information, see e2e's coding agents guide.
Run e2e on EAS Workflows
EAS Workflows can run e2e on a macOS worker with an iOS Simulator. The following workflow builds your app, boots a simulator on the worker, installs the app, and runs the tests.
2
4
Run the workflow
To start the workflow, run the following command:
The workflow uploads .e2e/report.json and the failure files in the Artifacts section of the workflow run. To run it on each pull request, add a pull_request trigger.
5
Use agent steps on the worker
Tests with only exact steps need no model.
For agent steps:
- It is recommended to use an API key from your provider instead of a subscription login because the login expires on the worker. e2e can read a subscription login from the
E2E_OAUTH_CREDENTIALSenvironment variable, which holds the contents of your local ~/.config/e2e/oauth.json file. However, e2e does not save refreshed tokens back to the variable. Add an agent for the API key to e2e.ci.config.ts by following e2e's model setup. - The
e2e_iosjob setsenvironment: preview, so it reads variables from thepreviewenvironment. Store the API key there as an EAS environment variable with the visibility set to Secret. npx e2e initadds.e2e/cache/to .gitignore, so the workflow starts without recorded agent steps. To replay them on the worker, remove that line and commit the .e2e/cache directory. See Commit your traces.- A replay needs the recorded elements on the screen. The simulator on the worker can report a different accessibility tree than your own simulator, and then the agent calls the model.
Run e2e on EAS Simulator
EAS Simulator runs Android Emulators and iOS Simulators on EAS infrastructure. The @e2e-dev/eas integration starts an EAS Simulator session for each e2e worker when a run starts. It stops the sessions when the run ends. e2e runs on your computer and drives each remote device through agent-device. The following example runs the tests on a remote iOS Simulator.
EAS Simulator is a limited-access preview. For more information, see the EAS Simulator documentation.
1
Install the EAS Simulator integration
Install @e2e-dev/eas as a development dependency:
Link your project to EAS and check that your account can use EAS Simulator:
eas init sets extra.eas.projectId in your app config. The integration uses this project ID to start sessions.
The integration authenticates with an Expo access token from the EXPO_TOKEN environment variable. It does not use the account that you signed in to with eas login. Create a personal access token to use when you run the tests.
2
Create an iOS Simulator build
EAS installs your app on the remote iOS Simulator from an EAS Build. Create a build with the e2e-ios-simulator profile from Add an iOS Simulator build profile:
Record the build ID from the command output, or find a completed simulator build:
3
Create an e2e configuration for EAS Simulator
Create e2e.eas.config.ts. It reuses e2e.config.ts, including the agent. It replaces the targets with one iOS target that gets its device from EAS Simulator through easSimulators():
Replace <your-eas-project-id> with the extra.eas.projectId value from your app config. EAS installs and launches the build from buildId before each session is ready.
videoTouches: false turns off the touch indicator in video recordings. On a remote iOS Simulator, the indicator takes minutes to draw, so e2e saves no video.
Each session counts toward your EAS Simulator usage. This configuration keeps workers: 1 from e2e.config.ts, so a run uses one session.
4
Run the tests
Replace <your-access-token> with your personal access token and <build-id> with the build ID from step 2. Then, run the tests:
The session is ready after EAS boots the remote iOS Simulator and installs your build. Boot time varies with device capacity. For each session, the output links to the session page on expo.dev. The page shows a recording of the session and each agent-device action, such as a tap.
If the run exits before e2e stops the session, EAS stops it after 10 minutes without activity. A session also has a maximum duration that depends on your plan, so the run must finish before the session reaches it.
Agent steps that you recorded on your own simulator can replay on the remote iOS Simulator without a model call.
Additional resources
Learn about e2e's test API, models, trace cache, and migration guides from Maestro and Detox.