Open Source · Apache 2.0

Test what users see,
not what developers write.

OrbitTest is an intent-first end-to-end testing platform built on Chrome DevTools Protocol. Write tests using visible labels, roles, and text — not CSS selectors or XPath.

Get Started View on GitHub ⬇ Download Studio
CLI / npm

OrbitTest

Intent-first browser automation built on Chrome DevTools Protocol. Runs in Node.js, integrates with any CI pipeline.

npm install orbittest Node ≥ 18 Apache 2.0
Windows Desktop

Orbittest Studio

Android QA desktop IDE — live device mirror, UI inspector, logcat viewer, and mobile test runner in one app.

Windows 10+ Android 8.0+ v1.0.0
0+
Browser Actions
0
CLI Commands
0
Report Formats
Android 8+
Mobile Support
Apache 2
Open Source
Orbittest Studio

Everything you need
in one desktop app.

A professional Android QA workspace — live device mirror, UI inspector, Monaco IDE, logcat viewer, and mobile test runner bundled in a single native Windows app.

Orbittest Studio — Devices panel

Connected Android devices appear instantly. See status, serial, OS version, and resolution — click Install to deploy the Companion app in one step.

Orbittest Studio — Monaco editor and UI Inspector

VS Code–style Monaco editor with full IntelliSense alongside a live UIAutomator hierarchy — click any node to inspect bounds, copy its locator, or generate tap code.

Orbittest Studio — live device mirror

Real-time device screen stream via OrbiStream. Switch between Auto, Low Latency, and High Quality modes. The Action Log tracks every test event live.

Orbittest Studio — Device Logs modal

Filter Android logcat by package, severity, time range, output limit, and keyword patterns. Download the full log or copy it to clipboard instantly.

OrbitTest Companion running on Android device

OrbitTest Companion runs on your Android device. It bridges Studio over ADB — reporting session status, battery level, port, uptime, and device diagnostics in real time.

Overview

OrbitTest lets you write browser tests using what users see — visible labels, roles, and text — rather than CSS selectors or XPath. It handles browser lifecycle, parallelism, retries, trace capture, structured failure reporting, and CI integration out of the box.

Feature Status

FeatureStatus
UI automationStable
Test lifecycle hooksStable
Intent-based locator engineStable
Text readers (text, visibleText, domText)Stable
Browser storage & session managementStable
Alerts, notifications, window/tab managementStable
Frames and Shadow DOM traversalStable
HTML/JSON/JUnit reportsStable
CI/CD mode (sharding, fail-fast, annotations)Stable
Step trace & trace timelineStable
Smart Report (browser evidence collection)Stable
UI local dashboardStable
Forge test recorderStable
Android mobile provider (@orbittest/mobile)Phase 1
Visual automation (canvas, WebGL, pixel checks)Experimental
API testingPlanned
🎯

Intent-First

Interact using visible text, labels, and roles — exactly what users see. No CSS selectors required for common flows.

🚀

Zero Config to Start

Run orbittest init and you're writing tests. No framework config needed for basic use.

📊

Rich Reports

HTML, JSON, and JUnit output. Inline screenshots, trace timelines, and Smart browser evidence on failure.

🔄

CI-Ready

Sharding, retries, fail-fast, flaky detection, and GitHub Actions annotations built in.

🔍

Forge Recorder

Record interactions in a live browser and get a ready-to-run OrbitTest script instantly.

📱

Mobile Testing

Android automation via @orbittest/mobile. ADB + UIAutomator, no Appium required.

Installation

Install as a project dependency:

npm install orbittest

Or install globally:

npm install -g orbittest
ℹ️

Requirements: Node.js 18 or later. A Chromium-based browser is required at runtime. OrbitTest will use system Chrome by default, or specify a path via ORBITTEST_CHROME_PATH.

Quick Start

Initialize a new project:

$ orbittest init

This creates:

orbittest.config.js
tests/
  example.test.js
reports/

Write a test:

const { test, expect } = require('orbittest');

test('Login flow', async (orbit) => {
  await orbit.open('https://example.com');
  await orbit.click('Login');
  await orbit.type('Email', 'user@example.com');
  await orbit.type('Password', 'secret');

  expect(await orbit.hasText('Dashboard')).toBe(true);
});

Run it:

$ orbittest run

Passed: 1
Failed: 0
Report: reports/runs/<run-id>/report.html

No CSS selectors. No XPath. No framework configuration needed for basic use.

Configuration

OrbitTest reads orbittest.config.js from the project root. All fields are optional.

module.exports = {
  // Test discovery
  testDir: 'tests',
  testMatch: ['**/*.test.js', '**/*.spec.js'],

  // Parallelism
  workers: 1,
  maxWorkers: 4,

  // Retry policy
  retries: 0,

  // Timeouts (ms)
  testTimeout: 30000,
  actionTimeout: 0,

  // Browser display: "auto" | "show" | "hide"
  browser: { display: 'auto' },

  // CI/CD mode
  ci: {
    enabled: Boolean(process.env.CI),
    retries: 1,
    trace: 'on-failure',
    screenshot: 'on-failure',
    failFast: false,
    shard: process.env.ORBITTEST_SHARD || null,
    githubAnnotations: Boolean(process.env.GITHUB_ACTIONS)
  },

  // Smart Report
  smartReport: false,
};

Writing Tests

Basic test

const { test, expect } = require('orbittest');

test('Home page loads', async (orbit) => {
  await orbit.open('https://example.com');
  expect(await orbit.hasText('Example Domain')).toBe(true);
});

Test options

test('Slow flow', { retries: 2, timeout: 60000 }, async (orbit) => {
  await orbit.open('https://example.com');
});

Lifecycle Hooks

const { beforeAll, afterAll, beforeEach, afterEach, test } = require('orbittest');

beforeAll(async (runInfo) => {
  console.log(`Run started: ${runInfo.runId}`);
});

beforeEach(async (orbit, testInfo) => {
  console.log(`Starting: ${testInfo.name}`);
});

afterEach(async (orbit, testInfo) => {
  if (testInfo.status === 'failed') {
    await orbit.screenshot(`reports/${testInfo.name}.png`);
  }
});

testInfo fields: name, file, index, attempt, retry, retries, timeout, status, startedAt, endedAt, durationMs, error, artifacts.

Locators

OrbitTest is intent-first: most actions accept visible text and resolve the target automatically. Use explicit locators when text resolution is ambiguous.

LocatorUsage
Text stringawait orbit.click("Login")
CSS selectorawait orbit.click(orbit.css("#login-btn"))
XPathawait orbit.click(orbit.xpath("//button[text()='Login']"))
Roleawait orbit.click(orbit.getByRole("button", "Login"))
Attributeawait orbit.click(orbit.getByAttribute("data-testid", "submit"))
Object literalawait orbit.click({ css: "#login" })

Working with Elements

Text readers

HelperReturnsHidden content
orbit.text(locator)DOM text, form values, ARIA label, title, altMay include ARIA sources
orbit.visibleText(locator)Rendered visible text onlyExcluded
orbit.domText(locator)Full DOM text from the element treeIncluded

Collections

const buttons = await orbit.all(orbit.css('button'));

for (const button of buttons) {
  if (button.visible) {
    await orbit.click(button);
  }
}

Frames & Shadow DOM

iFrames

const billing = await orbit.frame(orbit.getByAttribute('title', 'Billing'));
await billing.type('Email', 'team@example.test');
await billing.click('Save billing');
expect(await billing.exists('Saved')).toBe(true);

Shadow DOM

const profile = await orbit.shadow(orbit.css('user-profile'));
await profile.type('Email', 'team@example.test');
await profile.click('Save');

Browser Storage & Sessions

// Cookies
await orbit.storage.setCookie({ name: 'session', value: 'abc123' });
const cookies = await orbit.storage.cookies();
await orbit.storage.clearCookies();

// localStorage
await orbit.storage.setLocal('token', 'abc123');
const token = await orbit.storage.getLocal('token');

// Save/restore login state
await orbit.storage.saveSession('auth/session.json');
await orbit.storage.loadSession('auth/session.json');

Alerts, Notifications & Windows

// Dialogs
expect(await orbit.alertText()).toBe('hello');
await orbit.acceptAlert();
await orbit.dismissAlert();

// Notifications
await orbit.grantNotifications();

// Windows / Tabs
await orbit.click('Open report');
const popup = await orbit.waitForWindow({ switchTo: true });
await orbit.switchToWindow(0);
await orbit.closeWindow(popup.id);

Browser Actions API

CategoryMethodDescription
navorbit.open(url)Navigate to a URL
interactorbit.click(target)Click an element by text/locator
interactorbit.doubleClick(target)Double-click
interactorbit.rightClick(target)Right-click
interactorbit.hover(target)Hover over element
interactorbit.type(label, text)Type into an input matched by label
readorbit.hasText(text)Assert text presence on page
readorbit.title()Get page title
readorbit.url()Get current URL
readorbit.text(locator)Read element text
readorbit.visibleText(locator)Read rendered visible text
readorbit.exists(locator)Check element existence
readorbit.all(locator)Get all matching elements
waitorbit.waitForText(text)Wait for text to appear on page
waitorbit.waitFor(locator)Wait for element to exist
waitorbit.wait(ms)Fixed delay (use sparingly)
advancedorbit.evaluate(fn)Execute JS in the browser context
advancedorbit.screenshot(path)Capture a screenshot
advancedorbit.frame(locator)Scope to an iframe
advancedorbit.shadow(locator)Scope to a shadow root
advancedorbit.pageState()Get { title, url, … }

CLI Reference

CommandDescription
orbittest run [files]Run tests
orbittest initInitialize a new project
orbittest uiOpen the local UI dashboard
orbittest forge [url]Open the Forge test recorder
orbittest clean-reportsRemove old report runs
orbittest devicesList connected Android devices
orbittest doctorCheck environment and dependencies

orbittest run flags

FlagDescription
--workers <n>Number of parallel workers
--retries <n>Retry count per test
--timeout <ms>Test timeout in milliseconds
--env <name>Activate a named environment
--ciEnable CI mode
--fail-fastStop after first failure
--max-failures <n>Stop after N failures
--shard <n/total>Run a shard, e.g. 1/4
--github-annotationsEmit GitHub Actions annotations on failure
--traceCapture step-by-step trace
--smart-reportCapture browser evidence for failure diagnosis
--stepLive debugging with Orbit Inspector
--show-browserForce visible browser
--hide-browserForce headless browser
--verbosePrint internal browser/action logs

Environment Variables

VariableDescription
ORBITTEST_CHROME_PATHPath to a custom Chrome/Chromium executable
ORBITTEST_SHARDShard assignment in <n>/<total> format
CIStandard CI flag — enables headless browser and CI mode defaults
GITHUB_ACTIONSEnables GitHub annotation output

Reports & Diagnostics

Every run produces:

reports/
  latest.html
  latest.json
  latest-summary.json
  latest-junit.xml
  runs/
    <run-id>/
      report.html
      report.json
      junit.xml
      artifacts/
        screenshots/
        traces/

Trace Mode

Captures a step-by-step timeline for every test. The HTML report includes status, duration, URL, title, and screenshot links per step.

$ orbittest run tests/login.test.js --trace

Smart Report

Collects console errors, JS exceptions, failed network requests, slow requests, and navigation events. Detects clear application failures even without explicit assertions.

$ orbittest run tests/login.test.js --smart-report

Step Mode (Live Debugging)

$ orbittest run tests/login.test.js --step

Pauses before each orbit.* action. Click actions display a red dot at the exact coordinate. Trace is written automatically.

CI/CD Integration

Sharding

$ orbittest run --ci --shard 1/4
$ orbittest run --ci --shard 2/4
$ orbittest run --ci --shard 3/4
$ orbittest run --ci --shard 4/4

GitHub Actions

name: e2e

on:
  pull_request:
  push:
    branches: [main]

jobs:
  orbittest:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        include:
          - shard: 1/2
          - shard: 2/2
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 20 }
      - run: npm ci
      - run: npx orbittest run --ci --workers 2 --shard ${{ matrix.shard }} --github-annotations
      - uses: actions/upload-artifact@v4
        if: always()
        with:
          name: orbittest-report
          path: reports/

Mobile Testing

ℹ️

@orbittest/mobile uses ADB and UIAutomator directly. No Appium, WebdriverIO, Detox, Maestro, or Playwright mobile required.

$ npm install orbittest @orbittest/mobile
// orbittest.config.js
module.exports = {
  use: {
    mobile: {
      provider: '@orbittest/mobile',
      platform: 'android',
      adbPath: process.env.ADB_PATH || 'adb',
      deviceSerial: process.env.DEVICE_SERIAL,
      appPackage: 'com.myapp',
      screenshotOnFailure: true,
    }
  }
};

Visual Automation

⚠️

Experimental. The API is stable but coverage of edge cases may be limited.

// Pixel checks
await orbit.visual.snapshot('reports/state.png');
await orbit.visual.expectPixel({ x: 30, y: 30 }, '#ff0000', { tolerance: 5 });
await orbit.visual.waitForStable();

// Coordinate actions
await orbit.mouse.click(680, 450);
await orbit.mouse.drag({ x: 680, y: 450 }, { x: 760, y: 360 });
await orbit.mouse.wheel(0, -500);

Orbittest Studio

Android QA desktop IDE — live device mirror, UI inspector, logcat viewer, and mobile test runner in one Windows app.

Download Orbittest Studio

v1.0.0 · Windows 10+ x64 · MIT License

📦 Windows Installer (.exe) 🤖 Android 8.0+ (API 26+) 🔌 USB + ADB
⬇ Download for Windows
⚠️

Windows SmartScreen: The installer is not yet Authenticode-signed. Click More info → Run anyway. Verify the SHA256 hash before running.

Features

📺

Live Device Mirror

Stream your Android device's screen via the OrbiStream engine. Supports Auto, Low Latency, and High Quality modes.

🔬

UI Inspector

Dump and browse the UIAutomator hierarchy. Click any node to highlight it, copy its locator, or generate tap code.

📋

Device Logs

Capture and filter Android logcat by package, PID, tag, severity, text, regex, or time range.

▶️

Mobile Test Runner

Write and run tests with one click. Live stdout/stderr streams to the Console panel with full artifact output.

📑

Test Reports & Evidence

HTML reports with pass/fail status, action logs, final screenshot, and device recording with frame evidence player.

💻

Built-in IDE

VS Code–style workspace: Monaco editor, file explorer, tabs, integrated terminal, Git, and npm manager.

Installation

Quick Start

Mobile Test API

const { test, expect } = require('orbittest/mobile');

test('login smoke test', async (orbit) => {
  await orbit.wakeUp();
  await orbit.launchApp('com.example.myapp', 'com.example.myapp.MainActivity');

  await orbit.waitForId('username_field', 10000);
  await orbit.tapById('username_field');
  await orbit.typeText('testuser@example.com');

  await orbit.tapByText('Sign In');
  await orbit.waitForText('Welcome', 10000);
  expect(await orbit.hasText('Welcome')).toBe(true);
});

Key API Methods

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

Run Configurations

ConfigurationTraceSmart ReportVideo Recording
Quick RunOffOnAlways
Trace RunOnOnAlways
Evidence RunOnOnAlways
Minimal RunOffOffOff

Troubleshooting

Device not appearing

Run adb devices to confirm ADB is working and the device shows as device (not unauthorized). Try a different USB cable — some cables are charge-only. If ADB is not on PATH, set the ADB binary path in Studio Settings.

Device shows as "unauthorized"

Unlock the phone and tap Allow on the "Allow USB debugging?" dialog. If the prompt doesn't appear, unplug and replug.

Companion install blocked by Android

Go to Developer Options → Install via USB and enable it, then retry Install from Studio. Uninstall any previous version first.

Live mirror shows black screen

OrbiStream uses Android's MediaProjection API — approve the screen-capture permission dialog on the phone. If the stream stays black, tap Ping in the Devices panel to confirm the companion bridge is alive.

Installer Integrity

Verify the downloaded installer before running it.

SHA256 — v1.0.0
183CF4BD94647F58CF64F0A482EA4734120DA559E131C9D1C7E5056E2A00ECD6
# Verify with PowerShell
Get-FileHash .\Orbittest-Studio-Setup-1.0.0.exe -Algorithm SHA256

System Requirements

RequirementDetails
OSWindows 10 or later, 64-bit
AndroidAndroid 8.0 (API 26) or later recommended
ADBBundled with Android Studio or standalone platform-tools
USBUSB data cable with USB debugging enabled on device
Optionalffmpeg — enables WebM preview generation in test reports

Release Validation — v1.0.0

CheckResult
Prettier format check✓ Passed
ESLint✓ Passed
TypeScript typecheck✓ Passed
Vitest unit tests✓ 7 files, 32 tests passed
npm high-severity security audit✓ 0 vulnerabilities
Third-party license audit✓ Passed
Windows NSIS installer build✓ Passed
Bundled Companion APK verification✓ Passed

Roadmap

OrbitTest is organized as a small set of Orbit-themed modules. Each has a clear job, and together they move a test from a user-written file to a real Chrome run with reports.

Architecture

Entry Point

🛸 Orbit Shell

Terminal surface. Parses commands, discovers .test.js files, passes the resolved test list to Mission Control.

Public API

⚙️ Orbit Core

Exposes test, expect, and run. Creates the Orbit object. Hides all WebSocket and CDP details.

Orchestrator

🎛️ Mission Control

Registers tests, runs each in a fresh Capsule, tracks pass/fail, captures screenshots, writes JSON and HTML reports.

Isolation

🧪 Orbit Capsule

Each test gets a clean browser profile — no cookies, history, or extensions from other tests.

Interaction

🖱️ Orbit Surface

Resolves human intent to DOM elements using accessible names, labels, and visible text.

Protocol Layer

📡 Orbit Signal

Opens the WebSocket to Chrome's DevTools Protocol port, serializes commands, correlates async responses.

Browser Lifecycle

🚀 Orbit Launchpad

Finds Chrome (system, Puppeteer fallback, or ORBITTEST_CHROME_PATH), creates a temp profile, starts Chrome with remote debugging.

Current Flow

→ Execution Order

Shell → Core → Mission Control → Capsule → Surface → Signal → Launchpad → Chrome

Planned Improvements

Orbit Shell

Orbit Core

Mission Control

Orbit Surface


Contributing

Contributions are welcome. Please review the guidelines before opening a pull request.

🔒

Security: To report a vulnerability, open a private security advisory on GitHub or contact the maintainer directly. Do not file public issues for security reports.

License

OrbitTest is licensed under the Apache License 2.0. Orbittest Studio is licensed under the MIT License.

Copyright 2026 Abhay. See LICENSE, NOTICE, and TRADEMARKS.md.