@@ -11,6 +11,9 @@ import 'package:flutter_test/flutter_test.dart';
1111
1212import '../widgets/semantics_tester.dart' ;
1313
14+ // From bottom_sheet.dart.
15+ const Duration _bottomSheetExitDuration = Duration (milliseconds: 200 );
16+
1417void main () {
1518 // Regression test for https://github.com/flutter/flutter/issues/103741
1619 testWidgets ('extendBodyBehindAppBar change should not cause the body widget lose state' , (WidgetTester tester) async {
@@ -2622,6 +2625,86 @@ void main() {
26222625 matchesSemantics (label: 'BottomSheet' , hasDismissAction: false ),
26232626 );
26242627 });
2628+
2629+ // Regression test for https://github.com/flutter/flutter/issues/117004
2630+ testWidgets ('can rebuild and remove bottomSheet at the same time' , (WidgetTester tester) async {
2631+ bool themeIsLight = true ;
2632+ bool ? defaultBottomSheet = true ;
2633+ final GlobalKey bottomSheetKey1 = GlobalKey ();
2634+ final GlobalKey bottomSheetKey2 = GlobalKey ();
2635+ late StateSetter setState;
2636+
2637+ await tester.pumpWidget (
2638+ StatefulBuilder (
2639+ builder: (BuildContext context, StateSetter stateSetter) {
2640+ setState = stateSetter;
2641+ return MaterialApp (
2642+ theme: themeIsLight ? ThemeData .light () : ThemeData .dark (),
2643+ home: Scaffold (
2644+ bottomSheet: defaultBottomSheet == null
2645+ ? null
2646+ : defaultBottomSheet!
2647+ ? Container (
2648+ key: bottomSheetKey1,
2649+ width: double .infinity,
2650+ height: 100 ,
2651+ color: Colors .blue,
2652+ child: const Text ('BottomSheet' ),
2653+ )
2654+ : Container (
2655+ key: bottomSheetKey2,
2656+ width: double .infinity,
2657+ height: 100 ,
2658+ color: Colors .red,
2659+ child: const Text ('BottomSheet' ),
2660+ ),
2661+ body: const Placeholder (),
2662+ ),
2663+ );
2664+ },
2665+ ),
2666+ );
2667+
2668+ expect (find.byKey (bottomSheetKey1), findsOneWidget);
2669+ expect (find.byKey (bottomSheetKey2), findsNothing);
2670+
2671+ // Change to the other bottomSheet.
2672+ setState (() {
2673+ defaultBottomSheet = false ;
2674+ });
2675+ expect (find.byKey (bottomSheetKey1), findsOneWidget);
2676+ expect (find.byKey (bottomSheetKey2), findsNothing);
2677+ await tester.pumpAndSettle ();
2678+ expect (find.byKey (bottomSheetKey1), findsNothing);
2679+ expect (find.byKey (bottomSheetKey2), findsOneWidget);
2680+
2681+ // Set bottomSheet to null, which starts its exit animation.
2682+ setState (() {
2683+ defaultBottomSheet = null ;
2684+ });
2685+ expect (find.byKey (bottomSheetKey1), findsNothing);
2686+ expect (find.byKey (bottomSheetKey2), findsOneWidget);
2687+
2688+ // While the bottomSheet is on the way out, change the theme to cause it to
2689+ // rebuild.
2690+ setState (() {
2691+ themeIsLight = false ;
2692+ });
2693+ expect (find.byKey (bottomSheetKey1), findsNothing);
2694+ expect (find.byKey (bottomSheetKey2), findsOneWidget);
2695+
2696+ // The most recent bottomSheet remains on screen during the exit animation.
2697+ await tester.pump (_bottomSheetExitDuration);
2698+ expect (find.byKey (bottomSheetKey1), findsNothing);
2699+ expect (find.byKey (bottomSheetKey2), findsOneWidget);
2700+
2701+ // After animating out, the bottomSheet is gone.
2702+ await tester.pumpAndSettle ();
2703+ expect (find.byKey (bottomSheetKey1), findsNothing);
2704+ expect (find.byKey (bottomSheetKey2), findsNothing);
2705+
2706+ expect (tester.takeException (), isNull);
2707+ });
26252708}
26262709
26272710class _GeometryListener extends StatefulWidget {
0 commit comments