From 4f9ec547d863f6c8bd6c5c18876e541cb2835272 Mon Sep 17 00:00:00 2001 From: Sanaullah49 Date: Thu, 9 Apr 2026 12:34:59 +0500 Subject: [PATCH 1/7] Remove semantics_tester import from card_test.dart --- .../temporarily_disabled_tests/card_test.dart | 66 +++++++------------ 1 file changed, 24 insertions(+), 42 deletions(-) diff --git a/packages/material_ui/temporarily_disabled_tests/card_test.dart b/packages/material_ui/temporarily_disabled_tests/card_test.dart index 44de32308031..82baead97664 100644 --- a/packages/material_ui/temporarily_disabled_tests/card_test.dart +++ b/packages/material_ui/temporarily_disabled_tests/card_test.dart @@ -8,7 +8,6 @@ import 'package:material_ui/material_ui.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter_test/flutter_test.dart'; -import '../widgets/semantics_tester.dart'; void main() { testWidgets('Material3 - Card defaults (Elevated card)', (WidgetTester tester) async { @@ -93,7 +92,7 @@ void main() { }); testWidgets('Card can take semantic text from multiple children', (WidgetTester tester) async { - final semantics = SemanticsTester(tester); + final SemanticsHandle handle = tester.ensureSemantics(); await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -115,37 +114,32 @@ void main() { ); expect( - semantics, - hasSemantics( - TestSemantics.root( - children: [ - TestSemantics(id: 1, label: 'I am text!', textDirection: TextDirection.ltr), - TestSemantics(id: 2, label: 'Moar text!!1', textDirection: TextDirection.ltr), - TestSemantics( - id: 3, - label: 'Button', - textDirection: TextDirection.ltr, - actions: [SemanticsAction.tap, SemanticsAction.focus], - flags: [ - SemanticsFlag.hasEnabledState, - SemanticsFlag.isButton, - SemanticsFlag.isEnabled, - SemanticsFlag.isFocusable, - ], - ), - ], - ), - ignoreTransform: true, - ignoreRect: true, + tester.getSemantics(find.text('I am text!')), + matchesSemantics(label: 'I am text!', textDirection: TextDirection.ltr), + ); + expect( + tester.getSemantics(find.text('Moar text!!1')), + matchesSemantics(label: 'Moar text!!1', textDirection: TextDirection.ltr), + ); + expect( + tester.getSemantics(find.widgetWithText(ElevatedButton, 'Button')), + matchesSemantics( + label: 'Button', + textDirection: TextDirection.ltr, + hasTapAction: true, + hasFocusAction: true, + hasEnabledState: true, + isButton: true, + isEnabled: true, + isFocusable: true, ), ); - semantics.dispose(); + handle.dispose(); }); testWidgets('Card merges children when it is a semanticContainer', (WidgetTester tester) async { - final semantics = SemanticsTester(tester); - debugResetSemanticsIdCounter(); + final SemanticsHandle handle = tester.ensureSemantics(); await tester.pumpWidget( const Directionality( @@ -161,23 +155,11 @@ void main() { ); expect( - semantics, - hasSemantics( - TestSemantics.root( - children: [ - TestSemantics( - id: 1, - label: 'First child\nSecond child', - textDirection: TextDirection.ltr, - ), - ], - ), - ignoreTransform: true, - ignoreRect: true, - ), + tester.getSemantics(find.byType(Card)), + matchesSemantics(label: 'First child\nSecond child', textDirection: TextDirection.ltr), ); - semantics.dispose(); + handle.dispose(); }); testWidgets('Card margin', (WidgetTester tester) async { From 4be58a352d81424a91f4dcb8a6ae8df4213fe07d Mon Sep 17 00:00:00 2001 From: Sanaullah49 Date: Thu, 9 Apr 2026 13:04:29 +0500 Subject: [PATCH 2/7] Address review feedback on Card semantics tests --- .../temporarily_disabled_tests/card_test.dart | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/material_ui/temporarily_disabled_tests/card_test.dart b/packages/material_ui/temporarily_disabled_tests/card_test.dart index 82baead97664..f30f97c30902 100644 --- a/packages/material_ui/temporarily_disabled_tests/card_test.dart +++ b/packages/material_ui/temporarily_disabled_tests/card_test.dart @@ -93,6 +93,12 @@ void main() { testWidgets('Card can take semantic text from multiple children', (WidgetTester tester) async { final SemanticsHandle handle = tester.ensureSemantics(); + var semanticsDisposed = false; + addTearDown(() { + if (!semanticsDisposed) { + handle.dispose(); + } + }); await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -136,10 +142,18 @@ void main() { ); handle.dispose(); + semanticsDisposed = true; + }); testWidgets('Card merges children when it is a semanticContainer', (WidgetTester tester) async { final SemanticsHandle handle = tester.ensureSemantics(); + var semanticsDisposed = false; + addTearDown(() { + if (!semanticsDisposed) { + handle.dispose(); + } + }); await tester.pumpWidget( const Directionality( @@ -160,6 +174,8 @@ void main() { ); handle.dispose(); + semanticsDisposed = true; + }); testWidgets('Card margin', (WidgetTester tester) async { From f34c1221151604529234e920a1c8126180cf62de Mon Sep 17 00:00:00 2001 From: Sanaullah49 Date: Thu, 9 Apr 2026 14:49:40 +0500 Subject: [PATCH 3/7] Use addTearDown for card semantics handles --- .../temporarily_disabled_tests/card_test.dart | 22 ++----------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/packages/material_ui/temporarily_disabled_tests/card_test.dart b/packages/material_ui/temporarily_disabled_tests/card_test.dart index f30f97c30902..99c4769f97f8 100644 --- a/packages/material_ui/temporarily_disabled_tests/card_test.dart +++ b/packages/material_ui/temporarily_disabled_tests/card_test.dart @@ -93,12 +93,7 @@ void main() { testWidgets('Card can take semantic text from multiple children', (WidgetTester tester) async { final SemanticsHandle handle = tester.ensureSemantics(); - var semanticsDisposed = false; - addTearDown(() { - if (!semanticsDisposed) { - handle.dispose(); - } - }); + addTearDown(handle.dispose); await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -140,20 +135,11 @@ void main() { isFocusable: true, ), ); - - handle.dispose(); - semanticsDisposed = true; - }); testWidgets('Card merges children when it is a semanticContainer', (WidgetTester tester) async { final SemanticsHandle handle = tester.ensureSemantics(); - var semanticsDisposed = false; - addTearDown(() { - if (!semanticsDisposed) { - handle.dispose(); - } - }); + addTearDown(handle.dispose); await tester.pumpWidget( const Directionality( @@ -172,10 +158,6 @@ void main() { tester.getSemantics(find.byType(Card)), matchesSemantics(label: 'First child\nSecond child', textDirection: TextDirection.ltr), ); - - handle.dispose(); - semanticsDisposed = true; - }); testWidgets('Card margin', (WidgetTester tester) async { From 07ad7c9329894962a577ae2f9da98de9ba23821f Mon Sep 17 00:00:00 2001 From: Sanaullah49 Date: Tue, 28 Apr 2026 15:46:59 +0500 Subject: [PATCH 4/7] Dispose card semantics handles with try-finally --- .../temporarily_disabled_tests/card_test.dart | 109 +++++++++--------- 1 file changed, 57 insertions(+), 52 deletions(-) diff --git a/packages/material_ui/temporarily_disabled_tests/card_test.dart b/packages/material_ui/temporarily_disabled_tests/card_test.dart index 99c4769f97f8..bfd14480491d 100644 --- a/packages/material_ui/temporarily_disabled_tests/card_test.dart +++ b/packages/material_ui/temporarily_disabled_tests/card_test.dart @@ -93,71 +93,76 @@ void main() { testWidgets('Card can take semantic text from multiple children', (WidgetTester tester) async { final SemanticsHandle handle = tester.ensureSemantics(); - addTearDown(handle.dispose); - await tester.pumpWidget( - Directionality( - textDirection: TextDirection.ltr, - child: Material( - child: Center( - child: Card( - semanticContainer: false, - child: Column( - children: [ - const Text('I am text!'), - const Text('Moar text!!1'), - ElevatedButton(onPressed: () {}, child: const Text('Button')), - ], + try { + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: Material( + child: Center( + child: Card( + semanticContainer: false, + child: Column( + children: [ + const Text('I am text!'), + const Text('Moar text!!1'), + ElevatedButton(onPressed: () {}, child: const Text('Button')), + ], + ), ), ), ), ), - ), - ); + ); - expect( - tester.getSemantics(find.text('I am text!')), - matchesSemantics(label: 'I am text!', textDirection: TextDirection.ltr), - ); - expect( - tester.getSemantics(find.text('Moar text!!1')), - matchesSemantics(label: 'Moar text!!1', textDirection: TextDirection.ltr), - ); - expect( - tester.getSemantics(find.widgetWithText(ElevatedButton, 'Button')), - matchesSemantics( - label: 'Button', - textDirection: TextDirection.ltr, - hasTapAction: true, - hasFocusAction: true, - hasEnabledState: true, - isButton: true, - isEnabled: true, - isFocusable: true, - ), - ); + expect( + tester.getSemantics(find.text('I am text!')), + matchesSemantics(label: 'I am text!', textDirection: TextDirection.ltr), + ); + expect( + tester.getSemantics(find.text('Moar text!!1')), + matchesSemantics(label: 'Moar text!!1', textDirection: TextDirection.ltr), + ); + expect( + tester.getSemantics(find.widgetWithText(ElevatedButton, 'Button')), + matchesSemantics( + label: 'Button', + textDirection: TextDirection.ltr, + hasTapAction: true, + hasFocusAction: true, + hasEnabledState: true, + isButton: true, + isEnabled: true, + isFocusable: true, + ), + ); + } finally { + handle.dispose(); + } }); testWidgets('Card merges children when it is a semanticContainer', (WidgetTester tester) async { final SemanticsHandle handle = tester.ensureSemantics(); - addTearDown(handle.dispose); - - await tester.pumpWidget( - const Directionality( - textDirection: TextDirection.ltr, - child: Material( - child: Center( - child: Card( - child: Column(children: [Text('First child'), Text('Second child')]), + try { + await tester.pumpWidget( + const Directionality( + textDirection: TextDirection.ltr, + child: Material( + child: Center( + child: Card( + child: Column(children: [Text('First child'), Text('Second child')]), + ), ), ), ), - ), - ); + ); - expect( - tester.getSemantics(find.byType(Card)), - matchesSemantics(label: 'First child\nSecond child', textDirection: TextDirection.ltr), - ); + expect( + tester.getSemantics(find.byType(Card)), + matchesSemantics(label: 'First child\nSecond child', textDirection: TextDirection.ltr), + ); + } finally { + handle.dispose(); + } }); testWidgets('Card margin', (WidgetTester tester) async { From bd643948478e9f6c4f2ee957de887061a4ea8b46 Mon Sep 17 00:00:00 2001 From: Sanaullah49 Date: Tue, 5 May 2026 10:25:07 +0500 Subject: [PATCH 5/7] Address review feedback: use addTearDown instead of try/finally Replace manual SemanticsHandle + try/finally + dispose with the addTearDown pattern as requested by @justinmc and @gemini-code-assist. --- .../temporarily_disabled_tests/card_test.dart | 110 ++++++++---------- 1 file changed, 51 insertions(+), 59 deletions(-) diff --git a/packages/material_ui/temporarily_disabled_tests/card_test.dart b/packages/material_ui/temporarily_disabled_tests/card_test.dart index bfd14480491d..4b87e53aa90d 100644 --- a/packages/material_ui/temporarily_disabled_tests/card_test.dart +++ b/packages/material_ui/temporarily_disabled_tests/card_test.dart @@ -92,77 +92,69 @@ void main() { }); testWidgets('Card can take semantic text from multiple children', (WidgetTester tester) async { - final SemanticsHandle handle = tester.ensureSemantics(); - try { - await tester.pumpWidget( - Directionality( - textDirection: TextDirection.ltr, - child: Material( - child: Center( - child: Card( - semanticContainer: false, - child: Column( - children: [ - const Text('I am text!'), - const Text('Moar text!!1'), - ElevatedButton(onPressed: () {}, child: const Text('Button')), - ], - ), + addTearDown(tester.ensureSemantics().dispose); + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: Material( + child: Center( + child: Card( + semanticContainer: false, + child: Column( + children: [ + const Text('I am text!'), + const Text('Moar text!!1'), + ElevatedButton(onPressed: () {}, child: const Text('Button')), + ], ), ), ), ), - ); + ), + ); - expect( - tester.getSemantics(find.text('I am text!')), - matchesSemantics(label: 'I am text!', textDirection: TextDirection.ltr), - ); - expect( - tester.getSemantics(find.text('Moar text!!1')), - matchesSemantics(label: 'Moar text!!1', textDirection: TextDirection.ltr), - ); - expect( - tester.getSemantics(find.widgetWithText(ElevatedButton, 'Button')), - matchesSemantics( - label: 'Button', - textDirection: TextDirection.ltr, - hasTapAction: true, - hasFocusAction: true, - hasEnabledState: true, - isButton: true, - isEnabled: true, - isFocusable: true, - ), - ); - } finally { - handle.dispose(); - } + expect( + tester.getSemantics(find.text('I am text!')), + matchesSemantics(label: 'I am text!', textDirection: TextDirection.ltr), + ); + expect( + tester.getSemantics(find.text('Moar text!!1')), + matchesSemantics(label: 'Moar text!!1', textDirection: TextDirection.ltr), + ); + expect( + tester.getSemantics(find.widgetWithText(ElevatedButton, 'Button')), + matchesSemantics( + label: 'Button', + textDirection: TextDirection.ltr, + hasTapAction: true, + hasFocusAction: true, + hasEnabledState: true, + isButton: true, + isEnabled: true, + isFocusable: true, + ), + ); }); testWidgets('Card merges children when it is a semanticContainer', (WidgetTester tester) async { - final SemanticsHandle handle = tester.ensureSemantics(); - try { - await tester.pumpWidget( - const Directionality( - textDirection: TextDirection.ltr, - child: Material( - child: Center( - child: Card( - child: Column(children: [Text('First child'), Text('Second child')]), - ), + addTearDown(tester.ensureSemantics().dispose); + await tester.pumpWidget( + const Directionality( + textDirection: TextDirection.ltr, + child: Material( + child: Center( + child: Card( + child: Column(children: [Text('First child'), Text('Second child')]), ), ), ), - ); + ), + ); - expect( - tester.getSemantics(find.byType(Card)), - matchesSemantics(label: 'First child\nSecond child', textDirection: TextDirection.ltr), - ); - } finally { - handle.dispose(); - } + expect( + tester.getSemantics(find.byType(Card)), + matchesSemantics(label: 'First child\nSecond child', textDirection: TextDirection.ltr), + ); }); testWidgets('Card margin', (WidgetTester tester) async { From 2b1a712634e2e2c1cd73145db4ff43c39d882776 Mon Sep 17 00:00:00 2001 From: Sanaullah49 Date: Wed, 6 May 2026 10:32:51 +0500 Subject: [PATCH 6/7] Remove unnecessary rendering.dart import from card_test.dart --- packages/material_ui/temporarily_disabled_tests/card_test.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/material_ui/temporarily_disabled_tests/card_test.dart b/packages/material_ui/temporarily_disabled_tests/card_test.dart index 4b87e53aa90d..34a3e0e31c7f 100644 --- a/packages/material_ui/temporarily_disabled_tests/card_test.dart +++ b/packages/material_ui/temporarily_disabled_tests/card_test.dart @@ -6,7 +6,6 @@ 'This file is skipped due to a cross-import that needs to be fixed. Tracked in https://github.com/flutter/flutter/issues/177028.', ) import 'package:material_ui/material_ui.dart'; -import 'package:flutter/rendering.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { From 00e90fc776c80285515d341a154436e9e6e7ac02 Mon Sep 17 00:00:00 2001 From: Sanaullah49 Date: Fri, 15 May 2026 12:23:05 +0500 Subject: [PATCH 7/7] Fix leaking SemanticsHandle in card semantics tests testWidgets has semanticsEnabled: true by default, which creates and disposes a SemanticsHandle automatically. The addTearDown registered an extra handle that runs AFTER the framework's _verifySemanticsHandlesWereDisposed check, causing it to fail with 'A SemanticsHandle was active at the end of the test.' Removing the addTearDown line - tester.getSemantics works against the auto-created handle. --- packages/material_ui/temporarily_disabled_tests/card_test.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/material_ui/temporarily_disabled_tests/card_test.dart b/packages/material_ui/temporarily_disabled_tests/card_test.dart index 34a3e0e31c7f..046b0e5ca9eb 100644 --- a/packages/material_ui/temporarily_disabled_tests/card_test.dart +++ b/packages/material_ui/temporarily_disabled_tests/card_test.dart @@ -91,7 +91,6 @@ void main() { }); testWidgets('Card can take semantic text from multiple children', (WidgetTester tester) async { - addTearDown(tester.ensureSemantics().dispose); await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -136,7 +135,6 @@ void main() { }); testWidgets('Card merges children when it is a semanticContainer', (WidgetTester tester) async { - addTearDown(tester.ensureSemantics().dispose); await tester.pumpWidget( const Directionality( textDirection: TextDirection.ltr,