Skip to content

[Testing] containsSemantics can't find semanticsLabel inside FormField #173838

Closed

Description

@desmond206x

Steps to reproduce

Start the two example tests.
The first one failes, the second one is successfully.

Expected results

Both tests should work.

Actual results

The first test can't find the semantics from the semantics tree, because it is wrapped inside a FormField Widget.

It was working with Flutter 3.29.x, but is broken since Flutter 3.32.x.
Also broken with 3.35.1 and master channel.

Code sample

Example app
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple)),
      home: Scaffold(
        body: Column(
          children: [
            Semantics(
              label: 'first parent semantics label',
              explicitChildNodes: true,
              child: FormField(
                builder: (field) => Semantics(label: 'failing child semantics label', child: Container(height: 40)),
              ),
            ),
            Semantics(
              label: 'second parent semantics label',
              explicitChildNodes: true,
              child: Semantics(label: 'successful child semantics label', child: Container(height: 40)),
            ),
          ],
        ),
      ),
    );
  }
}
Example test
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:semantics/main.dart';

void main() {
  testWidgets('semantics broken', (WidgetTester tester) async {
    await tester.pumpWidget(const MyApp());

    debugDumpSemanticsTree();

    expect(
      tester.semantics.simulatedAccessibilityTraversal(),
      containsOnce(containsSemantics(label: 'failing child semantics label')),
    );
  });

  testWidgets('semantics successfully', (WidgetTester tester) async {
    await tester.pumpWidget(const MyApp());

    debugDumpSemanticsTree();
    expect(
      tester.semantics.simulatedAccessibilityTraversal(),
      containsOnce(containsSemantics(label: 'successful child semantics label')),
    );
  });
}

Screenshots or Video

Logs

Logs
[Paste your logs here]

Flutter Doctor output

Doctor output
[Paste your output here]

Activity

  1. tirth-patel-nc commented on Aug 15, 2025

    @tirth-patel-nc
    Member

    Thanks for the report. Seeing the same behaviour with latest SDK versions. First test fails on following versions:

    might be related to #165363

    stable : 3.32.8, 3.35.1
    master : 3.33.0-1.0.pre-1430
    beta   : 3.36.0-0.1.pre
    
    Error - flutter test log
    tirthpatel@Tirths-MacBook-Pro au15 % flutter test
    00:03 +0: semantics broken                                                                                                                                                                                 
    SemanticsNode#0
     │ Rect.fromLTRB(0.0, 0.0, 2400.0, 1800.0)
     │
     └─SemanticsNode#1
       │ Rect.fromLTRB(0.0, 0.0, 800.0, 600.0) scaled by 3.0x
       │ textDirection: ltr
       │
       └─SemanticsNode#2
         │ Rect.fromLTRB(0.0, 0.0, 800.0, 600.0)
         │ sortKey: OrdinalSortKey#b55ab(order: 0.0)
         │
         └─SemanticsNode#3
           │ Rect.fromLTRB(0.0, 0.0, 800.0, 600.0)
           │ flags: scopesRoute
           │
           ├─SemanticsNode#4
           │ │ Rect.fromLTRB(0.0, 0.0, 800.0, 40.0)
           │ │ label: "first parent semantics label"
           │ │ textDirection: ltr
           │ │
           │ └─SemanticsNode#5
           │     Rect.fromLTRB(0.0, 0.0, 800.0, 40.0)
           │     label: "failing child semantics label"
           │     textDirection: ltr
           │
           └─SemanticsNode#6
             │ Rect.fromLTRB(0.0, 40.0, 800.0, 80.0)
             │ label: "second parent semantics label"
             │ textDirection: ltr
             │
             └─SemanticsNode#7
                 Rect.fromLTRB(0.0, 0.0, 800.0, 40.0)
                 label: "successful child semantics label"
                 textDirection: ltr
    
    ══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
    The following TestFailure was thrown running a test:
    Expected: contains once(has semantics with label: failing child semantics label)
      Actual: SubListIterable<SemanticsNode>:[
                SemanticsNode:SemanticsNode#4(Rect.fromLTRB(0.0, 0.0, 800.0, 40.0), label: "first parent
    semantics label", textDirection: ltr),
                SemanticsNode:SemanticsNode#5(Rect.fromLTRB(0.0, 0.0, 800.0, 40.0), label: "failing
    child semantics label", textDirection: ltr),
                SemanticsNode:SemanticsNode#6(Rect.fromLTRB(0.0, 40.0, 800.0, 80.0), label: "second
    parent semantics label", textDirection: ltr),
                SemanticsNode:SemanticsNode#7(Rect.fromLTRB(0.0, 0.0, 800.0, 40.0), label: "successful
    child semantics label", textDirection: ltr)
              ]
       Which: did not find a value matching has semantics with label: failing child semantics label
    
    When the exception was thrown, this was the stack:
    #4      main.<anonymous closure> (file:///Users/tirthpatel/au15/test/widget_test.dart:11:5)
    <asynchronous suspension>
    #5      testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:192:15)
    <asynchronous suspension>
    #6      TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:1059:5)
    <asynchronous suspension>
    <asynchronous suspension>
    (elided one frame from package:stack_trace)
    
    This was caught by the test expectation on the following line:
      file:///Users/tirthpatel/au15/test/widget_test.dart line 11
    The test description was:
      semantics broken
    ════════════════════════════════════════════════════════════════════════════════════════════════════
    00:03 +0 -1: semantics broken [E]                                                                                                                                                                          
      Test failed. See exception logs above.
      The test description was: semantics broken
      
    
    To run this test again: /Users/tirthpatel/Development/flutter_master/flutter/bin/cache/dart-sdk/bin/dart test /Users/tirthpatel/au15/test/widget_test.dart -p vm --plain-name 'semantics broken'
    00:03 +0 -1: semantics successfully                                                                                                                                                                        
    SemanticsNode#0
     │ Rect.fromLTRB(0.0, 0.0, 2400.0, 1800.0)
     │
     └─SemanticsNode#1
       │ Rect.fromLTRB(0.0, 0.0, 800.0, 600.0) scaled by 3.0x
       │ textDirection: ltr
       │
       └─SemanticsNode#2
         │ Rect.fromLTRB(0.0, 0.0, 800.0, 600.0)
         │ sortKey: OrdinalSortKey#b55ab(order: 0.0)
         │
         └─SemanticsNode#3
           │ Rect.fromLTRB(0.0, 0.0, 800.0, 600.0)
           │ flags: scopesRoute
           │
           ├─SemanticsNode#4
           │ │ Rect.fromLTRB(0.0, 0.0, 800.0, 40.0)
           │ │ label: "first parent semantics label"
           │ │ textDirection: ltr
           │ │
           │ └─SemanticsNode#5
           │     Rect.fromLTRB(0.0, 0.0, 800.0, 40.0)
           │     label: "failing child semantics label"
           │     textDirection: ltr
           │
           └─SemanticsNode#6
             │ Rect.fromLTRB(0.0, 40.0, 800.0, 80.0)
             │ label: "second parent semantics label"
             │ textDirection: ltr
             │
             └─SemanticsNode#7
                 Rect.fromLTRB(0.0, 0.0, 800.0, 40.0)
                 label: "successful child semantics label"
                 textDirection: ltr
    
    00:03 +1 -1: Some tests failed.                                                                                                                                                                            
    tirthpatel@Tirths-MacBook-Pro au15 % 

    However both tests passes on 3.29.3. Marking it as a regression.

    3.29.3 - flutter test log
    tirthpatel@Tirths-MacBook-Pro au15 % flutter test
    00:01 +0: semantics broken                                                                                                                                                                                 
    SemanticsNode#0
     │ Rect.fromLTRB(0.0, 0.0, 2400.0, 1800.0)
     │
     └─SemanticsNode#1
       │ Rect.fromLTRB(0.0, 0.0, 800.0, 600.0) scaled by 3.0x
       │ textDirection: ltr
       │
       └─SemanticsNode#2
         │ Rect.fromLTRB(0.0, 0.0, 800.0, 600.0)
         │ sortKey: OrdinalSortKey#9f850(order: 0.0)
         │
         └─SemanticsNode#3
           │ Rect.fromLTRB(0.0, 0.0, 800.0, 600.0)
           │ flags: scopesRoute
           │
           ├─SemanticsNode#4
           │ │ Rect.fromLTRB(0.0, 0.0, 800.0, 40.0)
           │ │ label: "first parent semantics label"
           │ │ textDirection: ltr
           │ │
           │ └─SemanticsNode#5
           │     Rect.fromLTRB(0.0, 0.0, 800.0, 40.0)
           │     label: "failing child semantics label"
           │     textDirection: ltr
           │
           └─SemanticsNode#6
             │ Rect.fromLTRB(0.0, 40.0, 800.0, 80.0)
             │ label: "second parent semantics label"
             │ textDirection: ltr
             │
             └─SemanticsNode#7
                 Rect.fromLTRB(0.0, 0.0, 800.0, 40.0)
                 label: "successful child semantics label"
                 textDirection: ltr
    
    00:01 +1: semantics successfully                                                                                                                                                                           
    SemanticsNode#0
     │ Rect.fromLTRB(0.0, 0.0, 2400.0, 1800.0)
     │
     └─SemanticsNode#1
       │ Rect.fromLTRB(0.0, 0.0, 800.0, 600.0) scaled by 3.0x
       │ textDirection: ltr
       │
       └─SemanticsNode#2
         │ Rect.fromLTRB(0.0, 0.0, 800.0, 600.0)
         │ sortKey: OrdinalSortKey#9f850(order: 0.0)
         │
         └─SemanticsNode#3
           │ Rect.fromLTRB(0.0, 0.0, 800.0, 600.0)
           │ flags: scopesRoute
           │
           ├─SemanticsNode#4
           │ │ Rect.fromLTRB(0.0, 0.0, 800.0, 40.0)
           │ │ label: "first parent semantics label"
           │ │ textDirection: ltr
           │ │
           │ └─SemanticsNode#5
           │     Rect.fromLTRB(0.0, 0.0, 800.0, 40.0)
           │     label: "failing child semantics label"
           │     textDirection: ltr
           │
           └─SemanticsNode#6
             │ Rect.fromLTRB(0.0, 40.0, 800.0, 80.0)
             │ label: "second parent semantics label"
             │ textDirection: ltr
             │
             └─SemanticsNode#7
                 Rect.fromLTRB(0.0, 0.0, 800.0, 40.0)
                 label: "successful child semantics label"
                 textDirection: ltr
    
    00:01 +2: All tests passed!                                                                                                                                                                                
    tirthpatel@Tirths-MacBook-Pro au15 % 

    Bisected to #165935

    Bisect Log
    tirthpatel@Tirths-MacBook-Pro au15 % cd ~/Development/flutter_3.32.8
    tirthpatel@Tirths-MacBook-Pro flutter_3.32.8 % cd flutter 
    tirthpatel@Tirths-MacBook-Pro flutter % git bisect bad
    You need to start by "git bisect start"
    
    Do you want me to do it for you [Y/n]? Y
    status: waiting for both good and bad commits
    status: waiting for good commit(s), bad commit known
    tirthpatel@Tirths-MacBook-Pro flutter % git bisect good ea121f8
    Bisecting: a merge base must be tested
    [010c8a806bccad64ab9972286b85dd24ca98441f] Revert "Autocomplete Options Width" (#161666)
    tirthpatel@Tirths-MacBook-Pro flutter % git bisect good ea121f8
    Bisecting: a merge base must be tested
    [010c8a806bccad64ab9972286b85dd24ca98441f] Revert "Autocomplete Options Width" (#161666)
    tirthpatel@Tirths-MacBook-Pro flutter % git bisect good        
    Bisecting: 658 revisions left to test after this (roughly 9 steps)
    [07503bbc82a7372a6a685e5b5d1406d139b8353c] [macOS] Prepare FlutterKeyboardManager for multi-view (#163962)
    tirthpatel@Tirths-MacBook-Pro flutter % git bisect good 
    Bisecting: 329 revisions left to test after this (roughly 8 steps)
    [7b0be2e57e8a2724990795f08431471ea45d66eb] Roll Dart SDK from 13e950e67c2a to e00a58dc8fe7 (1 revision) (#165791)
    tirthpatel@Tirths-MacBook-Pro flutter % git bisect good 
    Bisecting: 164 revisions left to test after this (roughly 7 steps)
    [43bb8a669d6f88999394966e51a4dbf4f779a8e4] Update Roadmap (#166332)
    tirthpatel@Tirths-MacBook-Pro flutter % git bisect good 
    Bisecting: 82 revisions left to test after this (roughly 6 steps)
    [277d899bb74656070361125dc56e90cf61db410c] Roll Skia from 7d56b9cc7ce9 to 3ea44c88d37b (1 revision) (#166741)
    tirthpatel@Tirths-MacBook-Pro flutter % git bisect bad  
    Bisecting: 40 revisions left to test after this (roughly 5 steps)
    [b1c08092d069f63ade95ecd093a70f1ccae724ad] Reverts "[Impeller] Render conics without conversion from Flutter apps (#166305)" (#166591)
    tirthpatel@Tirths-MacBook-Pro flutter % git bisect bad
    Bisecting: 20 revisions left to test after this (roughly 4 steps)
    [3bf6754d481654d2a0978d644eb00380a7b21b59] Migrate to Theme.brightnessOf method (#163950)
    tirthpatel@Tirths-MacBook-Pro flutter % git bisect bad
    Bisecting: 9 revisions left to test after this (roughly 3 steps)
    [25f7c15dd74755667c7797887e419677c91c5b36] Started pixel aligning hairlines (#166351)
    tirthpatel@Tirths-MacBook-Pro flutter % git bisect good
    Bisecting: 4 revisions left to test after this (roughly 2 steps)
    [e359812a512878e9096cc5b6e8945a3dfa917523] Skip flaking scheduler test (#166471)
    tirthpatel@Tirths-MacBook-Pro flutter % git bisect bad 
    Bisecting: 2 revisions left to test after this (roughly 1 step)
    [10d2631548e30d9462c665027820ee7b313d27a2] Remove unnecessary cache busting mechanism in hot restart (#166295)
    tirthpatel@Tirths-MacBook-Pro flutter % git bisect good
    Bisecting: 0 revisions left to test after this (roughly 1 step)
    [2976ed00ceaf227f24f9fc627ca27cea08e9db81] Roll pub packages (#166043)
    tirthpatel@Tirths-MacBook-Pro flutter % git bisect bad 
    Bisecting: 0 revisions left to test after this (roughly 0 steps)
    [fbbe0f9e7a09c433c6cf07a847a1d8923a876ee7] [a11y] add SemanticsValidationResult (#165935)
    tirthpatel@Tirths-MacBook-Pro flutter % git bisect bad 
    fbbe0f9e7a09c433c6cf07a847a1d8923a876ee7 is the first bad commit
    commit fbbe0f9e7a09c433c6cf07a847a1d8923a876ee7
    Author: Yegor <[email protected]>
    Date:   Wed Apr 2 15:00:19 2025 -0700
    
        [a11y] add SemanticsValidationResult (#165935)
        
        Add `SemanticsValidationResult` to semantics that maps onto
        `aria-invalid`.
        
        Fixes https://github.com/flutter/flutter/issues/162142
    
     engine/src/flutter/lib/ui/semantics.dart           |  48 +++++++-
     .../src/flutter/lib/ui/semantics/semantics_node.h  |  13 +++
     .../lib/ui/semantics/semantics_update_builder.cc   |   5 +-
     .../lib/ui/semantics/semantics_update_builder.h    |   3 +-
     engine/src/flutter/lib/web_ui/lib/semantics.dart   |   5 +
     .../lib/src/engine/semantics/incrementable.dart    |   5 +
     .../web_ui/lib/src/engine/semantics/semantics.dart |  59 ++++++++++
     .../lib/src/engine/semantics/text_field.dart       |   5 +
     .../flutter/lib/web_ui/test/common/matchers.dart   |  15 ++-
     .../test/engine/semantics/semantics_test.dart      |  55 ++++++++++
     .../test/engine/semantics/semantics_tester.dart    |   2 +
     packages/flutter/lib/src/material/data_table.dart  |   1 -
     .../flutter/lib/src/rendering/custom_paint.dart    |   6 +
     packages/flutter/lib/src/rendering/proxy_box.dart  |   3 +
     packages/flutter/lib/src/rendering/table.dart      |   1 -
     packages/flutter/lib/src/semantics/semantics.dart  |  97 ++++++++++++++++-
     packages/flutter/lib/src/widgets/basic.dart        |   6 +-
     packages/flutter/lib/src/widgets/form.dart         |  10 +-
     packages/flutter/lib/src/widgets/table.dart        |   1 -
     .../flutter/test/material/data_table_test.dart     |   1 -
     .../flutter/test/material/date_picker_test.dart    |   1 +
     .../input_date_picker_form_field_test.dart         |   2 +
     .../test/semantics/semantics_update_test.dart      |   3 +-
     .../flutter/test/widgets/custom_painter_test.dart  |  88 +++++++++++++++
     packages/flutter/test/widgets/form_test.dart       |  49 +++++++++
     packages/flutter/test/widgets/semantics_test.dart  | 121 +++++++++++++++++++++
     .../flutter/test/widgets/semantics_tester.dart     |  19 +++-
     packages/flutter/test/widgets/table_test.dart      |   1 -
     packages/flutter_test/lib/src/matchers.dart        |  12 ++
     packages/flutter_test/test/matchers_test.dart      |   6 +
     30 files changed, 620 insertions(+), 23 deletions(-)
    tirthpatel@Tirths-MacBook-Pro flutter % 
  2. added
    c: regressionIt was better in the past than it is now
    a: tests"flutter test", flutter_test, or one of our tests
    frameworkflutter/packages/flutter repository. See also f: labels.
    p: material_uimaterial_ui package in flutter/packages
    has reproducible stepsThe issue has been confirmed reproducible and is ready to work on
    a: accessibilityAccessibility, e.g. VoiceOver or TalkBack. (aka a11y)
    team-accessibilityOwned by Framework Accessibility team (i.e. responsible for accessibility code in flutter/flutter)
    and removed
    in triagePresently being triaged by the triage team
    team-accessibilityOwned by Framework Accessibility team (i.e. responsible for accessibility code in flutter/flutter)
    on Aug 15, 2025
  3. 8 remaining items

  4. flutter-triage-bot commented on Aug 27, 2025

    @flutter-triage-bot

    The triaged-framework label is irrelevant if there is no team-framework label or fyi-framework label.

  5. chunhtai commented on Aug 27, 2025

    @chunhtai
    Contributor

    I think something probably got dropped during the semantics merging. Do you have a semantics tree dump to verify if the label is still in the tree?

  6. yjbanov commented on Aug 27, 2025

    @yjbanov
    Contributor

    FYI, the output of debugDumpSemanticsTree does contain the node:

    SemanticsNode#0
     │ Rect.fromLTRB(0.0, 0.0, 1688.0, 1744.0)
     │
     └─SemanticsNode#1
       │ Rect.fromLTRB(0.0, 0.0, 844.0, 872.0) scaled by 2.0x
       │ textDirection: ltr
       │
       └─SemanticsNode#2
         │ Rect.fromLTRB(0.0, 0.0, 844.0, 872.0)
         │ sortKey: OrdinalSortKey#e139e(order: 0.0)
         │
         └─SemanticsNode#3
           │ Rect.fromLTRB(0.0, 0.0, 844.0, 872.0)
           │ flags: scopesRoute
           │
           ├─SemanticsNode#4
           │ │ Rect.fromLTRB(0.0, 0.0, 844.0, 40.0)
           │ │ label: "first parent semantics label"
           │ │ textDirection: ltr
           │ │
           │ └─SemanticsNode#5
           │     Rect.fromLTRB(0.0, 0.0, 844.0, 40.0)
           │     label: "failing child semantics label"
           │     textDirection: ltr
           │
           └─SemanticsNode#6
             │ Rect.fromLTRB(0.0, 40.0, 844.0, 80.0)
             │ label: "second parent semantics label"
             │ textDirection: ltr
             │
             └─SemanticsNode#7
                 Rect.fromLTRB(0.0, 0.0, 844.0, 40.0)
                 label: "successful child semantics label"
                 textDirection: ltr
    
  7. self-assigned this
    on Aug 27, 2025
  8. hannah-hyj commented on Aug 27, 2025

    @hannah-hyj
    Member

    i can take a look at this one

  9. hannah-hyj commented on Aug 27, 2025

    @hannah-hyj
    Member

    looks like it is relate to SemanticsValidationResult

    For the formfield node, if we change

          containsSemantics(
              label: 'failing child semantics label')
    

    to

          containsSemantics(
              label: 'failing child semantics label',
              validationResult: SemanticsValidationResult.valid,
            ),
    

    The test will pass.

    We need to

    1. update containsSemantics to not check validationResult if it passes a null,

    2. improve the semantics tree dump, so the semantics tree will also show SemanticsValidationResult

  10. github-actions commented on Sep 12, 2025

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  11. locked as resolved and limited conversation to collaborators on Sep 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

P2Important issues not at the top of the work lista: accessibilityAccessibility, e.g. VoiceOver or TalkBack. (aka a11y)a: tests"flutter test", flutter_test, or one of our testsc: regressionIt was better in the past than it is nowfound in release: 3.32Found to occur in 3.32found in release: 3.33Found to occur in 3.33found in release: 3.35Found to occur in 3.35frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onp: material_uimaterial_ui package in flutter/packagesr: fixedIssue is closed as already fixed in a newer versionteam-accessibilityOwned by Framework Accessibility team (i.e. responsible for accessibility code in flutter/flutter)triaged-accessibilityTriaged by Framework Accessibility team

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions