[ Documentation ]
Maestro Driver

Maestro Driver

rnx runs Maestro-compatible YAML flows through the rnx maestro CLI, a drop-in for the real maestro CLI. Point it at your existing .maestro/ folder and it runs the flows against the browser simulator, no Mac or device needed.

terminal
rnx maestro # auto-discovers ./.maestro or ./maestro and runs every flow
rnx maestro test <flow-or-dir> # run one flow file, or every *.yaml/*.yml in a dir
rnx maestro init # scaffold a starter .maestro/login.yaml
rnx maestro --list-compat # print the full verb support matrix

Useful flags: --env KEY=VALUE (repeatable), --headed, --record, --preview / --preview-open (upload a recording to a preview link), --slow <ms>. The --format / --output / --device flags are accepted and ignored for maestro command-line compatibility.

There is no programmatic driver class; the CLI is the surface. Run rnx maestro --list-compat for the authoritative, always-current matrix; the summary below is a guide.

Supported steps

Interaction and input:

- tapOn: 'Button Text'
- tapOn: { id: 'my-button' }
- tapOn: { text: 'Submit', index: 1 }
- tapOn: { text: 'Row', childOf: { id: 'list' } }
- tapAtCoords: { x: 100, y: 200 }
- longPressOn: 'Item'
- inputText: 'hello world'
- eraseText: 5
- pressKey: 'Enter'
- dispatchKey: 'Escape'
- hideKeyboard: true
- back: true

Navigation and scrolling:

- swipe: { direction: 'LEFT' }
- scroll: { direction: 'DOWN' }
- scrollTo: { id: 'footer' }
- scrollUntilVisible:
element: 'Target Text'
direction: 'DOWN'
timeout: 10000
- pinch: { scale: 2 }

Assertions and waiting:

- assertVisible: 'Welcome'
- assertVisible: { id: 'header' }
- assertNotVisible: 'Loading'
- assertTreeContains: 'Submit' # rnx extension
- waitFor: { text: 'Ready', timeout: 5000 }
- extendedWaitUntil: { visible: 'Done', timeout: 10000 }
- waitForAnimationToEnd: true
- wait: 2000 # rnx extension: wait ms

Control flow, scripting, and capture:

- repeat:
times: 3
commands:
- tapOn: 'Next'
- waitForAnimationToEnd: true
- runFlow: 'sub-flow.yaml'
- runScript: 'setup.js' # full Maestro JS: http, json(), output, env, console.log
- evalScript: '${output.token = "abc"}'
- copyTextFrom: { id: 'code' } # then use ${maestro.copiedText}
- openLink: 'myapp://profile/42' # dispatched through Linking (react-navigation deep links)
- takeScreenshot: 'home-screen'
- takeScreenshot: { path: 'home.png', withFrame: true } # rnx: framed export
- dumpTree: 5 # rnx extension: dump tree to depth

Conditionals, lifecycle hooks, workspace mode, and ${...} JS-expression interpolation are supported: when: { visible / notVisible / platform / true }, optional: true, label:, onFlowStart / onFlowComplete, and a config.yaml workspace with flows: globs plus includeTags / excludeTags.

launchApp.arguments accepts a JSON object. It is installed before guest app entry and is available through react-native-launch-arguments and NativeModules.SettingsManager.settings. Each later launch replaces it or clears it when arguments is absent. stopApp leaves the guest stopped until launchApp or openLink creates the next runtime.

Partial support

  • +
    clearKeychain: warn-only; rnx has no keychain surface.
  • +
    when.platform: the Maestro runner reports iOS.
  • +
    openLink: dispatched into the app through Linking emulation (deep links work); there is no OS-level Safari fallback.
  • +
    env: seeded from your full shell environment, so ${RNX_*} and the like resolve. A bare ${NAME} that is undefined fails the step loudly rather than substituting "undefined".

Not implemented

These throw an “unsupported” error: travel, setLocation, setAirplaneMode, killApp, faker, addMedia, startRecording / stopRecording (use the --record flag instead), and repeat.while (only repeat.times is supported).