Summary
When using Maestro to test a Flutter web app, SemanticsBinding.instance.ensureSemantics() must be called in the app's main() for Maestro to detect any elements. Without it, everything silently fails — there are no errors, warnings, or hints about what's wrong.
The problem
Flutter web renders to <canvas> and does not create the DOM accessibility/semantics overlay by default. Maestro relies on this overlay to find elements. When it's missing:
assertVisible fails (even though the text is clearly rendered)
tapOn fails (element not found)
takeScreenshot within flows captures the rendered app correctly
- Failure screenshots in
~/.maestro/tests/ show the app fully loaded and functional
This creates a confusing debugging experience: the app is visually correct in screenshots, but Maestro can't see anything. There's no indication that semantics are the issue.
The fix (for app developers)
import 'package:flutter/rendering.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
SemanticsBinding.instance.ensureSemantics(); // ← required for Maestro on web
runApp(const MyApp());
}
Suggested improvements
-
Documentation: The Flutter support page mentions "Use Semantics to make elements addressable" for Flutter Web, but doesn't mention the critical ensureSemantics() call. This is the difference between "add semantic labels to widgets" (which most Flutter devs already do) and "force-enable the entire semantics DOM overlay on web" (which almost nobody does by default).
-
Runtime detection: When Maestro connects to a Flutter web app and finds zero semantic elements in the DOM, it could surface a warning like: "No semantic elements found. Flutter web requires SemanticsBinding.instance.ensureSemantics() in main() — see docs."
Environment
- Maestro 2.4.0
- Flutter 3.41.1 (stable)
- macOS, Chrome/Chromium
- Tested with both
maestro test CLI and Maestro MCP run_flow
Steps to reproduce
- Create any Flutter web app without
ensureSemantics() in main
- Add semantic labels to widgets (e.g.,
Semantics(label: 'hello', child: ...))
- Run with
flutter run -d web-server
- Write a Maestro flow:
url: http://localhost:8080
---
- launchApp
- assertVisible: "hello"
- Run
maestro test flow.yaml
- Result: Assertion fails. Failure screenshot shows the app rendered correctly with "hello" visible.
- Expected: Either the assertion passes, or Maestro warns about missing semantics.
Summary
When using Maestro to test a Flutter web app,
SemanticsBinding.instance.ensureSemantics()must be called in the app'smain()for Maestro to detect any elements. Without it, everything silently fails — there are no errors, warnings, or hints about what's wrong.The problem
Flutter web renders to
<canvas>and does not create the DOM accessibility/semantics overlay by default. Maestro relies on this overlay to find elements. When it's missing:assertVisiblefails (even though the text is clearly rendered)tapOnfails (element not found)takeScreenshotwithin flows captures the rendered app correctly~/.maestro/tests/show the app fully loaded and functionalThis creates a confusing debugging experience: the app is visually correct in screenshots, but Maestro can't see anything. There's no indication that semantics are the issue.
The fix (for app developers)
Suggested improvements
Documentation: The Flutter support page mentions "Use Semantics to make elements addressable" for Flutter Web, but doesn't mention the critical
ensureSemantics()call. This is the difference between "add semantic labels to widgets" (which most Flutter devs already do) and "force-enable the entire semantics DOM overlay on web" (which almost nobody does by default).Runtime detection: When Maestro connects to a Flutter web app and finds zero semantic elements in the DOM, it could surface a warning like: "No semantic elements found. Flutter web requires
SemanticsBinding.instance.ensureSemantics()in main() — see docs."Environment
maestro testCLI and Maestro MCPrun_flowSteps to reproduce
ensureSemantics()in mainSemantics(label: 'hello', child: ...))flutter run -d web-servermaestro test flow.yaml