Skip to content

Detect Maestro ​

Detect when your app is running under Astra Scout automation to enable test-specific behavior.

App developers can make the app behave differently while it is being tested: skip a 2FA (two-factor authentication) screen, turn off analytics so production data stays clean, or point to a mock server (a fake server used for testing).

Astra Scout runs flows with maestro-runner, a fork of Maestro (an open-source tool that runs UI tests for mobile apps). That is why the name "Maestro" shows up in your app code: the flow sends a flag to the app at launch, and the app reads that flag to know it is under test.

Why detect it? ​

Knowing the app is under test helps with situations that are hard to automate:

  • Bypassing 2FA: use a fixed code instead of one sent by SMS or email, so you need no real SIM or inbox.
  • Keeping content longer: let short-lived messages (like temporary banners) stay on screen longer, so Astra Scout has time to find and use them.
  • Switching environment: point the app to a mock server or a staging database so production data stays clean.
  • Disabling custom animations: if your app has an animation that waitForAnimationToEnd cannot wait for, turn it off during tests to avoid missed taps (a tap that lands while the element is still moving).

Mobile (iOS and Android) ​

The recommended way on mobile is to pass launchApp arguments from the flow. It is reliable and easy to follow.

Pass the argument in your Flow ​

In your flow, use the arguments parameter of launchApp to send a custom flag.

Launch arguments in Astra Scout

Astra Scout passes arguments to maestro-runner, which hands them to the app at launch. On iOS they reach the app as -key value launch arguments, so ProcessInfo.processInfo.arguments contains -isMaestro. On Android, run a quick test to confirm how the app receives the value before you rely on it.

yaml
- launchApp:
    appId: "com.example.app"
    arguments:
      isMaestro: "true"

Read the argument in your app code ​

Your app checks this flag when it starts.

Android (Kotlin/Java)

kotlin
val isMaestro = intent.getStringExtra("isMaestro") == "true"
if (isMaestro) {
    // Disable analytics or use mock data
}

iOS (Swift)

swift
if ProcessInfo.processInfo.arguments.contains("-isMaestro") {
    // Apply test-only configurations
}

React Native

For React Native, use a library like react-native-launch-arguments to retrieve the parameters passed during startup.

javascript
import { LaunchArguments } from 'react-native-launch-arguments';

if (LaunchArguments.value().isMaestro === "true") {
    // Apply test-only configurations
}

Flutter

For Flutter, the most straightforward approach is to use a package like flutter_launch_arguments to get the parameters from the flow, with no need to write a platform channel yourself:

dart
import 'package:flutter_launch_arguments/flutter_launch_arguments.dart';

Future<void> getArguments() async {
  final fla = FlutterLaunchArguments();

  final foo = await fla.getString('foo');
  final isFooEnabled = await fla.getBool('isFooEnabled');
  final fooValue = await fla.getDouble('fooValue');
  final fooInt = await fla.getInt('fooInt');
}
  • launchApp: Full reference for passing launch arguments.