feat(testmu): add @e2e-dev/testmu device provider

Merged
AM
9d ago
+1849-7

What and why

This adds @e2e-dev/testmu, a DeviceProvider that runs mobile targets on TestMu AI (formerly LambdaTest) Android emulators, iOS simulators and real devices. It works through agent-device's TestMu AI plugin, @agent-device/testmu (callstack/agent-device#3118).

import { mobile } from '@e2e-dev/mobile';
import { testmu } from '@e2e-dev/testmu';

engine: mobile({
  platform: 'android',
  device: testmu({ device: 'Galaxy S22 Ultra 5G', osVersion: '14', app: 'lt://APP-id' }),
}),
  • Shape: the package follows @e2e-dev/limrun.
    • agent-device and @agent-device/testmu are pinned dependencies at @e2e-dev/mobile's version, and acquire checks request.agentDeviceVersion.
    • Each lease starts its own agent-device daemon in a child process. The process gets a temp state dir and its own agent-device home, with the bundled plugin registered there, so users never run plugins add. Its environment carries LT_USERNAME/LT_ACCESS_KEY, so the credentials never touch the runner's process.env.
    • Release runs daemon stop --clean and removes the lease's dir.
  • Leases: each lease is allocated with retainOnClose, so e2e's session close between test files keeps the TestMu AI session. A 20 s heartbeat holds a 60 s lease TTL.
  • Options:
    • device, osVersion and app (lt://, URL or local path) select the target, and deviceType: 'real' picks real devices instead of emulators/simulators.
    • project, build and sessionName name the session on the dashboard; the session name defaults to e2e-<run id>-<target>-<slot>.
    • Device options: orientation, geoLocation, timezone, language, locale and appiumVersion.
    • Unknown options fail at config load.
  • Video: record() links TestMu AI's recording of the session.
  • Limits:
    • A session is billed from lease to release.
    • An abandoned session ends after TestMu AI's 120 s idle timeout.
    • Device settings, alerts, logs and port reverse are not available through agent-device's WebDriver runtime.

Split out at review: the iOS XCUIElementType role fix is #1133, and TestMu AI hosted browsers (testmuBrowsers()) will come as a follow-up PR.

Verified

Ran it locally: yes

  • pnpm check passes, including plugins:check. Unit tests: @e2e-dev/testmu 65, @e2e-dev/mobile 262, @e2e-dev/limrun 14.
  • I ran it end to end against a local fake TestMu AI hub with real agent-device 0.21.25. Allocation creates the session, a worker can snapshot, release deletes the session, and no daemon or temp dir is left behind.
  • Live on TestMu AI production, with earlier revisions of this package: Android emulator with video: 'on', iOS simulator, real Pixel 6 and real iPhone. The plugin itself was validated live at callstack/agent-device#3118's head. This child-process shape still needs a live run.

Checklist

  • Changeset added (pnpm changeset) for any change to a published package, or the change is testbed, docs, or CI only.
  • Breaking change: n/a, not breaking.
  • Docs updated in the same PR: docs/integrations/testmu.mdx, and skills/e2e/ for setup.
  • Contract change: n/a
  • Engine contract change: n/a

🤖 Generated with Claude Code