How to Write Conditional Logic in Maestro YAML: Complete Guide with Examples

Maestro lets you conditionally execute commands directly inside a flow file by adding a when: (or legacy if:) block to any supported command, parsing conditions into a YamlCondition data class that evaluates platform, visibility, or JavaScript expressions before running the command.

Conditional logic in Maestro YAML allows your mobile test flows to adapt dynamically to UI state, device platform, or environment variables without external scripting. According to the mobile-dev-inc/Maestro source code, the orchestration engine supports declarative conditions through the when: block defined in maestro-orchestra/src/main/java/maestro/orchestra/yaml/YamlCondition.kt.

Understanding the when: Block Structure

In YamlCondition.kt (lines 6‑14), Maestro defines the data class that captures all supported conditional fields. When the YAML parser processes a flow, YamlFluentCommand converts these definitions into concrete MaestroCommand objects. For each command carrying a conditional block, the parser invokes YamlCondition.toCondition() (lines 1005‑1013 in YamlFluentCommand.kt) to build a runtime Condition instance used by the executor.

This architecture allows the engine to evaluate conditions eagerly before executing the command. As noted in the project's CHANGELOG.md (line 99), this eager evaluation improves performance by checking script conditions ahead of visibility checks.

Supported Condition Types

Platform Filtering

Execute commands only on specific operating systems using the platform field. Valid values are ANDROID or IOS.

Visibility Checks

Use visible to run a command only when an element matching the selector is displayed. Conversely, use notVisible to execute only when an element is hidden from view.

JavaScript Expressions

The true field accepts arbitrary JavaScript expressions that must evaluate to true for the command to execute. This enables complex logic using environment variables or computed values via Maestro's built-in functions.

Debug Labels

Add an optional label field to any condition for clearer debugging and test reporting output.

Practical Code Examples

Run a script only when a button is visible:

- runScript:
    when:
      visible: "Continue"
    file: scripts/doStuff.js
    label: "Run when Continue button appears"

Launch the app only on Android devices:

- launchApp:
    when:
      platform: ANDROID
    appId: com.example.myapp

Execute a flow step only when a JavaScript condition is true:

- assertTrue:
    when:
      true: "${env('ENABLE_ASSERT') === 'true'}"
    condition: "someVariable > 0"
    label: "Guarded assertion"

Conditional repeat loop using while syntax:

- repeat:
    while:
      notVisible: "Loading"
    times: 10
    commands:
      - tapOn: "Refresh"

Run a sub-flow with multiple conditions:

- runFlow:
    when:
      platform: iOS
      true: "${env('RUN_SUBFLOW') == '1'}"
    file: subflows/login.yaml

Commands Supporting Conditional Logic

The when: block (and legacy if: syntax) functions across multiple command types in the orchestration layer. The parser handles conditional conversion for:

  • runScript – Execute JavaScript files conditionally
  • runFlow – Include sub-flows based on runtime state
  • repeat – Loop using while conditions (evaluated via notVisible or other checks)
  • assertTrue – Guard assertions with preconditions
  • assertVisible – Conditional visibility assertions
  • launchApp – Platform-specific app launches

Summary

  • Add conditional logic in Maestro YAML using the when: block on supported commands, or the legacy if: syntax
  • Conditions support platform filtering (ANDROID/IOS), visibility checks (visible/notVisible), and JavaScript boolean expressions (true)
  • The parser converts YAML conditions to runtime Condition objects via YamlCondition.toCondition() in YamlFluentCommand.kt
  • Evaluation happens eagerly before command execution to optimize performance, skipping the command entirely when the condition is false
  • Use optional label fields to improve debugging and test reporting clarity

Frequently Asked Questions

Can I combine multiple conditions in a single when: block?

Yes. You can specify multiple checks such as platform: iOS and true: "${env('FLAG') == '1'}" within the same when: block, and Maestro requires all conditions to evaluate to true before executing the command. This allows you to gate flows by both device type and environment configuration simultaneously.

What is the difference between when: and if: in Maestro YAML?

There is no functional difference. Maestro supports both when: and the legacy if: syntax for backward compatibility. Both keywords trigger the same condition parsing logic in YamlFluentCommand.kt, converting your YAML into a Condition instance that the runtime evaluates before command execution.

What JavaScript context is available in the true condition?

The true field executes JavaScript expressions with access to Maestro's built-in functions such as env() for reading environment variables. The expression must return a boolean value, and the evaluation occurs eagerly—before the associated command runs—according to the implementation in YamlCondition.toCondition().

Can I use conditional logic with repeat loops?

Yes. The repeat command accepts a while: block that uses the same condition structure as when:. You can specify notVisible, visible, platform, or true conditions to control loop execution. The engine evaluates the condition before each iteration, continuing the loop only while the condition remains satisfied.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →