// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart' show DragStartBehavior;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';

import '../widgets/semantics_tester.dart';

// From bottom_sheet.dart.
const Duration _bottomSheetExitDuration = Duration(milliseconds: 200);

void main() {
  // Regression test for https://github.com/flutter/flutter/issues/103741
  testWidgets('extendBodyBehindAppBar change should not cause the body widget lose state', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    Widget buildFrame({required bool extendBodyBehindAppBar}) {
      return MediaQuery(
        data: const MediaQueryData(),
        child: Directionality(
          textDirection: TextDirection.ltr,
          child: Scaffold(
            extendBodyBehindAppBar: extendBodyBehindAppBar,
            resizeToAvoidBottomInset: false,
            body: SingleChildScrollView(
              controller: controller,
              child: const FlutterLogo(
                size: 1107,
              ),
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildFrame(extendBodyBehindAppBar: true));
    expect(controller.position.pixels, 0.0);

    controller.jumpTo(100.0);
    await tester.pump();
    expect(controller.position.pixels, 100.0);

    await tester.pumpWidget(buildFrame(extendBodyBehindAppBar: false));
    expect(controller.position.pixels, 100.0);
  });

  testWidgets('Scaffold drawer callback test', (WidgetTester tester) async {
    bool isDrawerOpen = false;
    bool isEndDrawerOpen = false;

    await tester.pumpWidget(MaterialApp(
      home: Scaffold(
        drawer: Container(
          color: Colors.blue,
        ),
        onDrawerChanged: (bool isOpen) {
          isDrawerOpen = isOpen;
        },
        endDrawer: Container(
          color: Colors.green,
        ),
        onEndDrawerChanged: (bool isOpen) {
          isEndDrawerOpen = isOpen;
        },
        body: Container(),
      ),
    ));

    final ScaffoldState scaffoldState = tester.state(find.byType(Scaffold));

    scaffoldState.openDrawer();
    await tester.pumpAndSettle();
    expect(isDrawerOpen, true);
    scaffoldState.openEndDrawer();
    await tester.pumpAndSettle();
    expect(isDrawerOpen, false);

    scaffoldState.openEndDrawer();
    await tester.pumpAndSettle();
    expect(isEndDrawerOpen, true);
    scaffoldState.openDrawer();
    await tester.pumpAndSettle();
    expect(isEndDrawerOpen, false);
  });

  testWidgets('Scaffold drawer callback test - only call when changed', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/87914
    bool onDrawerChangedCalled = false;
    bool onEndDrawerChangedCalled = false;

    await tester.pumpWidget(MaterialApp(
      home: Scaffold(
        drawer: Container(
          color: Colors.blue,
        ),
        onDrawerChanged: (bool isOpen) {
          onDrawerChangedCalled = true;
        },
        endDrawer: Container(
          color: Colors.green,
        ),
        onEndDrawerChanged: (bool isOpen) {
          onEndDrawerChangedCalled = true;
        },
        body: Container(),
      ),
    ));

    await tester.flingFrom(Offset.zero, const Offset(10.0, 0.0), 10.0);
    expect(onDrawerChangedCalled, false);

    await tester.pumpAndSettle();

    final double width = tester.getSize(find.byType(MaterialApp)).width;
    await tester.flingFrom(Offset(width - 1, 0.0), const Offset(-10.0, 0.0), 10.0);
    await tester.pumpAndSettle();
    expect(onEndDrawerChangedCalled, false);
  });

  testWidgets('Scaffold control test', (WidgetTester tester) async {
    final Key bodyKey = UniqueKey();
    Widget boilerplate(Widget child) {
      return Localizations(
        locale: const Locale('en', 'us'),
        delegates: const <LocalizationsDelegate<dynamic>>[
          DefaultWidgetsLocalizations.delegate,
          DefaultMaterialLocalizations.delegate,
        ],
        child: Directionality(
          textDirection: TextDirection.ltr,
          child: child,
        ),
      );
    }
    await tester.pumpWidget(boilerplate(Scaffold(
        appBar: AppBar(title: const Text('Title')),
        body: Container(key: bodyKey),
      ),
    ));
    expect(tester.takeException(), isFlutterError);

    await tester.pumpWidget(MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Title')),
        body: Container(key: bodyKey),
      ),
    ));
    RenderBox bodyBox = tester.renderObject(find.byKey(bodyKey));
    expect(bodyBox.size, equals(const Size(800.0, 544.0)));

    await tester.pumpWidget(boilerplate(MediaQuery(
        data: const MediaQueryData(viewInsets: EdgeInsets.only(bottom: 100.0)),
        child: Scaffold(
          appBar: AppBar(title: const Text('Title')),
          body: Container(key: bodyKey),
        ),
      ),
    ));

    bodyBox = tester.renderObject(find.byKey(bodyKey));
    expect(bodyBox.size, equals(const Size(800.0, 444.0)));

    await tester.pumpWidget(boilerplate(MediaQuery(
      data: const MediaQueryData(viewInsets: EdgeInsets.only(bottom: 100.0)),
      child: Scaffold(
        appBar: AppBar(title: const Text('Title')),
        body: Container(key: bodyKey),
        resizeToAvoidBottomInset: false,
      ),
    )));

    bodyBox = tester.renderObject(find.byKey(bodyKey));
    expect(bodyBox.size, equals(const Size(800.0, 544.0)));
  });

  testWidgets('Scaffold large bottom padding test', (WidgetTester tester) async {
    final Key bodyKey = UniqueKey();

    Widget boilerplate(Widget child) {
      return Localizations(
        locale: const Locale('en', 'us'),
        delegates: const <LocalizationsDelegate<dynamic>>[
          DefaultWidgetsLocalizations.delegate,
          DefaultMaterialLocalizations.delegate,
        ],
        child: Directionality(
          textDirection: TextDirection.ltr,
          child: child,
        ),
      );
    }

    await tester.pumpWidget(boilerplate(MediaQuery(
      data: const MediaQueryData(
        viewInsets: EdgeInsets.only(bottom: 700.0),
      ),
      child: Scaffold(
        body: Container(key: bodyKey),
      ),
    )));

    final RenderBox bodyBox = tester.renderObject(find.byKey(bodyKey));
    expect(bodyBox.size, equals(const Size(800.0, 0.0)));

    await tester.pumpWidget(boilerplate(MediaQuery(
        data: const MediaQueryData(
          viewInsets: EdgeInsets.only(bottom: 500.0),
        ),
        child: Scaffold(
          body: Container(key: bodyKey),
        ),
      ),
    ));

    expect(bodyBox.size, equals(const Size(800.0, 100.0)));

    await tester.pumpWidget(boilerplate(MediaQuery(
        data: const MediaQueryData(
          viewInsets: EdgeInsets.only(bottom: 580.0),
        ),
        child: Scaffold(
          appBar: AppBar(
            title: const Text('Title'),
          ),
          body: Container(key: bodyKey),
        ),
      ),
    ));

    expect(bodyBox.size, equals(const Size(800.0, 0.0)));
  });

  testWidgets('Floating action entrance/exit animation', (WidgetTester tester) async {
    await tester.pumpWidget(const MaterialApp(home: Scaffold(
      floatingActionButton: FloatingActionButton(
        key: Key('one'),
        onPressed: null,
        child: Text('1'),
      ),
    )));

    expect(tester.binding.transientCallbackCount, 0);

    await tester.pumpWidget(const MaterialApp(home: Scaffold(
      floatingActionButton: FloatingActionButton(
        key: Key('two'),
        onPressed: null,
        child: Text('2'),
      ),
    )));

    expect(tester.binding.transientCallbackCount, greaterThan(0));
    await tester.pumpWidget(Container());
    expect(tester.binding.transientCallbackCount, 0);

    await tester.pumpWidget(const MaterialApp(home: Scaffold()));

    expect(tester.binding.transientCallbackCount, 0);

    await tester.pumpWidget(const MaterialApp(home: Scaffold(
      floatingActionButton: FloatingActionButton(
        key: Key('one'),
        onPressed: null,
        child: Text('1'),
      ),
    )));

    expect(tester.binding.transientCallbackCount, greaterThan(0));
  });

  testWidgets('Floating action button directionality', (WidgetTester tester) async {
    Widget build(TextDirection textDirection) {
      return Directionality(
        textDirection: textDirection,
        child: const MediaQuery(
          data: MediaQueryData(
            viewInsets: EdgeInsets.only(bottom: 200.0),
          ),
          child: Scaffold(
            floatingActionButton: FloatingActionButton(
              onPressed: null,
              child: Text('1'),
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(build(TextDirection.ltr));

    expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(756.0, 356.0));

    await tester.pumpWidget(build(TextDirection.rtl));
    expect(tester.binding.transientCallbackCount, 0);

    expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(44.0, 356.0));
  });

  testWidgets('Floating Action Button bottom padding not consumed by viewInsets', (WidgetTester tester) async {
    final Widget child = Directionality(
      textDirection: TextDirection.ltr,
      child: Scaffold(
        resizeToAvoidBottomInset: false,
        body: Container(),
        floatingActionButton: const Placeholder(),
      ),
    );

    await tester.pumpWidget(
      MediaQuery(
        data: const MediaQueryData(
          viewPadding: EdgeInsets.only(bottom: 20.0),
        ),
        child: child,
      ),
    );
    final Offset initialPoint = tester.getCenter(find.byType(Placeholder));
    expect(
      tester.getBottomLeft(find.byType(Placeholder)).dy,
      moreOrLessEquals(600.0 - 20.0 - kFloatingActionButtonMargin)
    );

    // Consume bottom padding - as if by the keyboard opening
    await tester.pumpWidget(
      MediaQuery(
        data: const MediaQueryData(
          viewPadding: EdgeInsets.only(bottom: 20),
          viewInsets: EdgeInsets.only(bottom: 300),
        ),
        child: child,
      ),
    );
    final Offset finalPoint = tester.getCenter(find.byType(Placeholder));
    expect(initialPoint, finalPoint);
  });

  testWidgets('viewPadding change should trigger _ScaffoldLayout re-layout', (WidgetTester tester) async {
    Widget buildFrame(EdgeInsets viewPadding) {
      return MediaQuery(
        data: MediaQueryData(
          viewPadding: viewPadding,
        ),
        child: Directionality(
          textDirection: TextDirection.ltr,
          child: Scaffold(
            resizeToAvoidBottomInset: false,
            body: Container(),
            floatingActionButton: const Placeholder(),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildFrame(const EdgeInsets.only(bottom: 300)));

    final RenderBox renderBox = tester.renderObject<RenderBox>(find.byType(CustomMultiChildLayout));
    expect(renderBox.debugNeedsLayout, false);

    await tester.pumpWidget(
      buildFrame(const EdgeInsets.only(bottom: 400)),
      null,
      EnginePhase.build,
    );

    expect(renderBox.debugNeedsLayout, true);
  });

  testWidgets('Drawer scrolling', (WidgetTester tester) async {
    final Key drawerKey = UniqueKey();
    const double appBarHeight = 256.0;

    final ScrollController scrollOffset = ScrollController();

    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          drawer: Drawer(
            key: drawerKey,
            child: ListView(
              dragStartBehavior: DragStartBehavior.down,
              controller: scrollOffset,
              children: List<Widget>.generate(10,
                (int index) => SizedBox(height: 100.0, child: Text('D$index')),
              ),
            ),
          ),
          body: CustomScrollView(
            slivers: <Widget>[
              const SliverAppBar(
                pinned: true,
                expandedHeight: appBarHeight,
                title: Text('Title'),
                flexibleSpace: FlexibleSpaceBar(title: Text('Title')),
              ),
              SliverPadding(
                padding: const EdgeInsets.only(top: appBarHeight),
                sliver: SliverList(
                  delegate: SliverChildListDelegate(List<Widget>.generate(
                    10, (int index) => SizedBox(height: 100.0, child: Text('B$index')),
                  )),
                ),
              ),
            ],
          ),
        ),
      ),
    );

    final ScaffoldState state = tester.firstState(find.byType(Scaffold));
    state.openDrawer();

    await tester.pump();
    await tester.pump(const Duration(seconds: 1));

    expect(scrollOffset.offset, 0.0);

    const double scrollDelta = 80.0;
    await tester.drag(find.byKey(drawerKey), const Offset(0.0, -scrollDelta));
    await tester.pump();

    expect(scrollOffset.offset, scrollDelta);

    final RenderBox renderBox = tester.renderObject(find.byType(AppBar));
    expect(renderBox.size.height, equals(appBarHeight));
  });

  Widget buildStatusBarTestApp(TargetPlatform? platform) {
    return MaterialApp(
      theme: ThemeData(platform: platform),
      home: MediaQuery(
        data: const MediaQueryData(padding: EdgeInsets.only(top: 25.0)), // status bar
        child: Scaffold(
          body: CustomScrollView(
            primary: true,
            slivers: <Widget>[
              const SliverAppBar(
                title: Text('Title'),
              ),
              SliverList(
                delegate: SliverChildListDelegate(List<Widget>.generate(
                  20, (int index) => SizedBox(height: 100.0, child: Text('$index')),
                )),
              ),
            ],
          ),
        ),
      ),
    );
  }

  testWidgets('Tapping the status bar scrolls to top', (WidgetTester tester) async {
    await tester.pumpWidget(buildStatusBarTestApp(debugDefaultTargetPlatformOverride));
    final ScrollableState scrollable = tester.state(find.byType(Scrollable));
    scrollable.position.jumpTo(500.0);
    expect(scrollable.position.pixels, equals(500.0));
    await tester.tapAt(const Offset(100.0, 10.0));
    await tester.pumpAndSettle();
    expect(scrollable.position.pixels, equals(0.0));
  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));

  testWidgets('Tapping the status bar scrolls to top with ease out curve animation', (WidgetTester tester) async {
    const int duration = 1000;
    final List<double> stops = <double>[0.842, 0.959, 0.993, 1.0];
    const double scrollOffset = 1000;

    await tester.pumpWidget(buildStatusBarTestApp(debugDefaultTargetPlatformOverride));
    final ScrollableState scrollable = tester.state(find.byType(Scrollable));
    scrollable.position.jumpTo(scrollOffset);
    await tester.tapAt(const Offset(100.0, 10.0));

    await tester.pump(Duration.zero);
    expect(scrollable.position.pixels, equals(scrollOffset));

    for (int i = 0; i < stops.length; i++) {
      await tester.pump( Duration(milliseconds: duration ~/ stops.length));
      // Scroll pixel position is very long double, compare with floored int
      // pixel position
      expect(
        scrollable.position.pixels.toInt(),
        equals(
         (scrollOffset * (1 - stops[i])).toInt()
        )
      );
    }

    // Finally stops at the top.
    expect(scrollable.position.pixels, equals(0.0));
  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));

  testWidgets('Tapping the status bar does not scroll to top', (WidgetTester tester) async {
    await tester.pumpWidget(buildStatusBarTestApp(TargetPlatform.android));
    final ScrollableState scrollable = tester.state(find.byType(Scrollable));
    scrollable.position.jumpTo(500.0);
    expect(scrollable.position.pixels, equals(500.0));
    await tester.tapAt(const Offset(100.0, 10.0));
    await tester.pump();
    await tester.pump(const Duration(seconds: 1));
    expect(scrollable.position.pixels, equals(500.0));
  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android }));

  testWidgets('Bottom sheet cannot overlap app bar', (WidgetTester tester) async {
    final Key sheetKey = UniqueKey();

    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(platform: TargetPlatform.android),
        home: Scaffold(
          appBar: AppBar(
            title: const Text('Title'),
          ),
          body: Builder(
            builder: (BuildContext context) {
              return GestureDetector(
                onTap: () {
                  Scaffold.of(context).showBottomSheet<void>((BuildContext context) {
                    return Container(
                      key: sheetKey,
                      color: Colors.blue[500],
                    );
                  });
                },
                child: const Text('X'),
              );
            },
          ),
        ),
      ),
    );
    await tester.tap(find.text('X'));
    await tester.pump(); // start animation
    await tester.pump(const Duration(seconds: 1));

    final RenderBox appBarBox = tester.renderObject(find.byType(AppBar));
    final RenderBox sheetBox = tester.renderObject(find.byKey(sheetKey));

    final Offset appBarBottomRight = appBarBox.localToGlobal(appBarBox.size.bottomRight(Offset.zero));
    final Offset sheetTopRight = sheetBox.localToGlobal(sheetBox.size.topRight(Offset.zero));

    expect(appBarBottomRight, equals(sheetTopRight));
  });

  testWidgets('BottomSheet bottom padding is not consumed by viewInsets', (WidgetTester tester) async {
    final Widget child = Directionality(
      textDirection: TextDirection.ltr,
      child: Scaffold(
        resizeToAvoidBottomInset: false,
        body: Container(),
        bottomSheet: const Placeholder(),
      ),
    );

    await tester.pumpWidget(
      MediaQuery(
        data: const MediaQueryData(
          padding: EdgeInsets.only(bottom: 20.0),
        ),
        child: child,
      ),
    );
    final Offset initialPoint = tester.getCenter(find.byType(Placeholder));
    // Consume bottom padding - as if by the keyboard opening
    await tester.pumpWidget(
      MediaQuery(
        data: const MediaQueryData(
          viewPadding: EdgeInsets.only(bottom: 20),
          viewInsets: EdgeInsets.only(bottom: 300),
        ),
        child: child,
      ),
    );
    final Offset finalPoint = tester.getCenter(find.byType(Placeholder));
    expect(initialPoint, finalPoint);
  });

  testWidgets('Persistent bottom buttons are persistent', (WidgetTester tester) async {
    bool didPressButton = false;
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: SingleChildScrollView(
            child: Container(
              color: Colors.amber[500],
              height: 5000.0,
              child: const Text('body'),
            ),
          ),
          persistentFooterButtons: <Widget>[
            TextButton(
              onPressed: () {
                didPressButton = true;
              },
              child: const Text('X'),
            ),
          ],
        ),
      ),
    );

    await tester.drag(find.byType(SingleChildScrollView), const Offset(0.0, -1000.0));
    expect(didPressButton, isFalse);
    await tester.tap(find.text('X'));
    expect(didPressButton, isTrue);
  });

  testWidgets('Persistent bottom buttons alignment', (WidgetTester tester) async {
    Widget buildApp(AlignmentDirectional persistentAligment) {
      return MaterialApp(
          home: Scaffold(
            body: SingleChildScrollView(
              child: Container(
                color: Colors.amber[500],
                height: 5000.0,
                child: const Text('body'),
              ),
            ),
            persistentFooterAlignment: persistentAligment,
            persistentFooterButtons: <Widget>[
              TextButton(
                onPressed: () { },
                child: const Text('X'),
              ),
            ],
          ),
      );
    }

    await tester.pumpWidget(buildApp(AlignmentDirectional.centerEnd));
    Finder footerButton = find.byType(TextButton);
    expect(tester.getTopRight(footerButton).dx, 800.0 - 8.0);

    await tester.pumpWidget(buildApp(AlignmentDirectional.center));
    footerButton = find.byType(TextButton);
    expect(tester.getCenter(footerButton).dx, 800.0 / 2);

    await tester.pumpWidget(buildApp(AlignmentDirectional.centerStart));
    footerButton = find.byType(TextButton);
    expect(tester.getTopLeft(footerButton).dx, 8.0);
  });

  testWidgets('Persistent bottom buttons apply media padding', (WidgetTester tester) async {
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: MediaQuery(
          data: const MediaQueryData(
            padding: EdgeInsets.fromLTRB(10.0, 20.0, 30.0, 40.0),
          ),
          child: Scaffold(
            body: SingleChildScrollView(
              child: Container(
                color: Colors.amber[500],
                height: 5000.0,
                child: const Text('body'),
              ),
            ),
            persistentFooterButtons: const <Widget>[Placeholder()],
          ),
        ),
      ),
    );

    final Finder buttonsBar = find.ancestor(of: find.byType(OverflowBar), matching: find.byType(Padding)).first;
    expect(tester.getBottomLeft(buttonsBar), const Offset(10.0, 560.0));
    expect(tester.getBottomRight(buttonsBar), const Offset(770.0, 560.0));
  });

  testWidgets('persistentFooterButtons with bottomNavigationBar apply SafeArea properly', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/pull/92039
    await tester.pumpWidget(
      MaterialApp(
        home: MediaQuery(
          data: const MediaQueryData(
            // Representing a navigational notch at the bottom of the screen
            viewPadding: EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 40.0),
          ),
          child: Scaffold(
            body: SingleChildScrollView(
              child: Container(
                color: Colors.amber[500],
                height: 5000.0,
                child: const Text('body'),
              ),
            ),
            bottomNavigationBar: BottomNavigationBar(
              items: const <BottomNavigationBarItem>[
                BottomNavigationBarItem(
                  icon: Icon(Icons.home),
                  label: 'Home',
                ),
                BottomNavigationBarItem(
                  icon: Icon(Icons.business),
                  label: 'Business',
                ),
                BottomNavigationBarItem(
                  icon: Icon(Icons.school),
                  label: 'School',
                ),
              ],
            ),
            persistentFooterButtons: const <Widget>[Placeholder()],
          ),
        ),
      ),
    );

    final Finder buttonsBar = find.ancestor(of: find.byType(OverflowBar), matching: find.byType(Padding)).first;
    // The SafeArea of the persistentFooterButtons should not pad below them
    // since they are stacked on top of the bottomNavigationBar. The
    // bottomNavigationBar will handle the padding instead.
    // 488 represents the height of the persistentFooterButtons, with the bottom
    // of the screen being 600. If the 40 pixels of bottom padding were being
    // errantly applied, the buttons would be higher (448).
    expect(tester.getTopLeft(buttonsBar), const Offset(0.0, 488.0));
  });

  testWidgets('Persistent bottom buttons bottom padding is not consumed by viewInsets', (WidgetTester tester) async {
    final Widget child = Directionality(
      textDirection: TextDirection.ltr,
      child: Scaffold(
        resizeToAvoidBottomInset: false,
        body: Container(),
        persistentFooterButtons: const <Widget>[Placeholder()],
      ),
    );

    await tester.pumpWidget(
      MediaQuery(
        data: const MediaQueryData(
          padding: EdgeInsets.only(bottom: 20.0),
        ),
        child: child,
      ),
    );
    final Offset initialPoint = tester.getCenter(find.byType(Placeholder));
    // Consume bottom padding - as if by the keyboard opening
    await tester.pumpWidget(
      MediaQuery(
        data: const MediaQueryData(
          viewPadding: EdgeInsets.only(bottom: 20),
          viewInsets: EdgeInsets.only(bottom: 300),
        ),
        child: child,
      ),
    );
    final Offset finalPoint = tester.getCenter(find.byType(Placeholder));
    expect(initialPoint, finalPoint);
  });

  group('back arrow', () {
    Future<void> expectBackIcon(WidgetTester tester, IconData expectedIcon) async {
      final GlobalKey rootKey = GlobalKey();
      final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
        '/': (_) => Container(key: rootKey, child: const Text('Home')),
        '/scaffold': (_) => Scaffold(
            appBar: AppBar(),
            body: const Text('Scaffold'),
        ),
      };
      await tester.pumpWidget(MaterialApp(routes: routes));

      Navigator.pushNamed(rootKey.currentContext!, '/scaffold');
      await tester.pump();
      await tester.pump(const Duration(seconds: 1));

      final Icon icon = tester.widget(find.byType(Icon));
      expect(icon.icon, expectedIcon);
    }

    testWidgets('Back arrow uses correct default', (WidgetTester tester) async {
      await expectBackIcon(tester, Icons.arrow_back);
    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.fuchsia }));

    testWidgets('Back arrow uses correct default', (WidgetTester tester) async {
      await expectBackIcon(tester, Icons.arrow_back_ios);
    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
  });

  group('close button', () {
    Future<void> expectCloseIcon(WidgetTester tester, PageRoute<void> Function() routeBuilder, String type) async {
      const IconData expectedIcon = Icons.close;
      await tester.pumpWidget(
        MaterialApp(
          home: Scaffold(appBar: AppBar(), body: const Text('Page 1')),
        ),
      );

      tester.state<NavigatorState>(find.byType(Navigator)).push(routeBuilder());

      await tester.pump();
      await tester.pump(const Duration(seconds: 1));

      final Icon icon = tester.widget(find.byType(Icon));
      expect(icon.icon, expectedIcon, reason: "didn't find close icon for $type");
      expect(find.byType(CloseButton), findsOneWidget, reason: "didn't find close button for $type");
    }

    PageRoute<void> materialRouteBuilder() {
      return MaterialPageRoute<void>(
        builder: (BuildContext context) {
          return Scaffold(appBar: AppBar(), body: const Text('Page 2'));
        },
        fullscreenDialog: true,
      );
    }

    PageRoute<void> pageRouteBuilder() {
      return PageRouteBuilder<void>(
        pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
          return Scaffold(appBar: AppBar(), body: const Text('Page 2'));
        },
        fullscreenDialog: true,
      );
    }

    PageRoute<void> customPageRouteBuilder() {
      return _CustomPageRoute<void>(
        builder: (BuildContext context) {
          return Scaffold(appBar: AppBar(), body: const Text('Page 2'));
        },
        fullscreenDialog: true,
      );
    }

    testWidgets('Close button shows correctly', (WidgetTester tester) async {
      await expectCloseIcon(tester, materialRouteBuilder, 'materialRouteBuilder');
    }, variant: TargetPlatformVariant.all());

    testWidgets('Close button shows correctly with PageRouteBuilder', (WidgetTester tester) async {
      await expectCloseIcon(tester, pageRouteBuilder, 'pageRouteBuilder');
    }, variant: TargetPlatformVariant.all());

    testWidgets('Close button shows correctly with custom page route', (WidgetTester tester) async {
      await expectCloseIcon(tester, customPageRouteBuilder, 'customPageRouteBuilder');
    }, variant: TargetPlatformVariant.all());
  });

  group('body size', () {
    testWidgets('body size with container', (WidgetTester tester) async {
      final Key testKey = UniqueKey();
      await tester.pumpWidget(Directionality(
        textDirection: TextDirection.ltr,
        child: MediaQuery(
          data: const MediaQueryData(),
          child: Scaffold(
            body: Container(
              key: testKey,
            ),
          ),
        ),
      ));
      expect(tester.element(find.byKey(testKey)).size, const Size(800.0, 600.0));
      expect(tester.renderObject<RenderBox>(find.byKey(testKey)).localToGlobal(Offset.zero), Offset.zero);
    });

    testWidgets('body size with sized container', (WidgetTester tester) async {
      final Key testKey = UniqueKey();
      await tester.pumpWidget(Directionality(
        textDirection: TextDirection.ltr,
        child: MediaQuery(
          data: const MediaQueryData(),
          child: Scaffold(
            body: Container(
              key: testKey,
              height: 100.0,
            ),
          ),
        ),
      ));
      expect(tester.element(find.byKey(testKey)).size, const Size(800.0, 100.0));
      expect(tester.renderObject<RenderBox>(find.byKey(testKey)).localToGlobal(Offset.zero), Offset.zero);
    });

    testWidgets('body size with centered container', (WidgetTester tester) async {
      final Key testKey = UniqueKey();
      await tester.pumpWidget(Directionality(
        textDirection: TextDirection.ltr,
        child: MediaQuery(
          data: const MediaQueryData(),
          child: Scaffold(
            body: Center(
              child: Container(
                key: testKey,
              ),
            ),
          ),
        ),
      ));
      expect(tester.element(find.byKey(testKey)).size, const Size(800.0, 600.0));
      expect(tester.renderObject<RenderBox>(find.byKey(testKey)).localToGlobal(Offset.zero), Offset.zero);
    });

    testWidgets('body size with button', (WidgetTester tester) async {
      final Key testKey = UniqueKey();
      await tester.pumpWidget(Directionality(
        textDirection: TextDirection.ltr,
        child: MediaQuery(
          data: const MediaQueryData(),
          child: Scaffold(
            body: TextButton(
              key: testKey,
              onPressed: () { },
              child: const Text(''),
            ),
          ),
        ),
      ));
      expect(tester.element(find.byKey(testKey)).size, const Size(64.0, 48.0));
      expect(tester.renderObject<RenderBox>(find.byKey(testKey)).localToGlobal(Offset.zero), Offset.zero);
    });

    testWidgets('body size with extendBody', (WidgetTester tester) async {
      final Key bodyKey = UniqueKey();
      late double mediaQueryBottom;

      Widget buildFrame({ required bool extendBody, bool? resizeToAvoidBottomInset, double viewInsetBottom = 0.0 }) {
        return Directionality(
          textDirection: TextDirection.ltr,
          child: MediaQuery(
            data: MediaQueryData(
              viewInsets: EdgeInsets.only(bottom: viewInsetBottom),
            ),
            child: Scaffold(
              resizeToAvoidBottomInset: resizeToAvoidBottomInset,
              extendBody: extendBody,
              body: Builder(
                builder: (BuildContext context) {
                  mediaQueryBottom = MediaQuery.paddingOf(context).bottom;
                  return Container(key: bodyKey);
                },
              ),
              bottomNavigationBar: const BottomAppBar(
                child: SizedBox(height: 48.0),
              ),
            ),
          ),
        );
      }

      await tester.pumpWidget(buildFrame(extendBody: true));
      expect(tester.getSize(find.byKey(bodyKey)), const Size(800.0, 600.0));
      expect(mediaQueryBottom, 48.0);

      await tester.pumpWidget(buildFrame(extendBody: false));
      expect(tester.getSize(find.byKey(bodyKey)), const Size(800.0, 552.0)); // 552 = 600 - 48 (BAB height)
      expect(mediaQueryBottom, 0.0);

      // If resizeToAvoidBottomInsets is false, same results as if it was unspecified (null).
      await tester.pumpWidget(buildFrame(extendBody: true, resizeToAvoidBottomInset: false, viewInsetBottom: 100.0));
      expect(tester.getSize(find.byKey(bodyKey)), const Size(800.0, 600.0));
      expect(mediaQueryBottom, 48.0);

      await tester.pumpWidget(buildFrame(extendBody: false, resizeToAvoidBottomInset: false, viewInsetBottom: 100.0));
      expect(tester.getSize(find.byKey(bodyKey)), const Size(800.0, 552.0));
      expect(mediaQueryBottom, 0.0);

      // If resizeToAvoidBottomInsets is true and viewInsets.bottom is > the bottom
      // navigation bar's height then the body always resizes and the MediaQuery
      // isn't adjusted. This case corresponds to the keyboard appearing.
      await tester.pumpWidget(buildFrame(extendBody: true, resizeToAvoidBottomInset: true, viewInsetBottom: 100.0));
      expect(tester.getSize(find.byKey(bodyKey)), const Size(800.0, 500.0));
      expect(mediaQueryBottom, 0.0);

      await tester.pumpWidget(buildFrame(extendBody: false, resizeToAvoidBottomInset: true, viewInsetBottom: 100.0));
      expect(tester.getSize(find.byKey(bodyKey)), const Size(800.0, 500.0));
      expect(mediaQueryBottom, 0.0);
    });

    testWidgets('body size with extendBodyBehindAppBar', (WidgetTester tester) async {
      final Key appBarKey = UniqueKey();
      final Key bodyKey = UniqueKey();

      const double appBarHeight = 100;
      const double windowPaddingTop = 24;
      late bool fixedHeightAppBar;
      late double mediaQueryTop;

      Widget buildFrame({ required bool extendBodyBehindAppBar, required bool hasAppBar }) {
        return Directionality(
          textDirection: TextDirection.ltr,
          child: MediaQuery(
            data: const MediaQueryData(
              padding: EdgeInsets.only(top: windowPaddingTop),
            ),
            child: Builder(
              builder: (BuildContext context) {
                return Scaffold(
                  extendBodyBehindAppBar: extendBodyBehindAppBar,
                  appBar: !hasAppBar ? null : PreferredSize(
                    key: appBarKey,
                    preferredSize: const Size.fromHeight(appBarHeight),
                    child: Container(
                      constraints: BoxConstraints(
                        minHeight: appBarHeight,
                        maxHeight: fixedHeightAppBar ? appBarHeight : double.infinity,
                      ),
                    ),
                  ),
                  body: Builder(
                    builder: (BuildContext context) {
                      mediaQueryTop = MediaQuery.paddingOf(context).top;
                      return Container(key: bodyKey);
                    },
                  ),
                );
              },
            ),
          ),
        );
      }

      fixedHeightAppBar = false;

      // When an appbar is provided, the Scaffold's body is built within a
      // MediaQuery with padding.top = 0, and the appBar's maxHeight is
      // constrained to its preferredSize.height + the original MediaQuery
      // padding.top. When extendBodyBehindAppBar is true, an additional
      // inner MediaQuery is added around the Scaffold's body with padding.top
      // equal to the overall height of the appBar. See _BodyBuilder in
      // material/scaffold.dart.

      await tester.pumpWidget(buildFrame(extendBodyBehindAppBar: true, hasAppBar: true));
      expect(tester.getSize(find.byKey(bodyKey)), const Size(800.0, 600.0));
      expect(tester.getSize(find.byKey(appBarKey)), const Size(800.0, appBarHeight + windowPaddingTop));
      expect(mediaQueryTop, appBarHeight + windowPaddingTop);

      await tester.pumpWidget(buildFrame(extendBodyBehindAppBar: true, hasAppBar: false));
      expect(tester.getSize(find.byKey(bodyKey)), const Size(800.0, 600.0));
      expect(find.byKey(appBarKey), findsNothing);
      expect(mediaQueryTop, windowPaddingTop);

      await tester.pumpWidget(buildFrame(extendBodyBehindAppBar: false, hasAppBar: true));
      expect(tester.getSize(find.byKey(bodyKey)), const Size(800.0, 600.0 - appBarHeight - windowPaddingTop));
      expect(tester.getSize(find.byKey(appBarKey)), const Size(800.0, appBarHeight + windowPaddingTop));
      expect(mediaQueryTop, 0.0);

      await tester.pumpWidget(buildFrame(extendBodyBehindAppBar: false, hasAppBar: false));
      expect(tester.getSize(find.byKey(bodyKey)), const Size(800.0, 600.0));
      expect(find.byKey(appBarKey), findsNothing);
      expect(mediaQueryTop, windowPaddingTop);

      fixedHeightAppBar = true;

      await tester.pumpWidget(buildFrame(extendBodyBehindAppBar: true, hasAppBar: true));
      expect(tester.getSize(find.byKey(bodyKey)), const Size(800.0, 600.0));
      expect(tester.getSize(find.byKey(appBarKey)), const Size(800.0, appBarHeight));
      expect(mediaQueryTop, appBarHeight);

      await tester.pumpWidget(buildFrame(extendBodyBehindAppBar: true, hasAppBar: false));
      expect(tester.getSize(find.byKey(bodyKey)), const Size(800.0, 600.0));
      expect(find.byKey(appBarKey), findsNothing);
      expect(mediaQueryTop, windowPaddingTop);

      await tester.pumpWidget(buildFrame(extendBodyBehindAppBar: false, hasAppBar: true));
      expect(tester.getSize(find.byKey(bodyKey)), const Size(800.0, 600.0 - appBarHeight));
      expect(tester.getSize(find.byKey(appBarKey)), const Size(800.0, appBarHeight));
      expect(mediaQueryTop, 0.0);

      await tester.pumpWidget(buildFrame(extendBodyBehindAppBar: false, hasAppBar: false));
      expect(tester.getSize(find.byKey(bodyKey)), const Size(800.0, 600.0));
      expect(find.byKey(appBarKey), findsNothing);
      expect(mediaQueryTop, windowPaddingTop);
    });
  });

  testWidgets('Open drawer hides underlying semantics tree', (WidgetTester tester) async {
    const String bodyLabel = 'I am the body';
    const String persistentFooterButtonLabel = 'a button on the bottom';
    const String bottomNavigationBarLabel = 'a bar in an app';
    const String floatingActionButtonLabel = 'I float in space';
    const String drawerLabel = 'I am the reason for this test';

    final SemanticsTester semantics = SemanticsTester(tester);
    await tester.pumpWidget(const MaterialApp(home: Scaffold(
      body: Text(bodyLabel),
      persistentFooterButtons: <Widget>[Text(persistentFooterButtonLabel)],
      bottomNavigationBar: Text(bottomNavigationBarLabel),
      floatingActionButton: Text(floatingActionButtonLabel),
      drawer: Drawer(child: Text(drawerLabel)),
    )));

    expect(semantics, includesNodeWith(label: bodyLabel));
    expect(semantics, includesNodeWith(label: persistentFooterButtonLabel));
    expect(semantics, includesNodeWith(label: bottomNavigationBarLabel));
    expect(semantics, includesNodeWith(label: floatingActionButtonLabel));
    expect(semantics, isNot(includesNodeWith(label: drawerLabel)));

    final ScaffoldState state = tester.firstState(find.byType(Scaffold));
    state.openDrawer();
    await tester.pump();
    await tester.pump(const Duration(seconds: 1));

    expect(semantics, isNot(includesNodeWith(label: bodyLabel)));
    expect(semantics, isNot(includesNodeWith(label: persistentFooterButtonLabel)));
    expect(semantics, isNot(includesNodeWith(label: bottomNavigationBarLabel)));
    expect(semantics, isNot(includesNodeWith(label: floatingActionButtonLabel)));
    expect(semantics, includesNodeWith(label: drawerLabel));

    semantics.dispose();
  });

  testWidgets('Scaffold and extreme window padding', (WidgetTester tester) async {
    final Key appBar = UniqueKey();
    final Key body = UniqueKey();
    final Key floatingActionButton = UniqueKey();
    final Key persistentFooterButton = UniqueKey();
    final Key drawer = UniqueKey();
    final Key bottomNavigationBar = UniqueKey();
    final Key insideAppBar = UniqueKey();
    final Key insideBody = UniqueKey();
    final Key insideFloatingActionButton = UniqueKey();
    final Key insidePersistentFooterButton = UniqueKey();
    final Key insideDrawer = UniqueKey();
    final Key insideBottomNavigationBar = UniqueKey();
    await tester.pumpWidget(
      Localizations(
        locale: const Locale('en', 'us'),
        delegates: const <LocalizationsDelegate<dynamic>>[
          DefaultWidgetsLocalizations.delegate,
          DefaultMaterialLocalizations.delegate,
        ],
        child: Directionality(
          textDirection: TextDirection.rtl,
          child: MediaQuery(
            data: const MediaQueryData(
              padding: EdgeInsets.only(
                left: 20.0,
                top: 30.0,
                right: 50.0,
                bottom: 60.0,
              ),
              viewInsets: EdgeInsets.only(bottom: 200.0),
            ),
            child: Scaffold(
              drawerDragStartBehavior: DragStartBehavior.down,
              appBar: PreferredSize(
                preferredSize: const Size(11.0, 13.0),
                child: Container(
                  key: appBar,
                  child: SafeArea(
                    child: Placeholder(key: insideAppBar),
                  ),
                ),
              ),
              body: Container(
                key: body,
                child: SafeArea(
                  child: Placeholder(key: insideBody),
                ),
              ),
              floatingActionButton: SizedBox(
                key: floatingActionButton,
                width: 77.0,
                height: 77.0,
                child: SafeArea(
                  child: Placeholder(key: insideFloatingActionButton),
                ),
              ),
              persistentFooterButtons: <Widget>[
                SizedBox(
                  key: persistentFooterButton,
                  width: 100.0,
                  height: 90.0,
                  child: SafeArea(
                    child: Placeholder(key: insidePersistentFooterButton),
                  ),
                ),
              ],
              drawer: SizedBox(
                key: drawer,
                width: 204.0,
                child: SafeArea(
                  child: Placeholder(key: insideDrawer),
                ),
              ),
              bottomNavigationBar: SizedBox(
                key: bottomNavigationBar,
                height: 85.0,
                child: SafeArea(
                  child: Placeholder(key: insideBottomNavigationBar),
                ),
              ),
            ),
          ),
        ),
      ),
    );
    // open drawer
    await tester.flingFrom(const Offset(795.0, 5.0), const Offset(-200.0, 0.0), 10.0);
    await tester.pump();
    await tester.pump(const Duration(seconds: 1));

    expect(tester.getRect(find.byKey(appBar)), const Rect.fromLTRB(0.0, 0.0, 800.0, 43.0));
    expect(tester.getRect(find.byKey(body)), const Rect.fromLTRB(0.0, 43.0, 800.0, 400.0));
    expect(tester.getRect(find.byKey(floatingActionButton)), rectMoreOrLessEquals(const Rect.fromLTRB(36.0, 307.0, 113.0, 384.0)));
    expect(tester.getRect(find.byKey(persistentFooterButton)),const  Rect.fromLTRB(28.0, 417.0, 128.0, 507.0)); // Note: has 8px each top/bottom padding.
    expect(tester.getRect(find.byKey(drawer)), const Rect.fromLTRB(596.0, 0.0, 800.0, 600.0));
    expect(tester.getRect(find.byKey(bottomNavigationBar)), const Rect.fromLTRB(0.0, 515.0, 800.0, 600.0));
    expect(tester.getRect(find.byKey(insideAppBar)), const Rect.fromLTRB(20.0, 30.0, 750.0, 43.0));
    expect(tester.getRect(find.byKey(insideBody)), const Rect.fromLTRB(20.0, 43.0, 750.0, 400.0));
    expect(tester.getRect(find.byKey(insideFloatingActionButton)), rectMoreOrLessEquals(const Rect.fromLTRB(36.0, 307.0, 113.0, 384.0)));
    expect(tester.getRect(find.byKey(insidePersistentFooterButton)), const Rect.fromLTRB(28.0, 417.0, 128.0, 507.0));
    expect(tester.getRect(find.byKey(insideDrawer)), const Rect.fromLTRB(596.0, 30.0, 750.0, 540.0));
    expect(tester.getRect(find.byKey(insideBottomNavigationBar)), const Rect.fromLTRB(20.0, 515.0, 750.0, 540.0));
  });

  testWidgets('Scaffold and extreme window padding - persistent footer buttons only', (WidgetTester tester) async {
    final Key appBar = UniqueKey();
    final Key body = UniqueKey();
    final Key floatingActionButton = UniqueKey();
    final Key persistentFooterButton = UniqueKey();
    final Key drawer = UniqueKey();
    final Key insideAppBar = UniqueKey();
    final Key insideBody = UniqueKey();
    final Key insideFloatingActionButton = UniqueKey();
    final Key insidePersistentFooterButton = UniqueKey();
    final Key insideDrawer = UniqueKey();
    await tester.pumpWidget(
      Localizations(
        locale: const Locale('en', 'us'),
        delegates: const <LocalizationsDelegate<dynamic>>[
          DefaultWidgetsLocalizations.delegate,
          DefaultMaterialLocalizations.delegate,
        ],
        child: Directionality(
          textDirection: TextDirection.rtl,
          child: MediaQuery(
            data: const MediaQueryData(
              padding: EdgeInsets.only(
                left: 20.0,
                top: 30.0,
                right: 50.0,
                bottom: 60.0,
              ),
              viewInsets: EdgeInsets.only(bottom: 200.0),
            ),
            child: Scaffold(
              appBar: PreferredSize(
                preferredSize: const Size(11.0, 13.0),
                child: Container(
                  key: appBar,
                  child: SafeArea(
                    child: Placeholder(key: insideAppBar),
                  ),
                ),
              ),
              body: Container(
                key: body,
                child: SafeArea(
                  child: Placeholder(key: insideBody),
                ),
              ),
              floatingActionButton: SizedBox(
                key: floatingActionButton,
                width: 77.0,
                height: 77.0,
                child: SafeArea(
                  child: Placeholder(key: insideFloatingActionButton),
                ),
              ),
              persistentFooterButtons: <Widget>[
                SizedBox(
                  key: persistentFooterButton,
                  width: 100.0,
                  height: 90.0,
                  child: SafeArea(
                    child: Placeholder(key: insidePersistentFooterButton),
                  ),
                ),
              ],
              drawer: SizedBox(
                key: drawer,
                width: 204.0,
                child: SafeArea(
                  child: Placeholder(key: insideDrawer),
                ),
              ),
            ),
          ),
        ),
      ),
    );
    // open drawer
    await tester.flingFrom(const Offset(795.0, 5.0), const Offset(-200.0, 0.0), 10.0);
    await tester.pump();
    await tester.pump(const Duration(seconds: 1));

    expect(tester.getRect(find.byKey(appBar)), const Rect.fromLTRB(0.0, 0.0, 800.0, 43.0));
    expect(tester.getRect(find.byKey(body)), const Rect.fromLTRB(0.0, 43.0, 800.0, 400.0));
    expect(tester.getRect(find.byKey(floatingActionButton)), rectMoreOrLessEquals(const Rect.fromLTRB(36.0, 307.0, 113.0, 384.0)));
    expect(tester.getRect(find.byKey(persistentFooterButton)), const Rect.fromLTRB(28.0, 442.0, 128.0, 532.0)); // Note: has 8px each top/bottom padding.
    expect(tester.getRect(find.byKey(drawer)), const Rect.fromLTRB(596.0, 0.0, 800.0, 600.0));
    expect(tester.getRect(find.byKey(insideAppBar)), const Rect.fromLTRB(20.0, 30.0, 750.0, 43.0));
    expect(tester.getRect(find.byKey(insideBody)), const Rect.fromLTRB(20.0, 43.0, 750.0, 400.0));
    expect(tester.getRect(find.byKey(insideFloatingActionButton)), rectMoreOrLessEquals(const Rect.fromLTRB(36.0, 307.0, 113.0, 384.0)));
    expect(tester.getRect(find.byKey(insidePersistentFooterButton)), const Rect.fromLTRB(28.0, 442.0, 128.0, 532.0));
    expect(tester.getRect(find.byKey(insideDrawer)), const Rect.fromLTRB(596.0, 30.0, 750.0, 540.0));
  });


  group('ScaffoldGeometry', () {
    testWidgets('bottomNavigationBar', (WidgetTester tester) async {
      final GlobalKey key = GlobalKey();
      await tester.pumpWidget(MaterialApp(home: Scaffold(
            body: Container(),
            bottomNavigationBar: ConstrainedBox(
              key: key,
              constraints: const BoxConstraints.expand(height: 80.0),
              child: const _GeometryListener(),
            ),
      )));

      final RenderBox navigationBox = tester.renderObject(find.byKey(key));
      final RenderBox appBox = tester.renderObject(find.byType(MaterialApp));
      final _GeometryListenerState listenerState = tester.state(find.byType(_GeometryListener));
      final ScaffoldGeometry geometry = listenerState.cache.value;

      expect(
        geometry.bottomNavigationBarTop,
        appBox.size.height - navigationBox.size.height,
      );
    });

    testWidgets('no bottomNavigationBar', (WidgetTester tester) async {
      await tester.pumpWidget(MaterialApp(home: Scaffold(
            body: ConstrainedBox(
              constraints: const BoxConstraints.expand(height: 80.0),
              child: const _GeometryListener(),
            ),
      )));

      final _GeometryListenerState listenerState = tester.state(find.byType(_GeometryListener));
      final ScaffoldGeometry geometry = listenerState.cache.value;

      expect(
        geometry.bottomNavigationBarTop,
        null,
      );
    });

    testWidgets('Scaffold BottomNavigationBar bottom padding is not consumed by viewInsets.', (WidgetTester tester) async {
      Widget boilerplate(Widget child) {
        return Localizations(
          locale: const Locale('en', 'us'),
          delegates: const <LocalizationsDelegate<dynamic>>[
            DefaultWidgetsLocalizations.delegate,
            DefaultMaterialLocalizations.delegate,
          ],
          child: Directionality(
            textDirection: TextDirection.ltr,
            child: child,
          ),
        );
      }

      final Widget child = boilerplate(
        Scaffold(
          resizeToAvoidBottomInset: false,
          body: const Placeholder(),
          bottomNavigationBar: Navigator(
            onGenerateRoute: (RouteSettings settings) {
              return MaterialPageRoute<void>(
                builder: (BuildContext context) {
                  return BottomNavigationBar(
                    items: const <BottomNavigationBarItem>[
                      BottomNavigationBarItem(
                        icon: Icon(Icons.add),
                        label: 'test',
                      ),
                      BottomNavigationBarItem(
                        icon: Icon(Icons.add),
                        label: 'test',
                      ),
                    ],
                  );
                },
              );
            },
          ),
        ),
      );

      await tester.pumpWidget(
        MediaQuery(
          data: const MediaQueryData(padding: EdgeInsets.only(bottom: 20.0)),
          child: child,
        ),
      );
      final Offset initialPoint = tester.getCenter(find.byType(Placeholder));
      // Consume bottom padding - as if by the keyboard opening
      await tester.pumpWidget(
        MediaQuery(
          data: const MediaQueryData(
            viewPadding: EdgeInsets.only(bottom: 20),
            viewInsets: EdgeInsets.only(bottom: 300),
          ),
          child: child,
        ),
      );
      final Offset finalPoint = tester.getCenter(find.byType(Placeholder));
      expect(initialPoint, finalPoint);
    });

    testWidgets('floatingActionButton', (WidgetTester tester) async {
      final GlobalKey key = GlobalKey();
      await tester.pumpWidget(MaterialApp(home: Scaffold(
            body: Container(),
            floatingActionButton: FloatingActionButton(
              key: key,
              child: const _GeometryListener(),
              onPressed: () { },
            ),
      )));

      final RenderBox floatingActionButtonBox = tester.renderObject(find.byKey(key));
      final _GeometryListenerState listenerState = tester.state(find.byType(_GeometryListener));
      final ScaffoldGeometry geometry = listenerState.cache.value;

      final Rect fabRect = floatingActionButtonBox.localToGlobal(Offset.zero) & floatingActionButtonBox.size;

      expect(
        geometry.floatingActionButtonArea,
        fabRect,
      );
    });

    testWidgets('no floatingActionButton', (WidgetTester tester) async {
      await tester.pumpWidget(MaterialApp(home: Scaffold(
            body: ConstrainedBox(
              constraints: const BoxConstraints.expand(height: 80.0),
              child: const _GeometryListener(),
            ),
      )));

      final _GeometryListenerState listenerState = tester.state(find.byType(_GeometryListener));
      final ScaffoldGeometry geometry = listenerState.cache.value;

      expect(
          geometry.floatingActionButtonArea,
          null,
      );
    });

    testWidgets('floatingActionButton entrance/exit animation', (WidgetTester tester) async {
      final GlobalKey key = GlobalKey();
      await tester.pumpWidget(MaterialApp(home: Scaffold(
            body: ConstrainedBox(
              constraints: const BoxConstraints.expand(height: 80.0),
              child: const _GeometryListener(),
            ),
      )));

      await tester.pumpWidget(MaterialApp(home: Scaffold(
            body: Container(),
            floatingActionButton: FloatingActionButton(
              key: key,
              child: const _GeometryListener(),
              onPressed: () { },
            ),
      )));

      final _GeometryListenerState listenerState = tester.state(find.byType(_GeometryListener));
      await tester.pump(const Duration(milliseconds: 50));

      ScaffoldGeometry geometry = listenerState.cache.value;
      final Rect transitioningFabRect = geometry.floatingActionButtonArea!;

      final double transitioningRotation = tester.widget<RotationTransition>(
        find.byType(RotationTransition),
      ).turns.value;

      await tester.pump(const Duration(seconds: 3));
      geometry = listenerState.cache.value;
      final RenderBox floatingActionButtonBox = tester.renderObject(find.byKey(key));
      final Rect fabRect = floatingActionButtonBox.localToGlobal(Offset.zero) & floatingActionButtonBox.size;

      final double completedRotation = tester.widget<RotationTransition>(
        find.byType(RotationTransition),
      ).turns.value;

      expect(transitioningRotation, lessThan(1.0));

      expect(completedRotation, equals(1.0));

      expect(
        geometry.floatingActionButtonArea,
        fabRect,
      );

      expect(
        geometry.floatingActionButtonArea!.center,
        transitioningFabRect.center,
      );

      expect(
        geometry.floatingActionButtonArea!.width,
        greaterThan(transitioningFabRect.width),
      );

      expect(
        geometry.floatingActionButtonArea!.height,
        greaterThan(transitioningFabRect.height),
      );
    });

    testWidgets('change notifications', (WidgetTester tester) async {
      final GlobalKey key = GlobalKey();
      int numNotificationsAtLastFrame = 0;
      await tester.pumpWidget(MaterialApp(home: Scaffold(
            body: ConstrainedBox(
              constraints: const BoxConstraints.expand(height: 80.0),
              child: const _GeometryListener(),
            ),
      )));

      final _GeometryListenerState listenerState = tester.state(find.byType(_GeometryListener));

      expect(listenerState.numNotifications, greaterThan(numNotificationsAtLastFrame));
      numNotificationsAtLastFrame = listenerState.numNotifications;

      await tester.pumpWidget(MaterialApp(home: Scaffold(
            body: Container(),
            floatingActionButton: FloatingActionButton(
              key: key,
              child: const _GeometryListener(),
              onPressed: () { },
            ),
      )));

      expect(listenerState.numNotifications, greaterThan(numNotificationsAtLastFrame));
      numNotificationsAtLastFrame = listenerState.numNotifications;

      await tester.pump(const Duration(milliseconds: 50));

      expect(listenerState.numNotifications, greaterThan(numNotificationsAtLastFrame));
      numNotificationsAtLastFrame = listenerState.numNotifications;

      await tester.pump(const Duration(seconds: 3));

      expect(listenerState.numNotifications, greaterThan(numNotificationsAtLastFrame));
      numNotificationsAtLastFrame = listenerState.numNotifications;
    });

    testWidgets('Simultaneous drawers on either side', (WidgetTester tester) async {
      const String bodyLabel = 'I am the body';
      const String drawerLabel = 'I am the label on start side';
      const String endDrawerLabel = 'I am the label on end side';

      final SemanticsTester semantics = SemanticsTester(tester);
      await tester.pumpWidget(const MaterialApp(home: Scaffold(
        body: Text(bodyLabel),
        drawer: Drawer(child: Text(drawerLabel)),
        endDrawer: Drawer(child: Text(endDrawerLabel)),
      )));

      expect(semantics, includesNodeWith(label: bodyLabel));
      expect(semantics, isNot(includesNodeWith(label: drawerLabel)));
      expect(semantics, isNot(includesNodeWith(label: endDrawerLabel)));

      final ScaffoldState state = tester.firstState(find.byType(Scaffold));
      state.openDrawer();
      await tester.pump();
      await tester.pump(const Duration(seconds: 1));

      expect(semantics, isNot(includesNodeWith(label: bodyLabel)));
      expect(semantics, includesNodeWith(label: drawerLabel));

      state.openEndDrawer();
      await tester.pump();
      await tester.pump(const Duration(seconds: 1));

      expect(semantics, isNot(includesNodeWith(label: bodyLabel)));
      expect(semantics, includesNodeWith(label: endDrawerLabel));

      semantics.dispose();
    });

    testWidgets('Drawer state query correctly', (WidgetTester tester) async {
      await tester.pumpWidget(
        MaterialApp(
          home: SafeArea(
            left: false,
            right: false,
            bottom: false,
            child: Scaffold(
              endDrawer: const Drawer(
                child: Text('endDrawer'),
              ),
              drawer: const Drawer(
                child: Text('drawer'),
              ),
              body: const Text('scaffold body'),
              appBar: AppBar(
                centerTitle: true,
                title: const Text('Title'),
              ),
            ),
          ),
        ),
      );

      final ScaffoldState scaffoldState = tester.state(find.byType(Scaffold));

      final Finder drawerOpenButton = find.byType(IconButton).first;
      final Finder endDrawerOpenButton = find.byType(IconButton).last;

      await tester.tap(drawerOpenButton);
      await tester.pumpAndSettle();
      expect(scaffoldState.isDrawerOpen, true);
      await tester.tap(endDrawerOpenButton, warnIfMissed: false); // hits the modal barrier
      await tester.pumpAndSettle();
      expect(scaffoldState.isDrawerOpen,  false);

      await tester.tap(endDrawerOpenButton);
      await tester.pumpAndSettle();
      expect(scaffoldState.isEndDrawerOpen, true);
      await tester.tap(drawerOpenButton, warnIfMissed: false); // hits the modal barrier
      await tester.pumpAndSettle();
      expect(scaffoldState.isEndDrawerOpen, false);

      scaffoldState.openDrawer();
      expect(scaffoldState.isDrawerOpen, true);
      await tester.tap(endDrawerOpenButton, warnIfMissed: false); // hits the modal barrier
      await tester.pumpAndSettle();
      expect(scaffoldState.isDrawerOpen, false);

      scaffoldState.openEndDrawer();
      expect(scaffoldState.isEndDrawerOpen, true);

      scaffoldState.openDrawer();
      expect(scaffoldState.isDrawerOpen, true);
    });

    testWidgets('Dual Drawer Opening', (WidgetTester tester) async {
      await tester.pumpWidget(
        MaterialApp(
          home: SafeArea(
            left: false,
            right: false,
            bottom: false,
            child: Scaffold(
              endDrawer: const Drawer(
                child: Text('endDrawer'),
              ),
              drawer: const Drawer(
                child: Text('drawer'),
              ),
              body: const Text('scaffold body'),
              appBar: AppBar(
                centerTitle: true,
                title: const Text('Title'),
              ),
            ),
          ),
        ),
      );

      // Open Drawer, tap on end drawer, which closes the drawer, but does
      // not open the drawer.
      await tester.tap(find.byType(IconButton).first);
      await tester.pumpAndSettle();
      await tester.tap(find.byType(IconButton).last, warnIfMissed: false); // hits the modal barrier
      await tester.pumpAndSettle();

      expect(find.text('endDrawer'), findsNothing);
      expect(find.text('drawer'), findsNothing);

      // Tapping the first opens the first drawer
      await tester.tap(find.byType(IconButton).first);
      await tester.pumpAndSettle();

      expect(find.text('endDrawer'), findsNothing);
      expect(find.text('drawer'), findsOneWidget);

      // Tapping on the end drawer and then on the drawer should close the
      // drawer and then reopen it.
      await tester.tap(find.byType(IconButton).last, warnIfMissed: false); // hits the modal barrier
      await tester.pumpAndSettle();
      await tester.tap(find.byType(IconButton).first);
      await tester.pumpAndSettle();

      expect(find.text('endDrawer'), findsNothing);
      expect(find.text('drawer'), findsOneWidget);
    });

    testWidgets('Drawer opens correctly with padding from MediaQuery (LTR)', (WidgetTester tester) async {
      const double simulatedNotchSize = 40.0;
      await tester.pumpWidget(
        MaterialApp(
          home: Scaffold(
            drawer: const Drawer(
              child: Text('Drawer'),
            ),
            body: const Text('Scaffold Body'),
            appBar: AppBar(
              centerTitle: true,
              title: const Text('Title'),
            ),
          ),
        ),
      );

      ScaffoldState scaffoldState = tester.state(find.byType(Scaffold));
      expect(scaffoldState.isDrawerOpen, false);

      await tester.dragFrom(const Offset(simulatedNotchSize + 15.0, 100), const Offset(300, 0));
      await tester.pumpAndSettle();
      expect(scaffoldState.isDrawerOpen, false);

      await tester.pumpWidget(
        MaterialApp(
          home: MediaQuery(
            data: const MediaQueryData(
              padding: EdgeInsets.fromLTRB(simulatedNotchSize, 0, 0, 0),
            ),
            child: Scaffold(
              drawer: const Drawer(
                child: Text('Drawer'),
              ),
              body: const Text('Scaffold Body'),
              appBar: AppBar(
                centerTitle: true,
                title: const Text('Title'),
              ),
            ),
          ),
        ),
      );
      scaffoldState = tester.state(find.byType(Scaffold));
      expect(scaffoldState.isDrawerOpen, false);

      await tester.dragFrom(
        const Offset(simulatedNotchSize + 15.0, 100),
        const Offset(300, 0),
      );
      await tester.pumpAndSettle();
      expect(scaffoldState.isDrawerOpen, true);
    });

    testWidgets('Drawer opens correctly with padding from MediaQuery (RTL)', (WidgetTester tester) async {
      const double simulatedNotchSize = 40.0;
      await tester.pumpWidget(
        MaterialApp(
          home: Scaffold(
            drawer: const Drawer(
              child: Text('Drawer'),
            ),
            body: const Text('Scaffold Body'),
            appBar: AppBar(
              centerTitle: true,
              title: const Text('Title'),
            ),
          ),
        ),
      );

      final double scaffoldWidth = tester.renderObject<RenderBox>(
        find.byType(Scaffold),
      ).size.width;
      ScaffoldState scaffoldState = tester.state(find.byType(Scaffold));
      expect(scaffoldState.isDrawerOpen, false);

      await tester.dragFrom(
        Offset(scaffoldWidth - simulatedNotchSize - 15.0, 100),
        const Offset(-300, 0),
      );
      await tester.pumpAndSettle();
      expect(scaffoldState.isDrawerOpen, false);

      await tester.pumpWidget(
        MaterialApp(
          home: MediaQuery(
            data: const MediaQueryData(
              padding: EdgeInsets.fromLTRB(0, 0, simulatedNotchSize, 0),
            ),
            child: Directionality(
              textDirection: TextDirection.rtl,
              child: Scaffold(
                drawer: const Drawer(
                  child: Text('Drawer'),
                ),
                body: const Text('Scaffold body'),
                appBar: AppBar(
                  centerTitle: true,
                  title: const Text('Title'),
                ),
              ),
            ),
          ),
        ),
      );
      scaffoldState = tester.state(find.byType(Scaffold));
      expect(scaffoldState.isDrawerOpen, false);

      await tester.dragFrom(
        Offset(scaffoldWidth - simulatedNotchSize - 15.0, 100),
        const Offset(-300, 0),
      );
      await tester.pumpAndSettle();
      expect(scaffoldState.isDrawerOpen, true);
    });
  });

  testWidgets('Drawer opens correctly with custom edgeDragWidth', (WidgetTester tester) async {
    // The default edge drag width is 20.0.
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          drawer: const Drawer(
            child: Text('Drawer'),
          ),
          body: const Text('Scaffold body'),
          appBar: AppBar(
            centerTitle: true,
            title: const Text('Title'),
          ),
        ),
      ),
    );
    ScaffoldState scaffoldState = tester.state(find.byType(Scaffold));
    expect(scaffoldState.isDrawerOpen, false);

    await tester.dragFrom(const Offset(35, 100), const Offset(300, 0));
    await tester.pumpAndSettle();
    expect(scaffoldState.isDrawerOpen, false);

    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          drawer: const Drawer(
            child: Text('Drawer'),
          ),
          drawerEdgeDragWidth: 40.0,
          body: const Text('Scaffold Body'),
          appBar: AppBar(
            centerTitle: true,
            title: const Text('Title'),
          ),
        ),
      ),
    );
    scaffoldState = tester.state(find.byType(Scaffold));
    expect(scaffoldState.isDrawerOpen, false);

    await tester.dragFrom(const Offset(35, 100), const Offset(300, 0));
    await tester.pumpAndSettle();
    expect(scaffoldState.isDrawerOpen, true);
  });

  testWidgets('Drawer does not open with a drag gesture when it is disabled on mobile', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          drawer: const Drawer(
            child: Text('Drawer'),
          ),
          body: const Text('Scaffold Body'),
          appBar: AppBar(
            centerTitle: true,
            title: const Text('Title'),
          ),
        ),
      ),
    );
    ScaffoldState scaffoldState = tester.state(find.byType(Scaffold));
    expect(scaffoldState.isDrawerOpen, false);

    // Test that we can open the drawer with a drag gesture when
    // `Scaffold.drawerEnableDragGesture` is true.
    await tester.dragFrom(const Offset(0, 100), const Offset(300, 0));
    await tester.pumpAndSettle();
    expect(scaffoldState.isDrawerOpen, true);

    await tester.dragFrom(const Offset(300, 100), const Offset(-300, 0));
    await tester.pumpAndSettle();
    expect(scaffoldState.isDrawerOpen, false);

    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          drawer: const Drawer(
            child: Text('Drawer'),
          ),
          drawerEnableOpenDragGesture: false,
          body: const Text('Scaffold body'),
          appBar: AppBar(
            centerTitle: true,
            title: const Text('Title'),
          ),
        ),
      ),
    );
    scaffoldState = tester.state(find.byType(Scaffold));
    expect(scaffoldState.isDrawerOpen, false);

    // Test that we cannot open the drawer with a drag gesture when
    // `Scaffold.drawerEnableDragGesture` is false.
    await tester.dragFrom(const Offset(0, 100), const Offset(300, 0));
    await tester.pumpAndSettle();
    expect(scaffoldState.isDrawerOpen, false);

    // Test that we can close drawer with a drag gesture when
    // `Scaffold.drawerEnableDragGesture` is false.
    final Finder drawerOpenButton = find.byType(IconButton).first;
    await tester.tap(drawerOpenButton);
    await tester.pumpAndSettle();
    expect(scaffoldState.isDrawerOpen, true);

    await tester.dragFrom(const Offset(300, 100), const Offset(-300, 0));
    await tester.pumpAndSettle();
    expect(scaffoldState.isDrawerOpen, false);
  }, variant: TargetPlatformVariant.mobile());

  testWidgets('Drawer does not open with a drag gesture on dekstop', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          drawer: const Drawer(
            child: Text('Drawer'),
          ),
          body: const Text('Scaffold Body'),
          appBar: AppBar(
            centerTitle: true,
            title: const Text('Title'),
          ),
        ),
      ),
    );
    final ScaffoldState scaffoldState = tester.state(find.byType(Scaffold));
    expect(scaffoldState.isDrawerOpen, false);

    // Test that we cannot open the drawer with a drag gesture.
    await tester.dragFrom(const Offset(0, 100), const Offset(300, 0));
    await tester.pumpAndSettle();
    expect(scaffoldState.isDrawerOpen, false);

    // Test that we can open the drawer with a tap gesture on drawer icon button.
    final Finder drawerOpenButton = find.byType(IconButton).first;
    await tester.tap(drawerOpenButton);
    await tester.pumpAndSettle();
    expect(scaffoldState.isDrawerOpen, true);

    // Test that we cannot close the drawer with a drag gesture.
    await tester.dragFrom(const Offset(300, 100), const Offset(-300, 0));
    await tester.pumpAndSettle();
    expect(scaffoldState.isDrawerOpen, true);

    // Test that we can close the drawer with a tap gesture in the body.
    await tester.tapAt(const Offset(500, 300));
    await tester.pumpAndSettle();
    expect(scaffoldState.isDrawerOpen, false);
  }, variant: TargetPlatformVariant.desktop());

  testWidgets('End drawer does not open with a drag gesture when it is disabled', (WidgetTester tester) async {
    late double screenWidth;
    await tester.pumpWidget(
      MaterialApp(
        home: Builder(
          builder: (BuildContext context) {
            screenWidth = MediaQuery.sizeOf(context).width;
            return Scaffold(
              endDrawer: const Drawer(
                child: Text('Drawer'),
              ),
              body: const Text('Scaffold Body'),
              appBar: AppBar(
                centerTitle: true,
                title: const Text('Title'),
              ),
            );
          },
        ),
      ),
    );
    ScaffoldState scaffoldState = tester.state(find.byType(Scaffold));
    expect(scaffoldState.isEndDrawerOpen, false);

    // Test that we can open the end drawer with a drag gesture when
    // `Scaffold.endDrawerEnableDragGesture` is true.
    await tester.dragFrom(Offset(screenWidth - 1, 100), const Offset(-300, 0));
    await tester.pumpAndSettle();
    expect(scaffoldState.isEndDrawerOpen, true);

    await tester.dragFrom(Offset(screenWidth - 300, 100), const Offset(300, 0));
    await tester.pumpAndSettle();
    expect(scaffoldState.isEndDrawerOpen, false);

    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          endDrawer: const Drawer(
            child: Text('Drawer'),
          ),
          endDrawerEnableOpenDragGesture: false,
          body: const Text('Scaffold body'),
          appBar: AppBar(
            centerTitle: true,
            title: const Text('Title'),
          ),
        ),
      ),
    );
    scaffoldState = tester.state(find.byType(Scaffold));
    expect(scaffoldState.isEndDrawerOpen, false);

    // Test that we cannot open the end drawer with a drag gesture when
    // `Scaffold.endDrawerEnableDragGesture` is false.
    await tester.dragFrom(Offset(screenWidth - 1, 100), const Offset(-300, 0));
    await tester.pumpAndSettle();
    expect(scaffoldState.isEndDrawerOpen, false);

    // Test that we can close the end drawer a with drag gesture when
    // `Scaffold.endDrawerEnableDragGesture` is false.
    final Finder endDrawerOpenButton = find.byType(IconButton).first;
    await tester.tap(endDrawerOpenButton);
    await tester.pumpAndSettle();
    expect(scaffoldState.isEndDrawerOpen, true);

    await tester.dragFrom(Offset(screenWidth - 300, 100), const Offset(300, 0));
    await tester.pumpAndSettle();
    expect(scaffoldState.isEndDrawerOpen, false);
  });

  testWidgets('Nested scaffold body insets', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/20295
    final Key bodyKey = UniqueKey();

    Widget buildFrame(bool? innerResizeToAvoidBottomInset, bool? outerResizeToAvoidBottomInset) {
      return Directionality(
        textDirection: TextDirection.ltr,
        child: MediaQuery(
          data: const MediaQueryData(viewInsets: EdgeInsets.only(bottom: 100.0)),
          child: Builder(
            builder: (BuildContext context) {
              return Scaffold(
                resizeToAvoidBottomInset: outerResizeToAvoidBottomInset,
                body: Builder(
                  builder: (BuildContext context) {
                    return Scaffold(
                      resizeToAvoidBottomInset: innerResizeToAvoidBottomInset,
                      body: Container(key: bodyKey),
                    );
                  },
                ),
              );
            },
          ),
        ),
      );
    }

    await tester.pumpWidget(buildFrame(true, true));
    expect(tester.getSize(find.byKey(bodyKey)), const Size(800.0, 500.0));

    await tester.pumpWidget(buildFrame(false, true));
    expect(tester.getSize(find.byKey(bodyKey)), const Size(800.0, 500.0));

    await tester.pumpWidget(buildFrame(true, false));
    expect(tester.getSize(find.byKey(bodyKey)), const Size(800.0, 500.0));

    // This is the only case where the body is not bottom inset.
    await tester.pumpWidget(buildFrame(false, false));
    expect(tester.getSize(find.byKey(bodyKey)), const Size(800.0, 600.0));

    await tester.pumpWidget(buildFrame(null, null));  // resizeToAvoidBottomInset default is true
    expect(tester.getSize(find.byKey(bodyKey)), const Size(800.0, 500.0));

    await tester.pumpWidget(buildFrame(null, false));
    expect(tester.getSize(find.byKey(bodyKey)), const Size(800.0, 500.0));

    await tester.pumpWidget(buildFrame(false, null));
    expect(tester.getSize(find.byKey(bodyKey)), const Size(800.0, 500.0));
  });

  group('FlutterError control test', () {
    testWidgets('showBottomSheet() while Scaffold has bottom sheet',
      (WidgetTester tester) async {
        final GlobalKey<ScaffoldState> key = GlobalKey<ScaffoldState>();
        await tester.pumpWidget(
          MaterialApp(
            home: Scaffold(
              key: key,
              body: Center(
                child: Container(),
              ),
              bottomSheet: const Text('Bottom sheet'),
            ),
          ),
        );
        late FlutterError error;
        try {
          key.currentState!.showBottomSheet<void>((BuildContext context) {
            final ThemeData themeData = Theme.of(context);
            return Container(
              decoration: BoxDecoration(
                border: Border(top: BorderSide(color: themeData.disabledColor)),
              ),
              child: Padding(
                padding: const EdgeInsets.all(32.0),
                child: Text('This is a Material persistent bottom sheet. Drag downwards to dismiss it.',
                  textAlign: TextAlign.center,
                  style: TextStyle(
                    color: themeData.colorScheme.secondary,
                    fontSize: 24.0,
                  ),
                ),
              ),
            );
          });
        } on FlutterError catch (e) {
          error = e;
        } finally {
          expect(error, isNotNull);
          expect(error.toStringDeep(), equalsIgnoringHashCodes(
            'FlutterError\n'
            '   Scaffold.bottomSheet cannot be specified while a bottom sheet\n'
            '   displayed with showBottomSheet() is still visible.\n'
            '   Rebuild the Scaffold with a null bottomSheet before calling\n'
            '   showBottomSheet().\n',
          ));
        }
      },
    );

    testWidgets(
      'didUpdate bottomSheet while a previous bottom sheet is still displayed',
      (WidgetTester tester) async {
        final GlobalKey<ScaffoldState> key = GlobalKey<ScaffoldState>();
        const Key buttonKey = Key('button');
        final List<FlutterErrorDetails> errors = <FlutterErrorDetails>[];
        FlutterError.onError = (FlutterErrorDetails error) => errors.add(error);
        int state = 0;
        await tester.pumpWidget(
          MaterialApp(
            home: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
                return Scaffold(
                  key: key,
                  body: Container(),
                  floatingActionButton: FloatingActionButton(
                    key: buttonKey,
                    onPressed: () {
                      state += 1;
                      setState(() {});
                    },
                  ),
                  bottomSheet: state == 0 ? null : const SizedBox(),
                );
              },
            ),
          ),
        );
        key.currentState!.showBottomSheet<void>((_) => Container());
        await tester.tap(find.byKey(buttonKey));
        await tester.pump();
        expect(errors, isNotEmpty);
        expect(errors.first.exception, isFlutterError);
        final FlutterError error = errors.first.exception as FlutterError;
        expect(error.diagnostics.length, 2);
        expect(error.diagnostics.last.level, DiagnosticLevel.hint);
        expect(
          error.diagnostics.last.toStringDeep(),
          'Use the PersistentBottomSheetController returned by\n'
          'showBottomSheet() to close the old bottom sheet before creating a\n'
          'Scaffold with a (non null) bottomSheet.\n',
        );
        expect(
          error.toStringDeep(),
          'FlutterError\n'
          '   Scaffold.bottomSheet cannot be specified while a bottom sheet\n'
          '   displayed with showBottomSheet() is still visible.\n'
          '   Use the PersistentBottomSheetController returned by\n'
          '   showBottomSheet() to close the old bottom sheet before creating a\n'
          '   Scaffold with a (non null) bottomSheet.\n',
        );
        await tester.pumpAndSettle();
      },
    );

    testWidgets('Call to Scaffold.of() without context', (WidgetTester tester) async {
      await tester.pumpWidget(
        MaterialApp(
          home: Builder(
            builder: (BuildContext context) {
              Scaffold.of(context).showBottomSheet<void>((BuildContext context) {
                return Container();
              });
              return Container();
            },
          ),
        ),
      );
      final dynamic exception = tester.takeException();
      expect(exception, isFlutterError);
      final FlutterError error = exception as FlutterError;
      expect(error.diagnostics.length, 5);
      expect(error.diagnostics[2].level, DiagnosticLevel.hint);
      expect(
        error.diagnostics[2].toStringDeep(),
        equalsIgnoringHashCodes(
          'There are several ways to avoid this problem. The simplest is to\n'
          'use a Builder to get a context that is "under" the Scaffold. For\n'
          'an example of this, please see the documentation for\n'
          'Scaffold.of():\n'
          '  https://api.flutter.dev/flutter/material/Scaffold/of.html\n',
        ),
      );
      expect(error.diagnostics[3].level, DiagnosticLevel.hint);
      expect(
        error.diagnostics[3].toStringDeep(),
        equalsIgnoringHashCodes(
          'A more efficient solution is to split your build function into\n'
          'several widgets. This introduces a new context from which you can\n'
          'obtain the Scaffold. In this solution, you would have an outer\n'
          'widget that creates the Scaffold populated by instances of your\n'
          'new inner widgets, and then in these inner widgets you would use\n'
          'Scaffold.of().\n'
          'A less elegant but more expedient solution is assign a GlobalKey\n'
          'to the Scaffold, then use the key.currentState property to obtain\n'
          'the ScaffoldState rather than using the Scaffold.of() function.\n',
        ),
      );
      expect(error.diagnostics[4], isA<DiagnosticsProperty<Element>>());
      expect(
        error.toStringDeep(),
        'FlutterError\n'
        '   Scaffold.of() called with a context that does not contain a\n'
        '   Scaffold.\n'
        '   No Scaffold ancestor could be found starting from the context\n'
        '   that was passed to Scaffold.of(). This usually happens when the\n'
        '   context provided is from the same StatefulWidget as that whose\n'
        '   build function actually creates the Scaffold widget being sought.\n'
        '   There are several ways to avoid this problem. The simplest is to\n'
        '   use a Builder to get a context that is "under" the Scaffold. For\n'
        '   an example of this, please see the documentation for\n'
        '   Scaffold.of():\n'
        '     https://api.flutter.dev/flutter/material/Scaffold/of.html\n'
        '   A more efficient solution is to split your build function into\n'
        '   several widgets. This introduces a new context from which you can\n'
        '   obtain the Scaffold. In this solution, you would have an outer\n'
        '   widget that creates the Scaffold populated by instances of your\n'
        '   new inner widgets, and then in these inner widgets you would use\n'
        '   Scaffold.of().\n'
        '   A less elegant but more expedient solution is assign a GlobalKey\n'
        '   to the Scaffold, then use the key.currentState property to obtain\n'
        '   the ScaffoldState rather than using the Scaffold.of() function.\n'
        '   The context used was:\n'
        '     Builder\n',
      );
      await tester.pumpAndSettle();
    });

    testWidgets('Call to Scaffold.geometryOf() without context', (WidgetTester tester) async {
      ValueListenable<ScaffoldGeometry>? geometry;
      await tester.pumpWidget(
        MaterialApp(
          home: Builder(
            builder: (BuildContext context) {
              geometry = Scaffold.geometryOf(context);
              return Container();
            },
          ),
        ),
      );
      final dynamic exception = tester.takeException();
      expect(exception, isFlutterError);
      expect(geometry, isNull);
      final FlutterError error = exception as FlutterError;
      expect(error.diagnostics.length, 5);
      expect(error.diagnostics[2].level, DiagnosticLevel.hint);
      expect(
        error.diagnostics[2].toStringDeep(),
        equalsIgnoringHashCodes(
          'There are several ways to avoid this problem. The simplest is to\n'
          'use a Builder to get a context that is "under" the Scaffold. For\n'
          'an example of this, please see the documentation for\n'
          'Scaffold.of():\n'
          '  https://api.flutter.dev/flutter/material/Scaffold/of.html\n',
        ),
      );
      expect(error.diagnostics[3].level, DiagnosticLevel.hint);
      expect(
        error.diagnostics[3].toStringDeep(),
        equalsIgnoringHashCodes(
          'A more efficient solution is to split your build function into\n'
          'several widgets. This introduces a new context from which you can\n'
          'obtain the Scaffold. In this solution, you would have an outer\n'
          'widget that creates the Scaffold populated by instances of your\n'
          'new inner widgets, and then in these inner widgets you would use\n'
          'Scaffold.geometryOf().\n',
        ),
      );
      expect(error.diagnostics[4], isA<DiagnosticsProperty<Element>>());
      expect(
        error.toStringDeep(),
        'FlutterError\n'
        '   Scaffold.geometryOf() called with a context that does not contain\n'
        '   a Scaffold.\n'
        '   This usually happens when the context provided is from the same\n'
        '   StatefulWidget as that whose build function actually creates the\n'
        '   Scaffold widget being sought.\n'
        '   There are several ways to avoid this problem. The simplest is to\n'
        '   use a Builder to get a context that is "under" the Scaffold. For\n'
        '   an example of this, please see the documentation for\n'
        '   Scaffold.of():\n'
        '     https://api.flutter.dev/flutter/material/Scaffold/of.html\n'
        '   A more efficient solution is to split your build function into\n'
        '   several widgets. This introduces a new context from which you can\n'
        '   obtain the Scaffold. In this solution, you would have an outer\n'
        '   widget that creates the Scaffold populated by instances of your\n'
        '   new inner widgets, and then in these inner widgets you would use\n'
        '   Scaffold.geometryOf().\n'
        '   The context used was:\n'
        '     Builder\n',
      );
      await tester.pumpAndSettle();
    });

    testWidgets('FloatingActionButton always keeps the same position regardless of extendBodyBehindAppBar', (WidgetTester tester) async {
      await tester.pumpWidget(MaterialApp(
        home: Scaffold(
          appBar: AppBar(),
          floatingActionButton: FloatingActionButton(
            onPressed: () {},
            child: const Icon(Icons.add),
          ),
          floatingActionButtonLocation: FloatingActionButtonLocation.endTop,
        ),
      ));
      final Offset defaultOffset = tester.getCenter(find.byType(FloatingActionButton));

      await tester.pumpWidget(MaterialApp(
        home: Scaffold(
          appBar: AppBar(),
          floatingActionButton: FloatingActionButton(
            onPressed: () {},
            child: const Icon(Icons.add),
          ),
          floatingActionButtonLocation: FloatingActionButtonLocation.endTop,
          extendBodyBehindAppBar: true,
        ),
      ));
      final Offset extendedBodyOffset = tester.getCenter(find.byType(FloatingActionButton));

      expect(defaultOffset.dy, extendedBodyOffset.dy);
    });
  });

  testWidgets('ScaffoldMessenger.maybeOf can return null if not found', (WidgetTester tester) async {
    ScaffoldMessengerState? scaffoldMessenger;
    const Key tapTarget = Key('tap-target');
    await tester.pumpWidget(Directionality(
      textDirection: TextDirection.ltr,
      child: MediaQuery(
        data: const MediaQueryData(),
        child: Scaffold(
          body: Builder(
            builder: (BuildContext context) {
              return GestureDetector(
                key: tapTarget,
                onTap: () {
                  scaffoldMessenger = ScaffoldMessenger.maybeOf(context);
                },
                behavior: HitTestBehavior.opaque,
                child: const SizedBox(
                  height: 100.0,
                  width: 100.0,
                ),
              );
            },
          ),
        ),
      ),
    ));
    await tester.tap(find.byKey(tapTarget));
    await tester.pump();
    expect(scaffoldMessenger, isNull);
  });

  testWidgets('ScaffoldMessenger.of will assert if not found', (WidgetTester tester) async {
    const Key tapTarget = Key('tap-target');

    final List<dynamic> exceptions = <dynamic>[];
    final FlutterExceptionHandler? oldHandler = FlutterError.onError;
    FlutterError.onError = (FlutterErrorDetails details) {
      exceptions.add(details.exception);
    };

    await tester.pumpWidget(Directionality(
      textDirection: TextDirection.ltr,
      child: MediaQuery(
        data: const MediaQueryData(),
        child: Scaffold(
          body: Builder(
            builder: (BuildContext context) {
              return GestureDetector(
                key: tapTarget,
                onTap: () {
                  ScaffoldMessenger.of(context);
                },
                behavior: HitTestBehavior.opaque,
                child: const SizedBox(
                  height: 100.0,
                  width: 100.0,
                ),
              );
            },
          ),
        ),
      ),
    ));
    await tester.tap(find.byKey(tapTarget));
    FlutterError.onError = oldHandler;

    expect(exceptions.length, 1);
    // ignore: avoid_dynamic_calls
    expect(exceptions.single.runtimeType, FlutterError);
    final FlutterError error = exceptions.first as FlutterError;
    expect(error.diagnostics.length, 5);
    expect(error.diagnostics[2], isA<DiagnosticsProperty<Element>>());
    expect(error.diagnostics[3], isA<DiagnosticsBlock>());
    expect(error.diagnostics[4].level, DiagnosticLevel.hint);
    expect(
      error.diagnostics[4].toStringDeep(),
      equalsIgnoringHashCodes(
        'Typically, the ScaffoldMessenger widget is introduced by the\n'
        'MaterialApp at the top of your application widget tree.\n',
      ),
    );
    expect(error.toStringDeep(), equalsIgnoringHashCodes(
      'FlutterError\n'
      '   No ScaffoldMessenger widget found.\n'
      '   Builder widgets require a ScaffoldMessenger widget ancestor.\n'
      '   The specific widget that could not find a ScaffoldMessenger\n'
      '   ancestor was:\n'
      '     Builder\n'
      '   The ancestors of this widget were:\n'
      '     KeyedSubtree-[GlobalKey#00000]\n'
      '     _BodyBuilder\n'
      '     MediaQuery\n'
      '     LayoutId-[<_ScaffoldSlot.body>]\n'
      '     CustomMultiChildLayout\n'
      '     _ActionsMarker\n'
      '     Actions\n'
      '     AnimatedBuilder\n'
      '     DefaultTextStyle\n'
      '     AnimatedDefaultTextStyle\n'
      '     _InkFeatures-[GlobalKey#00000 ink renderer]\n'
      '     NotificationListener<LayoutChangedNotification>\n'
      '     PhysicalModel\n'
      '     AnimatedPhysicalModel\n'
      '     Material\n'
      '     _ScrollNotificationObserverScope\n'
      '     NotificationListener<ScrollNotification>\n'
      '     NotificationListener<ScrollMetricsNotification>\n'
      '     ScrollNotificationObserver\n'
      '     _ScaffoldScope\n'
      '     Scaffold\n'
      '     MediaQuery\n'
      '     Directionality\n'
      '     View-[GlobalObjectKey TestWindow#e6136]\n'
      '     [root]\n'
      '   Typically, the ScaffoldMessenger widget is introduced by the\n'
      '   MaterialApp at the top of your application widget tree.\n',
    ));
  });

  testWidgets('ScaffoldMessenger checks for nesting when a new Scaffold is registered', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/77251
    const String snackBarContent = 'SnackBar Content';
    await tester.pumpWidget(MaterialApp(
      home: Builder(
        builder: (BuildContext context) => Scaffold(
          body: Scaffold(
            body: TextButton(
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute<void>(
                    builder: (BuildContext context) {
                      return Scaffold(
                        body: Column(
                          children: <Widget>[
                            TextButton(
                              onPressed: () {
                                const SnackBar snackBar = SnackBar(
                                  content: Text(snackBarContent),
                                  behavior: SnackBarBehavior.floating,
                                );
                                ScaffoldMessenger.of(context).showSnackBar(snackBar);
                              },
                              child: const Text('Show SnackBar'),
                            ),
                            TextButton(
                              onPressed: () {
                                Navigator.pop(context, null);
                              },
                              child: const Text('Pop route'),
                            ),
                          ],
                        ),
                      );
                    },
                  ),
                );
              },
              child: const Text('Push route'),
            ),
          ),
        ),
      ),
    ));

    expect(find.text(snackBarContent), findsNothing);
    await tester.tap(find.text('Push route'));
    await tester.pumpAndSettle();
    expect(find.text(snackBarContent), findsNothing);
    expect(find.text('Pop route'), findsOneWidget);

    // Show SnackBar on second page
    await tester.tap(find.text('Show SnackBar'));
    await tester.pump();
    expect(find.text(snackBarContent), findsOneWidget);
    // Pop the second page, the SnackBar completes a hero animation to the next route.
    // If we have not handled the nested Scaffolds properly, this will throw an
    // exception as duplicate SnackBars on the first route would have a common hero tag.
    await tester.tap(find.text('Pop route'));
    await tester.pump();
    // There are SnackBars two during the execution of the hero animation.
    expect(find.text(snackBarContent), findsNWidgets(2));
    await tester.pumpAndSettle();
    expect(find.text(snackBarContent), findsOneWidget);
    // Allow the SnackBar to animate out
    await tester.pump(const Duration(seconds: 4));
    await tester.pumpAndSettle();
    expect(find.text(snackBarContent), findsNothing);
  });

  testWidgets('Drawer can be dismissed with escape keyboard shortcut', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/106131
    bool isDrawerOpen = false;
    bool isEndDrawerOpen = false;

    await tester.pumpWidget(MaterialApp(
      home: Scaffold(
        drawer: Container(
          color: Colors.blue,
        ),
        onDrawerChanged: (bool isOpen) {
          isDrawerOpen = isOpen;
        },
        endDrawer: Container(
          color: Colors.green,
        ),
        onEndDrawerChanged: (bool isOpen) {
          isEndDrawerOpen = isOpen;
        },
        body: Container(),
      ),
    ));

    final ScaffoldState scaffoldState = tester.state(find.byType(Scaffold));

    scaffoldState.openDrawer();
    await tester.pumpAndSettle();
    expect(isDrawerOpen, true);
    expect(isEndDrawerOpen, false);

    // Try to dismiss the drawer with the shortcut key
    await tester.sendKeyEvent(LogicalKeyboardKey.escape);
    await tester.pumpAndSettle();
    expect(isDrawerOpen, false);
    expect(isEndDrawerOpen, false);

    scaffoldState.openEndDrawer();
    await tester.pumpAndSettle();
    expect(isDrawerOpen, false);
    expect(isEndDrawerOpen, true);

    // Try to dismiss the drawer with the shortcut key
    await tester.sendKeyEvent(LogicalKeyboardKey.escape);
    await tester.pumpAndSettle();
    expect(isDrawerOpen, false);
    expect(isEndDrawerOpen, false);
  });

  testWidgets('ScaffoldMessenger showSnackBar throws an intuitive error message if called during build', (WidgetTester tester) async {
    await tester.pumpWidget(MaterialApp(
      home: Scaffold(
        body: Builder(
          builder: (BuildContext context) {
            ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('SnackBar')));
            return const SizedBox.shrink();
          },
        ),
      ),
    ));

    final FlutterError error = tester.takeException() as FlutterError;
    final ErrorSummary summary = error.diagnostics.first as ErrorSummary;
    expect(summary.toString(), 'The showSnackBar() method cannot be called during build.');
  });

  testWidgets('Persistent BottomSheet is not dismissible via a11y means', (WidgetTester tester) async {
    final Key bottomSheetKey = UniqueKey();

    await tester.pumpWidget(MaterialApp(
      home: Scaffold(
        bottomSheet: Container(
          key: bottomSheetKey,
          height: 44,
          color: Colors.blue,
          child: const Text('BottomSheet'),
        ),
      ),
    ));

    expect(
      tester.getSemantics(find.byKey(bottomSheetKey)),
      // Having the redundant argument value makes the intent of the test clear.
      // ignore: avoid_redundant_argument_values
      matchesSemantics(label: 'BottomSheet', hasDismissAction: false),
    );
  });

  // Regression test for https://github.com/flutter/flutter/issues/117004
  testWidgets('can rebuild and remove bottomSheet at the same time', (WidgetTester tester) async {
    bool themeIsLight = true;
    bool? defaultBottomSheet = true;
    final GlobalKey bottomSheetKey1 = GlobalKey();
    final GlobalKey bottomSheetKey2 = GlobalKey();
    late StateSetter setState;

    await tester.pumpWidget(
      StatefulBuilder(
        builder: (BuildContext context, StateSetter stateSetter) {
          setState = stateSetter;
          return MaterialApp(
            theme: themeIsLight ? ThemeData.light() : ThemeData.dark(),
            home: Scaffold(
              bottomSheet: defaultBottomSheet == null
                  ? null
                  : defaultBottomSheet!
                    ? Container(
                        key: bottomSheetKey1,
                        width: double.infinity,
                        height: 100,
                        color: Colors.blue,
                        child: const Text('BottomSheet'),
                      )
                    : Container(
                        key: bottomSheetKey2,
                        width: double.infinity,
                        height: 100,
                        color: Colors.red,
                        child: const Text('BottomSheet'),
                      ),
              body: const Placeholder(),
            ),
          );
        },
      ),
    );

    expect(find.byKey(bottomSheetKey1), findsOneWidget);
    expect(find.byKey(bottomSheetKey2), findsNothing);

    // Change to the other bottomSheet.
    setState(() {
      defaultBottomSheet = false;
    });
    expect(find.byKey(bottomSheetKey1), findsOneWidget);
    expect(find.byKey(bottomSheetKey2), findsNothing);
    await tester.pumpAndSettle();
    expect(find.byKey(bottomSheetKey1), findsNothing);
    expect(find.byKey(bottomSheetKey2), findsOneWidget);

    // Set bottomSheet to null, which starts its exit animation.
    setState(() {
      defaultBottomSheet = null;
    });
    expect(find.byKey(bottomSheetKey1), findsNothing);
    expect(find.byKey(bottomSheetKey2), findsOneWidget);

    // While the bottomSheet is on the way out, change the theme to cause it to
    // rebuild.
    setState(() {
      themeIsLight = false;
    });
    expect(find.byKey(bottomSheetKey1), findsNothing);
    expect(find.byKey(bottomSheetKey2), findsOneWidget);

    // The most recent bottomSheet remains on screen during the exit animation.
    await tester.pump(_bottomSheetExitDuration);
    expect(find.byKey(bottomSheetKey1), findsNothing);
    expect(find.byKey(bottomSheetKey2), findsOneWidget);

    // After animating out, the bottomSheet is gone.
    await tester.pumpAndSettle();
    expect(find.byKey(bottomSheetKey1), findsNothing);
    expect(find.byKey(bottomSheetKey2), findsNothing);

    expect(tester.takeException(), isNull);
  });
}

class _GeometryListener extends StatefulWidget {
  const _GeometryListener();

  @override
  _GeometryListenerState createState() => _GeometryListenerState();
}

class _GeometryListenerState extends State<_GeometryListener> {
  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      painter: cache,
    );
  }

  int numNotifications = 0;
  ValueListenable<ScaffoldGeometry>? geometryListenable;
  late _GeometryCachePainter cache;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    final ValueListenable<ScaffoldGeometry> newListenable = Scaffold.geometryOf(context);
    if (geometryListenable == newListenable) {
      return;
    }

    if (geometryListenable != null) {
      geometryListenable!.removeListener(onGeometryChanged);
    }

    geometryListenable = newListenable;
    geometryListenable!.addListener(onGeometryChanged);
    cache = _GeometryCachePainter(geometryListenable!);
  }

  void onGeometryChanged() {
    numNotifications += 1;
  }
}

// The Scaffold.geometryOf() value is only available at paint time.
// To fetch it for the tests we implement this CustomPainter that just
// caches the ScaffoldGeometry value in its paint method.
class _GeometryCachePainter extends CustomPainter {
  _GeometryCachePainter(this.geometryListenable) : super(repaint: geometryListenable);

  final ValueListenable<ScaffoldGeometry> geometryListenable;

  late ScaffoldGeometry value;
  @override
  void paint(Canvas canvas, Size size) {
    value = geometryListenable.value;
  }

  @override
  bool shouldRepaint(_GeometryCachePainter oldDelegate) {
    return true;
  }
}

class _CustomPageRoute<T> extends PageRoute<T> {
  _CustomPageRoute({
    required this.builder,
    RouteSettings super.settings = const RouteSettings(),
    this.maintainState = true,
    super.fullscreenDialog,
  }) : assert(builder != null);

  final WidgetBuilder builder;

  @override
  Duration get transitionDuration => const Duration(milliseconds: 300);

  @override
  Color? get barrierColor => null;

  @override
  String? get barrierLabel => null;

  @override
  final bool maintainState;

  @override
  Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
    return builder(context);
  }

  @override
  Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
    return child;
  }
}
