Skip to content

Mobile Test API

Every mobile test receives an OrbitDevice instance (the orbit argument). All methods are async. This is the complete category map:

CategoryMethods
App lifecyclelaunchApp, stopApp, installApp, uninstallApp, clearAppData, isAppInstalled
Gesturestap, longPress, swipe, scrollDown, scrollUp
Text & keystypeText, clearText, pressKey
UI lookuptapById, tapByText, tapByDescription, hasText, hasId
WaitswaitForId, waitForText, waitForDescription, waitForGoneId, waitForGoneText
Device statewakeUp, sleepScreen, isScreenOn, getScreenSize, getCurrentActivity
Evidencescreenshot, saveScreenshot, getLogcat, saveLogcat
await orbit.installApp(); // installs the configured APK
await orbit.launchApp("com.example.myapp", "com.example.myapp.MainActivity");
await orbit.stopApp("com.example.myapp");
await orbit.clearAppData("com.example.myapp"); // factory-fresh app state
await orbit.uninstallApp("com.example.myapp");
if (await orbit.isAppInstalled("com.example.myapp")) {
// ...
}

clearAppData is the mobile equivalent of OrbitTest’s clean browser profile: it resets the app to first-launch state, which is how you make tests repeatable on a shared device. Keep package and activity names in config or one helper file, not copy-pasted across twenty tests.

Android elements are matched three ways, and choosing well is most of the craft:

SelectorExampleChoose it when
Resource IDtapById(“login_button”)Best default: stable across translations and copy changes.
Visible texttapByText(“Sign In”)Text is stable and unique; also documents intent nicely.
Content descriptiontapByDescription(“Open menu”)Icon buttons with accessibility labels and no text.
await orbit.tapById("login_button");
await orbit.tapByText("Sign In");
await orbit.tapByDescription("Open navigation drawer");
// Raw gestures when there is no element to target
await orbit.tap(540, 1200);
await orbit.longPress(540, 1200);
await orbit.swipe(540, 1600, 540, 400); // swipe up
await orbit.scrollDown();
await orbit.scrollUp();

If text is translated or repeated on screen, prefer resource IDs. Studio’s Inspector shows you every element’s ID, text, and description, use it instead of guessing.

await orbit.tapById("username_field");
await orbit.typeText("testuser@example.com");
await orbit.clearText();
await orbit.pressKey("KEYCODE_BACK");

Waits follow the same rule as browser tests: wait for state, never for time. The “gone” variants wait for something to disappear, ideal for spinners:

await orbit.waitForId("home_screen", 10000);
await orbit.waitForText("Welcome", 10000);
await orbit.waitForDescription("Profile photo", 5000);
await orbit.waitForGoneId("loading_spinner", 15000);
await orbit.waitForGoneText("Loading...", 15000);

Timeouts are in milliseconds.

await orbit.wakeUp(); // wake and prepare the screen
await orbit.sleepScreen();
const on = await orbit.isScreenOn();
const { width, height } = await orbit.getScreenSize();
const activity = await orbit.getCurrentActivity();

getScreenSize() is how you make raw-coordinate gestures portable across devices, compute positions as fractions of the real screen instead of hard-coding pixels. getCurrentActivity() makes a great assertion that navigation really happened.

const png = await orbit.screenshot(); // in-memory
await orbit.saveScreenshot("evidence/step3.png"); // to disk
const log = await orbit.getLogcat();
await orbit.saveLogcat("evidence/failure.log");

Manual evidence capture, on top of the automatic on-failure captures from config.

Mobile assertions complete the picture: await expect(orbit).toHaveText("Welcome"), toHaveId("home_screen"), and toMatchScreenshot() for visual comparison.

Open Studio’s Inspector and click the element, the ID, text, and description are all displayed, with copyable tap code. Without Studio, adb shell uiautomator dump produces the same XML, just less comfortably.

What if the same text appears twice on screen?

Section titled “What if the same text appears twice on screen?”

Switch to the resource ID, or to the content description. Visible-text matching is the readable default, not the only tool.

Raw tap(x, y) coordinates are device-specific. Derive them from getScreenSize() proportions when you must use coordinates, and prefer ID/text taps whenever an element exists.

  • Mobile Testing — Android automation with ADB and UIAutomator through @orbittest/mobile: setup, configuration, hybrid tests, and evidence.
  • Quick Start — From new project to first passing mobile test: connect a device, write a smoke test, run it, and review the video evidence.
  • Features — A tour of Studio: OrbiStream live mirror, UI Inspector, logcat filters, the test runner with evidence reports, and the built-in IDE.
  • Visual Automation — Test canvas, WebGL, and pixel-rendered UIs with coordinate actions, snapshots, pixel assertions, and color search.