Skip to content

Flutter Web: ensureSemantics() required but not documented — silent failure #185

@andyhorn

Description

@andyhorn

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

  1. 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).

  2. 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

  1. Create any Flutter web app without ensureSemantics() in main
  2. Add semantic labels to widgets (e.g., Semantics(label: 'hello', child: ...))
  3. Run with flutter run -d web-server
  4. Write a Maestro flow:
    url: http://localhost:8080
    ---
    - launchApp
    - assertVisible: "hello"
  5. Run maestro test flow.yaml
  6. Result: Assertion fails. Failure screenshot shows the app rendered correctly with "hello" visible.
  7. Expected: Either the assertion passes, or Maestro warns about missing semantics.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions