Skip to main content
Translate Maestro flows into momentic-mobile tests while preserving the behavior each flow checks. Both use YAML, but launch behavior, selectors, variables, subflows, and assertions need review rather than a key rename.

Prepare the project

Complete the iOS or Android setup and keep your Maestro files and CI job. Momentic uses a separate CLI and momentic.config.yaml; it does not execute Maestro flow files.
  • Android needs an APK, adb, and ANDROID_HOME or ANDROID_SDK_ROOT, even for remote emulators. Local emulators also need an installed AVD. See Android app setup.
  • iOS needs a simulator .app build, not a device .ipa. Local simulators require macOS, Xcode, and idb. Remote simulators use an uploaded build. See iOS app setup.
  • Momentic supports emulators and simulators, not physical devices. Keep Maestro coverage that requires device hardware or an unsupported OS version.
  • Record the selected flow’s build, initial app state, permissions, test data, assertions, and hooks. Use the same conditions when comparing results.

Before and after

A representative Maestro flow:
checkout.yaml
The Android version force-stops the named package before opening it and keeps the expected text in its visibility checks:
checkout.test.yaml
Replace the package ID and targets with your app’s values. The example assumes the app’s starting state has an empty cart and a guest checkout flow. Add EMAIL to the existing staging environment in momentic.config.yaml. Do not replace other environments or settings:
momentic.config.yaml
defaultEnv: staging selects that environment. A shell variable only becomes available through an explicit variable reference or inheritFromShell: true; shell inheritance defaults to false. Put secrets in an ignored environment file or your CI secret store. See environment variables. For remote Android execution, upload the APK to a channel and pin the build tag when running the file:
Save the example as mobile-tests/checkout.test.yaml under the project’s configured include paths, and replace the APK path with your build. Without a channel or an explicit installation step, openApp assumes the app is already installed. For local execution, pass an AVD and APK, or an iOS simulator type and .app path. See mobile run options.

Command mapping

Preserve selectors, checks, and waits

Maestro’s text and ID selectors use regular expressions. Momentic target descriptions are natural language, not regular expressions or Maestro selector objects. Translate the intended target, including any parent, position, index, or state constraint. Do not paste an ID regex into tap and assume it keeps the original match. Use element visibility checks for visible or hidden elements. Use element content checks for exact text. checkScreenContains searches the screen hierarchy or WebView content and can match offscreen content; it does not replace assertVisible. Use AI assertions when the intended check is semantic, and review whether that changes the original contract. Preserve extendedWaitUntil timeouts on a condition step in milliseconds. For example, wait up to 30 seconds for the confirmation to become visible:
Auto-waiting handles target readiness, but it does not establish that a background save or network request has finished. Keep those checks explicit. Retries rerun actions; timeouts wait for a condition. Do not replace a wait with a retry when repeating the action creates duplicate data.

Subflows, variables, and hooks

Extract a reusable sequence into a mobile module. Map runFlow.env values to module inputs instead of putting every flow’s variables in the global project environment. Keep defaults local to the module, and use setVariable or saveAs for values created during a test. See module parameters and variable scope. This module takes one input and has no nested module calls:
modules/enter-email.module.yaml
Replace the inline email-entry step in the checkout test with this invocation:
env.EMAIL is an expression; use { string: "jeff@example.com" } to pass a literal. Flatten nested runFlow calls into the module’s steps, or invoke each module from the test. A module cannot call another module. Module paths are relative to the calling file, so mobile-tests/checkout.test.yaml uses ../modules/enter-email.module.yaml for the module shown above. Translate when conditions to an assertion-based if where possible. Split platform-specific behavior into iOS and Android tests or modules; the mobile if condition is not a Maestro platform selector. Check loop bounds and retry boundaries rather than renaming repeat or retry mechanically. Move each top-level flow’s onFlowStart and onFlowComplete behavior into before and after. Modules do not have Maestro flow hooks. Inline a subflow’s setup at its original call site. Put cleanup that must survive a subflow failure in the test’s after, and check that its ordering and scope still match the original flow. A failed before skips the main steps; after still runs, so cleanup must tolerate incomplete setup. Running one step in the editor skips test hooks. Validate them with a whole-test run. See before and after sections. Check Maestro launch options separately. Its default launchApp restarts the app, and options can clear app data or the iOS keychain and set permissions. Momentic’s killApp stops the current foreground app. Use it before openApp only when the intended app is already in the foreground; it does not target the identifier passed to a later openApp. The Android example uses shell am force-stop to stop that package regardless of which app is active. Neither method clears app data. To reset app data on Android, use an adb step:
Preserve iOS keychain, permissions, and other reset behavior using a verified setup method, or retain the Maestro test until you have one. Use independent backend records for each test and clean up only the records it created. A new emulator session does not clear your application’s backend.

What does not map

  • Momentic has no separate inspector app like Maestro Studio: the local editor’s element picker plus debugState cover element inspection.
  • Maestro runScript and evalScript code needs adaptation. Momentic’s javascript step runs in a Node sandbox with its own globals; Maestro’s output object and UI commands do not become Momentic APIs. Use env, setVariable, and saveAs for data, and preset or AI steps for UI actions.
  • Physical devices are not supported: remote execution is emulators and simulators only.
  • Maestro’s tolerance and optional-element flags have no equivalent: Momentic resolves target descriptions rather than Maestro selector flags. For an optional action, use an if step with an element check and nested then steps. Mobile if has no else branch. See mobile conditionals.
  • A maestro cloud command and its workspace configuration do not transfer to Momentic. Configure build upload, test selection, parallelism, reporting, and scheduling explicitly in your CI provider.

Incremental strategy

  1. Port one bounded flow end to end, including its hooks, subflows, inputs, waits, and cleanup. Start with a flow whose repeated locator failures you can compare. Keep Maestro installed and preserve the .maestro directory.
  2. Lint and run the file on the intended target. Compare both runners on the same build and starting state. Inspect screenshots at assertions, including a case where the expected outcome is absent.
  3. Separate environment values from module parameters. Pin the app build tag and check the OS version, permissions, and reset behavior before comparing stability.
  4. Add a separate Momentic CI job with its own test data. Do not run both runners concurrently on the same local emulator. Remote Momentic tests use independent emulator sessions; local Android parallel tests need distinct AVDs, and local iOS runs should use --parallel 1.
  5. Replace gates flow by flow after reviewing equivalent coverage and repeated results. Retain legacy flows for hardware, OS, selectors, or reset behavior you have not migrated. Remove their CI jobs and files only after that coverage is accounted for.
In CI, install momentic-mobile from the lockfile, set MOMENTIC_API_KEY from the CI secret store, and provide the platform prerequisites. Upload the build with a unique tag, then use that same tag when running tests. Add --reporter junit to generate reports under ./reports, and preserve the run command’s exit status as the job result. See GitHub Actions or the other CI guides.

Porting at scale with a coding agent

Paste this prompt into your coding agent after installing Momentic and providing the app build: