with one click
maestro-assertions-conditions
// Assertions (assertVisible/assertNotVisible), conditional branching (when), and subflow execution (runFlow) in Maestro.
// Assertions (assertVisible/assertNotVisible), conditional branching (when), and subflow execution (runFlow) in Maestro.
[HINT] Download the complete skill directory including SKILL.md and all related files
| name | maestro-assertions-conditions |
| description | Assertions (assertVisible/assertNotVisible), conditional branching (when), and subflow execution (runFlow) in Maestro. |
| tech_stack | ["maestro","mobile-native"] |
| capability | ["e2e-testing"] |
| version | maestro unversioned |
| collected_at | "2025-01-01T00:00:00.000Z" |
Source: https://docs.maestro.dev/maestro-flows/flow-control-and-logic/conditions, https://docs.maestro.dev/reference/commands-available/assertvisible, https://docs.maestro.dev/reference/commands-available/assertnotvisible, https://docs.maestro.dev/reference/commands-available/runflow
Validate UI state with assertVisible/assertNotVisible, branch test logic with when conditions, and compose modular flows with runFlow. Together these three primitives enable resilient, maintainable test suites that handle platform differences and dynamic UI.
when): Handle platform-specific UI (Android/iOS/Web), dynamic state like onboarding screens or A/B tests, "if element exists then act" patterns.Both commands auto-retry for ~7 seconds before failing. For longer waits, use extendedWaitUntil.
# Shorthand — assert by visible text
- assertVisible: "My Button"
- assertNotVisible: "Loading..."
# Full form — combine multiple selector properties
- assertVisible:
text: "Submit"
enabled: true
# Fails if: no "Submit" element, OR "Submit" exists but is disabled
- assertNotVisible:
text: "Error"
enabled: true
# Fails only if an enabled "Error" element is visible
Available selector properties: text, id, enabled, checked, focused, selected.
when — four condition typesAttach a when block to runFlow (or certain other commands). Maestro skips the command if the condition is false.
| Condition | Syntax | Use when… |
|---|---|---|
visible | visible: {text: "Foo"} | Element is on screen |
notVisible | notVisible: {text: "Foo"} | Element is absent |
platform | platform: Android | Platform-specific logic |
true | true: "${VAR} === 'on'" | Arbitrary JS expression |
| Parameter | Type | Purpose |
|---|---|---|
file | string | Relative path to a .yaml flow file |
commands | list | Inline command list (alternative to file) |
label | string | Description shown in reports |
env | map | Environment variables passed to the subflow |
- runFlow:
when:
platform: Android
file: subflows/android-permissions.yaml
- runFlow:
when:
platform: iOS
file: subflows/ios-permissions.yaml
Pattern A: runFlow + when (preferred for clarity)
- runFlow:
when:
visible:
text: "Rate this App"
file: subflows/dismiss-rate-popup.yaml
Pattern B: optional property (for single commands)
- tapOn:
text: "No Thanks"
optional: true
label: "Dismiss rate popup if present"
- runFlow:
when:
notVisible:
text: "Biometric Login"
commands:
- tapOn: "Standard Login"
- runFlow:
label: "Complete onboarding"
when:
visible:
text: "Welcome to our App"
commands:
- tapOn: "Next"
- tapOn: "Next"
- tapOn: "Get Started"
All conditions in a when block must be true:
- tapOn:
when:
platform: Android
visible:
text: "Allow Notifications"
text: "Allow"
# Inline JS expression
- runFlow:
when:
true: "${IS_FEATURE_ENABLED} === true"
file: new-feature-test.yaml
# External JS file (keeps YAML clean)
- runScript: checkFeatureFlag.js
- runFlow:
when:
true: "${output.FEATURE_FLAG} === true"
file: new-feature-test.yaml
# Login.yaml — defined once
appId: com.example.app
---
- launchApp
- tapOn: Username
- inputText: ${USERNAME}
- tapOn: Password
- inputText: ${PASSWORD}
- tapOn: Login
# Profile.yaml — reused
appId: com.example.app
---
- runFlow:
file: Login.yaml
env:
USERNAME: "admin"
PASSWORD: "secret123"
- tapOn: Profile
- assertVisible: "Name: admin"
assertVisible / assertNotVisible: Accept a string shorthand (text) or a map of selectors (text, id, enabled, checked, focused, selected). Auto-retry ~7s. Use extendedWaitUntil for longer waits.
when: Attached to runFlow (and some other commands). Supports visible, notVisible, platform (Android/iOS/Web), true (JS expression). Multiple conditions → AND logic.
runFlow: file (relative path to flow), commands (inline list), label (report name), env (variable map). Inline form is ideal for conditional branching without creating extra files.
visible/notVisible selectors target unique, reliable elements.extendedWaitUntil.when block. Use separate runFlow steps for OR logic.runFlow so Maestro can upload dependencies and config.yaml. Single-file mode uses best-effort dependency collection and may fail with Failed to parse file.assertVisible with enabled: true: fails if the element exists but is disabled, not just if absent.tapOn does not natively accept when in all contexts — use runFlow + when + inline commands as the workaround.maestro-flow-yaml-basics for the foundational commands (launchApp, tapOn, inputText) that populate the UI state you'll assert against.commands for small conditional blocks (1-3 commands); use file for reusable, multi-step sequences.label to runFlow — it makes CI reports readable.