Conditions

Execute commands conditionally based on visibility, platform, or custom expressions.

Conditions allow you to execute commands or entire Flows only when specific criteria are met. This is useful for handling platform-specific logic (Android vs. iOS vs. Web), managing A/B tests, or dealing with dynamic UI elements like onboarding screens or permission dialogs.

circle-check

Keep your tests simple

Supported conditions

In Maestro, conditions are primarily handled using the when argument. It can be attached to several commands. If the condition inside the when block evaluates to true, Maestro executes the command; otherwise, Maestro simply skips that command and moves on to the next one.

The following table lists the available conditions you can use to define the conditional execution of your Flow.

Condition
Description

visible

Executed if the element matching the selector is visible. The element must be defined using one or more Selectors.

notVisible

Executed if the element matching the selector is not visible. The element must be defined using one or more Selectors.

platform

Executed if the current platform matches (Android, iOS, or Web).

true

Executed if the JavaScript expression evaluates to true.

Common use cases

Handling platform differences

Mobile apps often have different UI or behaviors on Android, iOS, or Web. You can use the platform condition to run platform-specific Flows.

In this example, the test executes a specific subflow to handle permissions, depending on whether the device is running Android, iOS, or Web.

- runFlow:
      when:
      platform: Android
    file: subflows/android-permissions.yaml

- runFlow:
    when:
      platform: iOS
    file: subflows/ios-permissions.yaml
    
- runFlow:
    when:
      platform: Web
    file: subflows/web-permissions.yaml

Handling dynamic state

Sometimes an element may or may not appear, such as a "Rate this App" popup or a newsletter signup. You can handle these dynamic states using two different patterns:

This is the most idiomatically expressive way to handle conditions. It clearly defines the intent "Only run these commands when this condition is met." You combine runFlow and when:

circle-check

Using notVisible for negative conditions

You can use the notVisible condition to handle inverse or “else” scenarios where an action should occur only when a specific element is not present on the screen.

For example, the following command taps Standard Login only if the Biometric Login option is not visible. The runFlow command is used here because the tapOn command itself does not support conditional logic:

This approach allows your tests to adapt to different UI states.

Running multiple commands

You don't always need to create a separate file for conditional steps. You can use the commands list to define multiple actions inline.

In this example, if the "Welcome to our App" text is visible, the flow executes a sequence of taps to navigate through the onboarding screen.

Multiple conditions

You can combine multiple conditions in a single when block. Note that all conditions must be met (AND logic) for the commands to execute.

In this example, the Allow button is tapped only if the platform is Android AND the Allow Notifications text is visible.

Advanced logic with JavaScript

For more complex logic, such as feature flags or checking variables, use the true condition with a JavaScript expression.

In this example, the new-feature-test.yaml subflow is executed only if the IS_FEATURE_ENABLED variable evaluates to true.

If your JavaScript condition is longer than one line, move the logic into a separate .js file and use the output variable to keep your YAML clean.

The following example shows how to move the logic to an external file. First, create your script logic:

Then, reference it in your Flow:

Next steps

Now that you understand how to use conditions in your Flows, learn how to use parameters and constants or explore all the possibilities of using JavaScript to create tests.

Last updated