// 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 'dart:math';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  group('Basic floating action button locations', () {
    testWidgets('still animates motion when the floating action button is null', (WidgetTester tester) async {
      await tester.pumpWidget(buildFrame(fab: null, location: null));

      expect(find.byType(FloatingActionButton), findsNothing);
      expect(tester.binding.transientCallbackCount, 0);

      await tester.pumpWidget(buildFrame(fab: null, location: FloatingActionButtonLocation.endFloat));

      expect(find.byType(FloatingActionButton), findsNothing);
      expect(tester.binding.transientCallbackCount, greaterThan(0));

      await tester.pumpWidget(buildFrame(fab: null, location: FloatingActionButtonLocation.centerFloat));

      expect(find.byType(FloatingActionButton), findsNothing);
      expect(tester.binding.transientCallbackCount, greaterThan(0));
    });

    testWidgets('moves fab from center to end and back', (WidgetTester tester) async {
      await tester.pumpWidget(buildFrame(location: FloatingActionButtonLocation.endFloat));

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

      await tester.pumpWidget(buildFrame(location: FloatingActionButtonLocation.centerFloat));

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

      await tester.pumpAndSettle();

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(400.0, 356.0));
      expect(tester.binding.transientCallbackCount, 0);

      await tester.pumpWidget(buildFrame(location: FloatingActionButtonLocation.endFloat));

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

      await tester.pumpAndSettle();

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(756.0, 356.0));
      expect(tester.binding.transientCallbackCount, 0);
    });

    testWidgets('moves to and from custom-defined positions', (WidgetTester tester) async {
      await tester.pumpWidget(buildFrame(location: const _StartTopFloatingActionButtonLocation()));

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

      await tester.pumpWidget(buildFrame(location: FloatingActionButtonLocation.centerFloat));
      expect(tester.binding.transientCallbackCount, greaterThan(0));

      await tester.pumpAndSettle();

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(400.0, 356.0));
      expect(tester.binding.transientCallbackCount, 0);

      await tester.pumpWidget(buildFrame(location: const _StartTopFloatingActionButtonLocation()));

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

      await tester.pumpAndSettle();

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(44.0, 56.0));
      expect(tester.binding.transientCallbackCount, 0);

    });

    group('interrupts in-progress animations without jumps', () {
      _GeometryListener? geometryListener;
      ScaffoldGeometry? geometry;
      _GeometryListenerState? listenerState;
      Size? previousRect;
      Iterable<double>? previousRotations;

      // The maximum amounts we expect the fab width and height to change
      // during one step of a transition.
      const double maxDeltaWidth = 12.5;
      const double maxDeltaHeight = 12.5;

      // The maximum amounts we expect the fab icon to rotate during one step
      // of a transition.
      const double maxDeltaRotation = 0.09;

      // We'll listen to the Scaffold's geometry for any 'jumps' to detect
      // changes in the size and rotation of the fab.
      void setupListener(WidgetTester tester) {
        // Measure the delta in width and height of the fab, and check that it never grows
        // by more than the expected maximum deltas.
        void check() {
          geometry = listenerState?.cache.value;
          final Size? currentRect = geometry?.floatingActionButtonArea?.size;
          // Measure the delta in width and height of the rect, and check that
          // it never grows by more than a safe amount.
          if (previousRect != null && currentRect != null) {
            final double deltaWidth = currentRect.width - previousRect!.width;
            final double deltaHeight = currentRect.height - previousRect!.height;
            expect(
              deltaWidth.abs(),
              lessThanOrEqualTo(maxDeltaWidth),
              reason: "The Floating Action Button's width should not change "
                  'faster than $maxDeltaWidth per animation step.\n'
                  'Previous rect: $previousRect, current rect: $currentRect',
            );
            expect(
              deltaHeight.abs(),
              lessThanOrEqualTo(maxDeltaHeight),
              reason: "The Floating Action Button's width should not change "
                  'faster than $maxDeltaHeight per animation step.\n'
                  'Previous rect: $previousRect, current rect: $currentRect',
            );
          }
          previousRect = currentRect;

          // Measure the delta in rotation.
          // Check that it never grows by more than a safe amount.
          //
          // Note that there may be multiple transitions all active at
          // the same time. We are concerned only with the closest one.
          final Iterable<RotationTransition> rotationTransitions = tester.widgetList(
            find.byType(RotationTransition),
          );
          final Iterable<double> currentRotations = rotationTransitions.map((RotationTransition t) => t.turns.value);

          if (previousRotations != null && previousRotations!.isNotEmpty
              && currentRotations != null && currentRotations.isNotEmpty
              && previousRect != null && currentRect != null) {
            final List<double> deltas = <double>[];
            for (final double currentRotation in currentRotations) {
              late double minDelta;
              for (final double previousRotation in previousRotations!) {
                final double delta = (previousRotation - currentRotation).abs();
                minDelta = delta;
                minDelta = min(delta, minDelta);
              }
              deltas.add(minDelta);
            }

            if (deltas.where((double delta) => delta < maxDeltaRotation).isEmpty) {
              fail(
                "The Floating Action Button's rotation should not change "
                'faster than $maxDeltaRotation per animation step.\n'
                'Detected deltas were: $deltas\n'
                'Previous values: $previousRotations, current values: $currentRotations\n'
                'Previous rect: $previousRect, current rect: $currentRect',
              );
            }
          }
          previousRotations = currentRotations;
        }

        listenerState = tester.state(find.byType(_GeometryListener));
        listenerState!.geometryListenable!.addListener(check);
      }

      setUp(() {
        // We create the geometry listener here, but it can only be set up
        // after it is pumped into the widget tree and a tester is
        // available.
        geometryListener = _GeometryListener();
        geometry = null;
        listenerState = null;
        previousRect = null;
        previousRotations = null;
      });

      testWidgets('moving the fab to centerFloat', (WidgetTester tester) async {
        // Create a scaffold with the fab at endFloat
        await tester.pumpWidget(buildFrame(location: FloatingActionButtonLocation.endFloat, listener: geometryListener));
        setupListener(tester);

        // Move the fab to centerFloat'
        await tester.pumpWidget(buildFrame(location: FloatingActionButtonLocation.centerFloat, listener: geometryListener));
        await tester.pumpAndSettle();
      });

      testWidgets('interrupting motion towards the StartTop location.', (WidgetTester tester) async {
        await tester.pumpWidget(buildFrame(location: FloatingActionButtonLocation.centerFloat, listener: geometryListener));
        setupListener(tester);

        // Move the fab to the top start after creating the fab.
        await tester.pumpWidget(buildFrame(location: const _StartTopFloatingActionButtonLocation(), listener: geometryListener));
        await tester.pump(kFloatingActionButtonSegue ~/ 2);

        // Interrupt motion to move to the end float
        await tester.pumpWidget(buildFrame(location: FloatingActionButtonLocation.endFloat, listener: geometryListener));
        await tester.pumpAndSettle();
      });

      testWidgets('interrupting entrance to remove the fab.', (WidgetTester tester) async {
        await tester.pumpWidget(buildFrame(fab: null, location: FloatingActionButtonLocation.centerFloat, listener: geometryListener));
        setupListener(tester);

        // Animate the fab in.
        await tester.pumpWidget(buildFrame(location: FloatingActionButtonLocation.endFloat, listener: geometryListener));
        await tester.pump(kFloatingActionButtonSegue ~/ 2);

        // Remove the fab.
        await tester.pumpWidget(
          buildFrame(
            fab: null,
            location: FloatingActionButtonLocation.endFloat,
            listener: geometryListener,
          ),
        );
        await tester.pumpAndSettle();
      });

      testWidgets('interrupting entrance of a new fab.', (WidgetTester tester) async {
        await tester.pumpWidget(
          buildFrame(
            fab: null,
            location: FloatingActionButtonLocation.endFloat,
            listener: geometryListener,
          ),
        );
        setupListener(tester);

        // Bring in a new fab.
        await tester.pumpWidget(buildFrame(location: FloatingActionButtonLocation.centerFloat, listener: geometryListener));
        await tester.pump(kFloatingActionButtonSegue ~/ 2);

        // Interrupt motion to move the fab.
        await tester.pumpWidget(
          buildFrame(
            location: FloatingActionButtonLocation.endFloat,
            listener: geometryListener,
          ),
        );
        await tester.pumpAndSettle();
      });
    });
  });

  testWidgets('Docked floating action button locations', (WidgetTester tester) async {
    await tester.pumpWidget(
      buildFrame(
        location: FloatingActionButtonLocation.endDocked,
        bab: const SizedBox(height: 100.0),
        viewInsets: EdgeInsets.zero,
      ),
    );

    // Scaffold 800x600, FAB is 56x56, BAB is 800x100, FAB's center is
    // at the top of the BAB.
    expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(756.0, 500.0));

    await tester.pumpWidget(
      buildFrame(
        location: FloatingActionButtonLocation.centerDocked,
        bab: const SizedBox(height: 100.0),
        viewInsets: EdgeInsets.zero,
      ),
    );
    await tester.pumpAndSettle();
    expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(400.0, 500.0));


    await tester.pumpWidget(
      buildFrame(
        location: FloatingActionButtonLocation.endDocked,
        bab: const SizedBox(height: 100.0),
        viewInsets: EdgeInsets.zero,
      ),
    );
    await tester.pumpAndSettle();
    expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(756.0, 500.0));
  });

  testWidgets('Docked floating action button locations: no BAB, small BAB', (WidgetTester tester) async {
    await tester.pumpWidget(
      buildFrame(
        location: FloatingActionButtonLocation.endDocked,
        viewInsets: EdgeInsets.zero,
      ),
    );
    expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(756.0, 572.0));

    await tester.pumpWidget(
      buildFrame(
        location: FloatingActionButtonLocation.endDocked,
        bab: const SizedBox(height: 16.0),
        viewInsets: EdgeInsets.zero,
      ),
    );
    expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(756.0, 572.0));
  });

  testWidgets('Mini-start-top floating action button location', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          appBar: AppBar(),
          floatingActionButton: FloatingActionButton(onPressed: () { }, mini: true),
          floatingActionButtonLocation: FloatingActionButtonLocation.miniStartTop,
          body: Column(
            children: const <Widget>[
              ListTile(
                leading: CircleAvatar(),
              ),
            ],
          ),
        ),
      ),
    );
    expect(tester.getCenter(find.byType(FloatingActionButton)).dx, tester.getCenter(find.byType(CircleAvatar)).dx);
    expect(tester.getCenter(find.byType(FloatingActionButton)).dy, kToolbarHeight);
  });

  testWidgets('Start-top floating action button location LTR', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          appBar: AppBar(),
          floatingActionButton: const FloatingActionButton(onPressed: null),
          floatingActionButtonLocation: FloatingActionButtonLocation.startTop,
        ),
      ),
    );
    expect(tester.getRect(find.byType(FloatingActionButton)), rectMoreOrLessEquals(const Rect.fromLTWH(16.0, 28.0, 56.0, 56.0)));
  });

  testWidgets('End-top floating action button location RTL', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.rtl,
          child: Scaffold(
            appBar: AppBar(),
            floatingActionButton: const FloatingActionButton(onPressed: null),
            floatingActionButtonLocation: FloatingActionButtonLocation.endTop,
          ),
        ),
      ),
    );
    expect(tester.getRect(find.byType(FloatingActionButton)), rectMoreOrLessEquals(const Rect.fromLTWH(16.0, 28.0, 56.0, 56.0)));
  });

  testWidgets('Start-top floating action button location RTL', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Directionality(
          textDirection: TextDirection.rtl,
          child: Scaffold(
            appBar: AppBar(),
            floatingActionButton: const FloatingActionButton(onPressed: null),
            floatingActionButtonLocation: FloatingActionButtonLocation.startTop,
          ),
        ),
      ),
    );
    expect(tester.getRect(find.byType(FloatingActionButton)), rectMoreOrLessEquals(const Rect.fromLTWH(800.0 - 56.0 - 16.0, 28.0, 56.0, 56.0)));
  });

  testWidgets('End-top floating action button location LTR', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          appBar: AppBar(),
          floatingActionButton: const FloatingActionButton(onPressed: null),
          floatingActionButtonLocation: FloatingActionButtonLocation.endTop,
        ),
      ),
    );
    expect(tester.getRect(find.byType(FloatingActionButton)), rectMoreOrLessEquals(const Rect.fromLTWH(800.0 - 56.0 - 16.0, 28.0, 56.0, 56.0)));
  });

  group('New Floating Action Button Locations', () {
    testWidgets('startTop', (WidgetTester tester) async {
      await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.startTop));

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_leftOffsetX, _topOffsetY));
    });

    testWidgets('centerTop', (WidgetTester tester) async {
      await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.centerTop));

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_centerOffsetX, _topOffsetY));
    });

    testWidgets('endTop', (WidgetTester tester) async {
      await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.endTop));

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_rightOffsetX, _topOffsetY));
    });

    testWidgets('startFloat', (WidgetTester tester) async {
      await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.startFloat));

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_leftOffsetX, _floatOffsetY));
    });

    testWidgets('centerFloat', (WidgetTester tester) async {
      await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.centerFloat));

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_centerOffsetX, _floatOffsetY));
    });

    testWidgets('endFloat', (WidgetTester tester) async {
      await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.endFloat));

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_rightOffsetX, _floatOffsetY));
    });

    testWidgets('startDocked', (WidgetTester tester) async {
      await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.startDocked));

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_leftOffsetX, _dockedOffsetY));
    });

    testWidgets('centerDocked', (WidgetTester tester) async {
      await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.centerDocked));

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_centerOffsetX, _dockedOffsetY));
    });

    testWidgets('endDocked', (WidgetTester tester) async {
      await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.endDocked));

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_rightOffsetX, _dockedOffsetY));
    });

    testWidgets('miniStartTop', (WidgetTester tester) async {
      await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.miniStartTop));

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_miniLeftOffsetX, _topOffsetY));
    });

    testWidgets('miniEndTop', (WidgetTester tester) async {
      await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.miniEndTop));

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_miniRightOffsetX, _topOffsetY));
    });

    testWidgets('miniStartFloat', (WidgetTester tester) async {
      await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.miniStartFloat));

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_miniLeftOffsetX, _miniFloatOffsetY));
    });

    testWidgets('miniCenterFloat', (WidgetTester tester) async {
      await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.miniCenterFloat));

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_centerOffsetX, _miniFloatOffsetY));
    });

    testWidgets('miniEndFloat', (WidgetTester tester) async {
      await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.miniEndFloat));

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_miniRightOffsetX, _miniFloatOffsetY));
    });

    testWidgets('miniStartDocked', (WidgetTester tester) async {
      await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.miniStartDocked));

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_miniLeftOffsetX, _dockedOffsetY));
    });

    testWidgets('miniEndDocked', (WidgetTester tester) async {
      await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.miniEndDocked));

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_miniRightOffsetX, _dockedOffsetY));
    });

    // Test a few RTL cases.

    testWidgets('endTop, RTL', (WidgetTester tester) async {
      await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.endTop, textDirection: TextDirection.rtl));

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_leftOffsetX, _topOffsetY));
    });

    testWidgets('miniStartFloat, RTL', (WidgetTester tester) async {
      await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.miniStartFloat, textDirection: TextDirection.rtl));

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_miniRightOffsetX, _miniFloatOffsetY));
    });
  });

  group('Custom Floating Action Button Locations', () {
    testWidgets('Almost end float', (WidgetTester tester) async {
      await tester.pumpWidget(_singleFabScaffold(_AlmostEndFloatFabLocation()));

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_rightOffsetX - 50, _floatOffsetY));
    });

    testWidgets('Almost end float, RTL', (WidgetTester tester) async {
      await tester.pumpWidget(_singleFabScaffold(_AlmostEndFloatFabLocation(), textDirection: TextDirection.rtl));

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_leftOffsetX + 50, _floatOffsetY));
    });

    testWidgets('Quarter end top', (WidgetTester tester) async {
      await tester.pumpWidget(_singleFabScaffold(_QuarterEndTopFabLocation()));

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_rightOffsetX * 0.75 + _leftOffsetX * 0.25, _topOffsetY));
    });

    testWidgets('Quarter end top, RTL', (WidgetTester tester) async {
      await tester.pumpWidget(_singleFabScaffold(_QuarterEndTopFabLocation(), textDirection: TextDirection.rtl));

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_leftOffsetX * 0.75 + _rightOffsetX * 0.25, _topOffsetY));
    });
  });

  group('Moves involving new locations', () {
    testWidgets('Moves between new locations and new locations', (WidgetTester tester) async {
      await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.centerTop));

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_centerOffsetX, _topOffsetY));

      await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.startFloat));

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

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_leftOffsetX, _floatOffsetY));

      await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.startDocked));

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

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_leftOffsetX, _dockedOffsetY));
    });

    testWidgets('Moves between new locations and old locations', (WidgetTester tester) async {
      await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.endDocked));

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_rightOffsetX, _dockedOffsetY));

      await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.startDocked));

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

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_leftOffsetX, _dockedOffsetY));

      await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.centerFloat));

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

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_centerOffsetX, _floatOffsetY));

      await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.centerTop));

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

      expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_centerOffsetX, _topOffsetY));
    });

    testWidgets('Moves between new locations and old locations with custom animator', (WidgetTester tester) async {
      final FloatingActionButtonAnimator animator = _LinearMovementFabAnimator();
      const Offset begin = Offset(_centerOffsetX, _topOffsetY);
      const Offset end = Offset(_rightOffsetX - 50, _floatOffsetY);

      final Duration animationDuration = kFloatingActionButtonSegue * 2;

      await tester.pumpWidget(_singleFabScaffold(
        FloatingActionButtonLocation.centerTop,
        animator: animator,
      ));

      expect(find.byType(FloatingActionButton), findsOneWidget);

      expect(tester.binding.transientCallbackCount, 0);

      await tester.pumpWidget(_singleFabScaffold(
        _AlmostEndFloatFabLocation(),
        animator: animator,
      ));

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

      await tester.pump(animationDuration * 0.25);

      expect(tester.getCenter(find.byType(FloatingActionButton)), offsetMoreOrLessEquals(begin * 0.75 + end * 0.25));

      await tester.pump(animationDuration * 0.25);

      expect(tester.getCenter(find.byType(FloatingActionButton)), offsetMoreOrLessEquals(begin * 0.5 + end * 0.5));

      await tester.pump(animationDuration * 0.25);

      expect(tester.getCenter(find.byType(FloatingActionButton)), offsetMoreOrLessEquals(begin * 0.25 + end * 0.75));

      await tester.pumpAndSettle();

      expect(tester.getCenter(find.byType(FloatingActionButton)), end);

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

  group('Locations account for safe interactive areas', () {
    Widget _buildTest(
      FloatingActionButtonLocation location,
      MediaQueryData data,
      Key key, {
      bool mini = false,
      bool appBar = false,
      bool bottomNavigationBar = false,
      bool bottomSheet = false,
      bool resizeToAvoidBottomInset = true,
    }) {
      return MaterialApp(
        home: MediaQuery(
          data: data,
          child: Scaffold(
            resizeToAvoidBottomInset: resizeToAvoidBottomInset,
            bottomSheet: bottomSheet ? const SizedBox(
              height: 100,
              child: Center(child: Text('BottomSheet')),
            ) : null,
            appBar: appBar ? AppBar(title: const Text('Demo')) : null,
            bottomNavigationBar: bottomNavigationBar ? BottomNavigationBar(
              items: const <BottomNavigationBarItem>[
                BottomNavigationBarItem(
                  icon: Icon(Icons.star),
                  label: '0',
                ),
                BottomNavigationBarItem(
                  icon: Icon(Icons.star_border),
                  label: '1',
                ),
              ],
              currentIndex: 0,
            ) : null,
            floatingActionButtonLocation: location,
            floatingActionButton: Builder(
              builder: (BuildContext context) {
                return FloatingActionButton(
                  onPressed: () {
                    ScaffoldMessenger.of(context).showSnackBar(
                      const SnackBar(content: Text('Snacky!')),
                    );
                  },
                  child: const Text('FAB'),
                  mini: mini,
                  key: key,
                );
              },
            ),
          ),
        ),
      );
    }

    // Test float locations, for each (6), keyboard presented or not:
    //  - Default
    //  - with resizeToAvoidBottomInset: false
    //  - with BottomNavigationBar
    //  - with BottomNavigationBar and resizeToAvoidBottomInset: false
    //  - with BottomNavigationBar & BottomSheet
    //  - with BottomNavigationBar & BottomSheet, resizeToAvoidBottomInset: false
    //  - with BottomSheet
    //  - with BottomSheet and resizeToAvoidBottomInset: false
    //  - with SnackBar
    Future<void> _runFloatTests(
      WidgetTester tester,
      FloatingActionButtonLocation location, {
      required Rect defaultRect,
      required Rect bottomNavigationBarRect,
      required Rect bottomSheetRect,
      required Rect snackBarRect,
      bool mini = false,
    }) async  {
      const double keyboardHeight = 200.0;
      const double viewPadding = 50.0;
      final Key floatingActionButton = UniqueKey();
      const double bottomNavHeight = 106.0;
      // Default
      await tester.pumpWidget(_buildTest(
        location,
        const MediaQueryData(viewPadding: EdgeInsets.only(bottom: viewPadding)),
        floatingActionButton,
        mini: mini,
      ));
      expect(
        tester.getRect(find.byKey(floatingActionButton)),
        rectMoreOrLessEquals(defaultRect),
      );
      // Present keyboard and check position, should change
      await tester.pumpWidget(_buildTest(
        location,
        const MediaQueryData(
          viewPadding: EdgeInsets.only(bottom: viewPadding),
          viewInsets: EdgeInsets.only(bottom: keyboardHeight),
        ),
        floatingActionButton,
        mini: mini,
      ));
      expect(
        tester.getRect(find.byKey(floatingActionButton)),
        rectMoreOrLessEquals(defaultRect.translate(
          0.0,
          viewPadding - keyboardHeight,
        )),
      );

      // With resizeToAvoidBottomInset: false
      // With keyboard presented, should maintain default position
      await tester.pumpWidget(_buildTest(
        location,
        const MediaQueryData(
          viewPadding: EdgeInsets.only(bottom: viewPadding),
          viewInsets: EdgeInsets.only(bottom: keyboardHeight),
        ),
        floatingActionButton,
        resizeToAvoidBottomInset: false,
        mini: mini,
      ));
      expect(
        tester.getRect(find.byKey(floatingActionButton)),
        rectMoreOrLessEquals(defaultRect),
      );

      // BottomNavigationBar default
      await tester.pumpWidget(_buildTest(
        location,
        const MediaQueryData(
          padding: EdgeInsets.only(bottom: viewPadding),
          viewPadding: EdgeInsets.only(bottom: viewPadding),
        ),
        floatingActionButton,
        bottomNavigationBar: true,
        mini: mini,
      ));
      expect(
        tester.getRect(find.byKey(floatingActionButton)),
        rectMoreOrLessEquals(bottomNavigationBarRect),
      );
      // Present keyboard and check position, FAB position changes
      await tester.pumpWidget(_buildTest(
        location,
        const MediaQueryData(
          padding: EdgeInsets.only(bottom: viewPadding),
          viewPadding: EdgeInsets.only(bottom: viewPadding),
          viewInsets: EdgeInsets.only(bottom: keyboardHeight),
        ),
        floatingActionButton,
        bottomNavigationBar: true,
        mini: mini,
      ));
      expect(
        tester.getRect(find.byKey(floatingActionButton)),
        rectMoreOrLessEquals(bottomNavigationBarRect.translate(
          0.0,
          -keyboardHeight + bottomNavHeight,
        )),
      );

      // BottomNavigationBar with resizeToAvoidBottomInset: false
      // With keyboard presented, should maintain default position
      await tester.pumpWidget(_buildTest(
        location,
        const MediaQueryData(
          padding: EdgeInsets.only(bottom: viewPadding),
          viewPadding: EdgeInsets.only(bottom: viewPadding),
          viewInsets: EdgeInsets.only(bottom: keyboardHeight),
        ),
        floatingActionButton,
        bottomNavigationBar: true,
        resizeToAvoidBottomInset: false,
        mini: mini,
      ));
      expect(
        tester.getRect(find.byKey(floatingActionButton)),
        rectMoreOrLessEquals(bottomNavigationBarRect),
      );

      // BottomNavigationBar + BottomSheet default
      await tester.pumpWidget(_buildTest(
        location,
        const MediaQueryData(
          padding: EdgeInsets.only(bottom: viewPadding),
          viewPadding: EdgeInsets.only(bottom: viewPadding),
        ),
        floatingActionButton,
        bottomNavigationBar: true,
        bottomSheet: true,
        mini: mini,
      ));
      expect(
        tester.getRect(find.byKey(floatingActionButton)),
        rectMoreOrLessEquals(bottomSheetRect.translate(
          0.0,
          -bottomNavHeight,
        )),
      );
      // Present keyboard and check position, FAB position changes
      await tester.pumpWidget(_buildTest(
        location,
        const MediaQueryData(
          padding: EdgeInsets.only(bottom: viewPadding),
          viewPadding: EdgeInsets.only(bottom: viewPadding),
          viewInsets: EdgeInsets.only(bottom: keyboardHeight),
        ),
        floatingActionButton,
        bottomNavigationBar: true,
        bottomSheet: true,
        mini: mini,
      ));
      expect(
        tester.getRect(find.byKey(floatingActionButton)),
        rectMoreOrLessEquals(bottomSheetRect.translate(
          0.0,
          -keyboardHeight,
        )),
      );

      // BottomNavigationBar + BottomSheet with resizeToAvoidBottomInset: false
      // With keyboard presented, should maintain default position
      await tester.pumpWidget(_buildTest(
        location,
        const MediaQueryData(
          padding: EdgeInsets.only(bottom: viewPadding),
          viewPadding: EdgeInsets.only(bottom: viewPadding),
          viewInsets: EdgeInsets.only(bottom: keyboardHeight),
        ),
        floatingActionButton,
        bottomNavigationBar: true,
        bottomSheet: true,
        resizeToAvoidBottomInset: false,
        mini: mini,
      ));
      expect(
        tester.getRect(find.byKey(floatingActionButton)),
        rectMoreOrLessEquals(bottomSheetRect.translate(
          0.0,
          -bottomNavHeight,
        )),
      );

      // BottomSheet default
      await tester.pumpWidget(_buildTest(
        location,
        const MediaQueryData(viewPadding: EdgeInsets.only(bottom: viewPadding)),
        floatingActionButton,
        bottomSheet: true,
        mini: mini,
      ));
      expect(
        tester.getRect(find.byKey(floatingActionButton)),
        rectMoreOrLessEquals(bottomSheetRect),
      );
      // Present keyboard and check position, bottomSheet and FAB both resize
      await tester.pumpWidget(_buildTest(
        location,
        const MediaQueryData(
          viewPadding: EdgeInsets.only(bottom: viewPadding),
          viewInsets: EdgeInsets.only(bottom: keyboardHeight),
        ),
        floatingActionButton,
        bottomSheet: true,
        mini: mini,
      ));
      expect(
        tester.getRect(find.byKey(floatingActionButton)),
        rectMoreOrLessEquals(bottomSheetRect.translate(0.0, -keyboardHeight)),
      );

      // bottomSheet with resizeToAvoidBottomInset: false
      // With keyboard presented, should maintain default bottomSheet position
      await tester.pumpWidget(_buildTest(
        location,
        const MediaQueryData(
          viewPadding: EdgeInsets.only(bottom: viewPadding),
          viewInsets: EdgeInsets.only(bottom: keyboardHeight),
        ),
        floatingActionButton,
        bottomSheet: true,
        resizeToAvoidBottomInset: false,
        mini: mini,
      ));
      expect(
        tester.getRect(find.byKey(floatingActionButton)),
        rectMoreOrLessEquals(bottomSheetRect),
      );

      // SnackBar default
      await tester.pumpWidget(_buildTest(
        location,
        const MediaQueryData(viewPadding: EdgeInsets.only(bottom: viewPadding)),
        floatingActionButton,
        mini: mini,
      ));
      await tester.tap(find.byKey(floatingActionButton));
      await tester.pumpAndSettle(); // Show SnackBar
      expect(
        tester.getRect(find.byKey(floatingActionButton)),
        rectMoreOrLessEquals(snackBarRect),
      );

      // SnackBar when resized for presented keyboard
      await tester.pumpWidget(_buildTest(
        location,
        const MediaQueryData(
          viewPadding: EdgeInsets.only(bottom: viewPadding),
          viewInsets: EdgeInsets.only(bottom: keyboardHeight),
        ),
        floatingActionButton,
        mini: mini,
      ));
      await tester.tap(find.byKey(floatingActionButton));
      await tester.pumpAndSettle(); // Show SnackBar
      expect(
        tester.getRect(find.byKey(floatingActionButton)),
        rectMoreOrLessEquals(snackBarRect.translate(0.0, -keyboardHeight + kFloatingActionButtonMargin/2)),
      );
    }

    testWidgets('startFloat', (WidgetTester tester) async {
      const Rect defaultRect = Rect.fromLTRB(16.0, 478.0, 72.0, 534.0);
      // Positioned relative to BottomNavigationBar
      const Rect bottomNavigationBarRect = Rect.fromLTRB(16.0, 422.0, 72.0, 478.0);
      // Position relative to BottomSheet
      const Rect bottomSheetRect = Rect.fromLTRB(16.0, 472.0, 72.0, 528.0);
      // Positioned relative to SnackBar
      const Rect snackBarRect = Rect.fromLTRB(16.0, 478.0, 72.0, 534.0);
      await _runFloatTests(
        tester,
        FloatingActionButtonLocation.startFloat,
        defaultRect: defaultRect,
        bottomNavigationBarRect: bottomNavigationBarRect,
        bottomSheetRect: bottomSheetRect,
        snackBarRect: snackBarRect,
      );
    });

    testWidgets('miniStartFloat', (WidgetTester tester) async {
      const Rect defaultRect = Rect.fromLTRB(12.0, 490.0, 60.0, 538.0);
      // Positioned relative to BottomNavigationBar
      const Rect bottomNavigationBarRect = Rect.fromLTRB(12.0, 434.0, 60.0, 482.0);
      // Positioned relative to BottomSheet
      const Rect bottomSheetRect = Rect.fromLTRB(12.0, 480.0, 60.0, 528.0);
      // Positioned relative to SnackBar
      const Rect snackBarRect = Rect.fromLTRB(12.0, 490.0, 60.0, 538.0);
      await _runFloatTests(
        tester,
        FloatingActionButtonLocation.miniStartFloat,
        defaultRect: defaultRect,
        bottomNavigationBarRect: bottomNavigationBarRect,
        bottomSheetRect: bottomSheetRect,
        snackBarRect: snackBarRect,
        mini: true,
      );
    });

    testWidgets('centerFloat', (WidgetTester tester) async {
      const Rect defaultRect = Rect.fromLTRB(372.0, 478.0, 428.0, 534.0);
      // Positioned relative to BottomNavigationBar
      const Rect bottomNavigationBarRect = Rect.fromLTRB(372.0, 422.0, 428.0, 478.0);
      // Positioned relative to BottomSheet
      const Rect bottomSheetRect = Rect.fromLTRB(372.0, 472.0, 428.0, 528.0);
      // Positioned relative to SnackBar
      const Rect snackBarRect = Rect.fromLTRB(372.0, 478.0, 428.0, 534.0);
      await _runFloatTests(
        tester,
        FloatingActionButtonLocation.centerFloat,
        defaultRect: defaultRect,
        bottomNavigationBarRect: bottomNavigationBarRect,
        bottomSheetRect: bottomSheetRect,
        snackBarRect: snackBarRect,
      );
    });

    testWidgets('miniCenterFloat', (WidgetTester tester) async {
      const Rect defaultRect = Rect.fromLTRB(376.0, 490.0, 424.0, 538.0);
      // Positioned relative to BottomNavigationBar
      const Rect bottomNavigationBarRect = Rect.fromLTRB(376.0, 434.0, 424.0, 482.0);
      // Positioned relative to BottomSheet
      const Rect bottomSheetRect = Rect.fromLTRB(376.0, 480.0, 424.0, 528.0);
      // Positioned relative to SnackBar
      const Rect snackBarRect = Rect.fromLTRB(376.0, 490.0, 424.0, 538.0);
      await _runFloatTests(
        tester,
        FloatingActionButtonLocation.miniCenterFloat,
        defaultRect: defaultRect,
        bottomNavigationBarRect: bottomNavigationBarRect,
        bottomSheetRect: bottomSheetRect,
        snackBarRect: snackBarRect,
        mini: true,
      );
    });

    testWidgets('endFloat', (WidgetTester tester) async {
      const Rect defaultRect = Rect.fromLTRB(728.0, 478.0, 784.0, 534.0);
      // Positioned relative to BottomNavigationBar
      const Rect bottomNavigationBarRect = Rect.fromLTRB(728.0, 422.0, 784.0, 478.0);
      // Positioned relative to BottomSheet
      const Rect bottomSheetRect = Rect.fromLTRB(728.0, 472.0, 784.0, 528.0);
      // Positioned relative to SnackBar
      const Rect snackBarRect = Rect.fromLTRB(728.0, 478.0, 784.0, 534.0);
      await _runFloatTests(
        tester,
        FloatingActionButtonLocation.endFloat,
        defaultRect: defaultRect,
        bottomNavigationBarRect: bottomNavigationBarRect,
        bottomSheetRect: bottomSheetRect,
        snackBarRect: snackBarRect,
      );
    });

    testWidgets('miniEndFloat', (WidgetTester tester) async {
      const Rect defaultRect = Rect.fromLTRB(740.0, 490.0, 788.0, 538.0);
      // Positioned relative to BottomNavigationBar
      const Rect bottomNavigationBarRect = Rect.fromLTRB(740.0, 434.0, 788.0, 482.0);
      // Positioned relative to BottomSheet
      const Rect bottomSheetRect = Rect.fromLTRB(740.0, 480.0, 788.0, 528.0);
      // Positioned relative to SnackBar
      const Rect snackBarRect = Rect.fromLTRB(740.0, 490.0, 788.0, 538.0);
      await _runFloatTests(
        tester,
        FloatingActionButtonLocation.miniEndFloat,
        defaultRect: defaultRect,
        bottomNavigationBarRect: bottomNavigationBarRect,
        bottomSheetRect: bottomSheetRect,
        snackBarRect: snackBarRect,
        mini: true,
      );
    });

    // Test docked locations, for each (6), keyboard presented or not.
    // If keyboard is presented and resizeToAvoidBottomInset: true, test whether
    // the FAB is away from the keyboard(and thus not clipped):
    //  - Default
    //  - Default with resizeToAvoidBottomInset: false
    //  - docked with BottomNavigationBar
    //  - docked with BottomNavigationBar and resizeToAvoidBottomInset: false
    //  - docked with BottomNavigationBar & BottomSheet
    //  - docked with BottomNavigationBar & BottomSheet, resizeToAvoidBottomInset: false
    //  - with SnackBar
    Future<void> _runDockedTests(
      WidgetTester tester,
      FloatingActionButtonLocation location, {
      required Rect defaultRect,
      required Rect bottomNavigationBarRect,
      required Rect bottomSheetRect,
      required Rect snackBarRect,
      bool mini = false,
    }) async  {
      const double keyboardHeight = 200.0;
      const double viewPadding = 50.0;
      const double bottomNavHeight = 106.0;
      const double scaffoldHeight = 600.0;
      final Key floatingActionButton = UniqueKey();
      final double fabHeight = mini ? 48.0 : 56.0;
      // Default
      await tester.pumpWidget(_buildTest(
        location,
        const MediaQueryData(viewPadding: EdgeInsets.only(bottom: viewPadding)),
        floatingActionButton,
        mini: mini,
      ));
      expect(
        tester.getRect(find.byKey(floatingActionButton)),
        rectMoreOrLessEquals(defaultRect),
      );
      // Present keyboard and check position, should change
      await tester.pumpWidget(_buildTest(
        location,
        const MediaQueryData(
          viewPadding: EdgeInsets.only(bottom: viewPadding),
          viewInsets: EdgeInsets.only(bottom: keyboardHeight),
        ),
        floatingActionButton,
        mini: mini,
      ));
      expect(
        tester.getRect(find.byKey(floatingActionButton)),
        rectMoreOrLessEquals(defaultRect.translate(
          0.0,
          viewPadding - keyboardHeight - kFloatingActionButtonMargin,
        )),
      );
      // The FAB should be away from the keyboard
      expect(
        tester.getRect(find.byKey(floatingActionButton)).bottom,
        lessThan(scaffoldHeight - keyboardHeight),
      );

      // With resizeToAvoidBottomInset: false
      // With keyboard presented, should maintain default position
      await tester.pumpWidget(_buildTest(
        location,
        const MediaQueryData(
          viewPadding: EdgeInsets.only(bottom: viewPadding),
          viewInsets: EdgeInsets.only(bottom: keyboardHeight),
        ),
        floatingActionButton,
        resizeToAvoidBottomInset: false,
        mini: mini,
      ));
      expect(
        tester.getRect(find.byKey(floatingActionButton)),
        rectMoreOrLessEquals(defaultRect),
      );

      // BottomNavigationBar default
      await tester.pumpWidget(_buildTest(
        location,
        const MediaQueryData(
          padding: EdgeInsets.only(bottom: viewPadding),
          viewPadding: EdgeInsets.only(bottom: viewPadding),
        ),
        floatingActionButton,
        bottomNavigationBar: true,
        mini: mini,
      ));
      expect(
        tester.getRect(find.byKey(floatingActionButton)),
        rectMoreOrLessEquals(bottomNavigationBarRect),
      );
      // Present keyboard and check position, FAB position changes
      await tester.pumpWidget(_buildTest(
        location,
        const MediaQueryData(
          padding: EdgeInsets.only(bottom: viewPadding),
          viewPadding: EdgeInsets.only(bottom: viewPadding),
          viewInsets: EdgeInsets.only(bottom: keyboardHeight),
        ),
        floatingActionButton,
        bottomNavigationBar: true,
        mini: mini,
      ));
      expect(
        tester.getRect(find.byKey(floatingActionButton)),
        rectMoreOrLessEquals(bottomNavigationBarRect.translate(
          0.0,
          bottomNavHeight + fabHeight / 2.0 - keyboardHeight - kFloatingActionButtonMargin - fabHeight,
        )),
      );
      // The FAB should be away from the keyboard
      expect(
        tester.getRect(find.byKey(floatingActionButton)).bottom,
        lessThan(scaffoldHeight - keyboardHeight),
      );

      // BottomNavigationBar with resizeToAvoidBottomInset: false
      // With keyboard presented, should maintain default position
      await tester.pumpWidget(_buildTest(
        location,
        const MediaQueryData(
          padding: EdgeInsets.only(bottom: viewPadding),
          viewPadding: EdgeInsets.only(bottom: viewPadding),
          viewInsets: EdgeInsets.only(bottom: keyboardHeight),
        ),
        floatingActionButton,
        bottomNavigationBar: true,
        resizeToAvoidBottomInset: false,
        mini: mini,
      ));
      expect(
        tester.getRect(find.byKey(floatingActionButton)),
        rectMoreOrLessEquals(bottomNavigationBarRect),
      );

      // BottomNavigationBar + BottomSheet default
      await tester.pumpWidget(_buildTest(
        location,
        const MediaQueryData(
          padding: EdgeInsets.only(bottom: viewPadding),
          viewPadding: EdgeInsets.only(bottom: viewPadding),
        ),
        floatingActionButton,
        bottomNavigationBar: true,
        bottomSheet: true,
        mini: mini,
      ));
      expect(
        tester.getRect(find.byKey(floatingActionButton)),
        rectMoreOrLessEquals(bottomSheetRect),
      );
      // Present keyboard and check position, FAB position changes
      await tester.pumpWidget(_buildTest(
        location,
        const MediaQueryData(
          padding: EdgeInsets.only(bottom: viewPadding),
          viewPadding: EdgeInsets.only(bottom: viewPadding),
          viewInsets: EdgeInsets.only(bottom: keyboardHeight),
        ),
        floatingActionButton,
        bottomNavigationBar: true,
        bottomSheet: true,
        mini: mini,
      ));
      expect(
        tester.getRect(find.byKey(floatingActionButton)),
        rectMoreOrLessEquals(bottomSheetRect.translate(
          0.0,
          -keyboardHeight + bottomNavHeight,
        )),
      );
      // The FAB should be away from the keyboard
      expect(
        tester.getRect(find.byKey(floatingActionButton)).bottom,
        lessThan(scaffoldHeight - keyboardHeight),
      );

      // BottomNavigationBar + BottomSheet with resizeToAvoidBottomInset: false
      // With keyboard presented, should maintain default position
      await tester.pumpWidget(_buildTest(
        location,
        const MediaQueryData(
          padding: EdgeInsets.only(bottom: viewPadding),
          viewPadding: EdgeInsets.only(bottom: viewPadding),
          viewInsets: EdgeInsets.only(bottom: keyboardHeight),
        ),
        floatingActionButton,
        bottomNavigationBar: true,
        bottomSheet: true,
        resizeToAvoidBottomInset: false,
        mini: mini,
      ));
      expect(
        tester.getRect(find.byKey(floatingActionButton)),
        rectMoreOrLessEquals(bottomSheetRect),
      );

      // SnackBar default
      await tester.pumpWidget(_buildTest(
        location,
        const MediaQueryData(viewPadding: EdgeInsets.only(bottom: viewPadding)),
        floatingActionButton,
        mini: mini,
      ));
      await tester.tap(find.byKey(floatingActionButton));
      await tester.pumpAndSettle(); // Show SnackBar
      expect(
        tester.getRect(find.byKey(floatingActionButton)),
        rectMoreOrLessEquals(snackBarRect),
      );

      // SnackBar with BottomNavigationBar
      await tester.pumpWidget(_buildTest(
        location,
        const MediaQueryData(
          padding: EdgeInsets.only(bottom: viewPadding),
          viewPadding: EdgeInsets.only(bottom: viewPadding),
        ),
        floatingActionButton,
        bottomNavigationBar: true,
        mini: mini,
      ));
      await tester.tap(find.byKey(floatingActionButton));
      await tester.pumpAndSettle(); // Show SnackBar
      expect(
        tester.getRect(find.byKey(floatingActionButton)),
        rectMoreOrLessEquals(snackBarRect.translate(0.0, -bottomNavHeight)),
      );

      // SnackBar when resized for presented keyboard
      await tester.pumpWidget(_buildTest(
        location,
        const MediaQueryData(
          viewPadding: EdgeInsets.only(bottom: viewPadding),
          viewInsets: EdgeInsets.only(bottom: keyboardHeight),
        ),
        floatingActionButton,
        mini: mini,
      ));
      await tester.tap(find.byKey(floatingActionButton));
      await tester.pumpAndSettle(); // Show SnackBar
      expect(
        tester.getRect(find.byKey(floatingActionButton)),
        rectMoreOrLessEquals(snackBarRect.translate(0.0, -keyboardHeight)),
      );
      // The FAB should be away from the keyboard
      expect(
        tester.getRect(find.byKey(floatingActionButton)).bottom,
        lessThan(scaffoldHeight - keyboardHeight),
      );
    }

    testWidgets('startDocked', (WidgetTester tester) async {
      const Rect defaultRect = Rect.fromLTRB(16.0, 494.0, 72.0, 550.0);
      // Positioned relative to BottomNavigationBar
      const Rect bottomNavigationBarRect = Rect.fromLTRB(16.0, 466.0, 72.0, 522.0);
      // Positioned relative to BottomNavigationBar & BottomSheet
      const Rect bottomSheetRect = Rect.fromLTRB(16.0, 366.0, 72.0, 422.0);
      // Positioned relative to SnackBar
      const Rect snackBarRect = Rect.fromLTRB(16.0, 486.0, 72.0, 542.0);
      await _runDockedTests(
        tester,
        FloatingActionButtonLocation.startDocked,
        defaultRect: defaultRect,
        bottomNavigationBarRect: bottomNavigationBarRect,
        bottomSheetRect: bottomSheetRect,
        snackBarRect: snackBarRect,
      );
    });

    testWidgets('miniStartDocked', (WidgetTester tester) async {
      const Rect defaultRect = Rect.fromLTRB(12.0, 502.0, 60.0, 550.0);
      // Positioned relative to BottomNavigationBar
      const Rect bottomNavigationBarRect = Rect.fromLTRB(12.0, 470.0, 60.0, 518.0);
      // Positioned relative to BottomNavigationBar & BottomSheet
      const Rect bottomSheetRect = Rect.fromLTRB(12.0, 370.0, 60.0, 418.0);
      // Positioned relative to SnackBar
      const Rect snackBarRect = Rect.fromLTRB(12.0, 494.0, 60.0, 542.0);
      await _runDockedTests(
        tester,
        FloatingActionButtonLocation.miniStartDocked,
        defaultRect: defaultRect,
        bottomNavigationBarRect: bottomNavigationBarRect,
        bottomSheetRect: bottomSheetRect,
        snackBarRect: snackBarRect,
        mini: true,
      );
    });

    testWidgets('centerDocked', (WidgetTester tester) async {
      const Rect defaultRect = Rect.fromLTRB(372.0, 494.0, 428.0, 550.0);
      // Positioned relative to BottomNavigationBar
      const Rect bottomNavigationBarRect = Rect.fromLTRB(372.0, 466.0, 428.0, 522.0);
      // Positioned relative to BottomNavigationBar & BottomSheet
      const Rect bottomSheetRect = Rect.fromLTRB(372.0, 366.0, 428.0, 422.0);
      // Positioned relative to SnackBar
      const Rect snackBarRect = Rect.fromLTRB(372.0, 486.0, 428.0, 542.0);
      await _runDockedTests(
        tester,
        FloatingActionButtonLocation.centerDocked,
        defaultRect: defaultRect,
        bottomNavigationBarRect: bottomNavigationBarRect,
        bottomSheetRect: bottomSheetRect,
        snackBarRect: snackBarRect,
      );
    });

    testWidgets('miniCenterDocked', (WidgetTester tester) async {
      const Rect defaultRect = Rect.fromLTRB(376.0, 502.0, 424.0, 550.0);
      // Positioned relative to BottomNavigationBar
      const Rect bottomNavigationBarRect = Rect.fromLTRB(376.0, 470.0, 424.0, 518.0);
      // Positioned relative to BottomNavigationBar & BottomSheet
      const Rect bottomSheetRect = Rect.fromLTRB(376.0, 370.0, 424.0, 418.0);
      // Positioned relative to SnackBar
      const Rect snackBarRect = Rect.fromLTRB(376.0, 494.0, 424.0, 542.0);
      await _runDockedTests(
        tester,
        FloatingActionButtonLocation.miniCenterDocked,
        defaultRect: defaultRect,
        bottomNavigationBarRect: bottomNavigationBarRect,
        bottomSheetRect: bottomSheetRect,
        snackBarRect: snackBarRect,
        mini: true,
      );
    });

    testWidgets('endDocked', (WidgetTester tester) async {
      const Rect defaultRect = Rect.fromLTRB(728.0, 494.0, 784.0, 550.0);
      // Positioned relative to BottomNavigationBar
      const Rect bottomNavigationBarRect = Rect.fromLTRB(728.0, 466.0, 784.0, 522.0);
      // Positioned relative to BottomNavigationBar & BottomSheet
      const Rect bottomSheetRect = Rect.fromLTRB(728.0, 366.0, 784.0, 422.0);
      // Positioned relative to SnackBar
      const Rect snackBarRect = Rect.fromLTRB(728.0, 486.0, 784.0, 542.0);
      await _runDockedTests(
        tester,
        FloatingActionButtonLocation.endDocked,
        defaultRect: defaultRect,
        bottomNavigationBarRect: bottomNavigationBarRect,
        bottomSheetRect: bottomSheetRect,
        snackBarRect: snackBarRect,
      );
    });

    testWidgets('miniEndDocked', (WidgetTester tester) async {
      const Rect defaultRect = Rect.fromLTRB(740.0, 502.0, 788.0, 550.0);
      // Positioned relative to BottomNavigationBar
      const Rect bottomNavigationBarRect = Rect.fromLTRB(740.0, 470.0, 788.0, 518.0);
      // Positioned relative to BottomNavigationBar & BottomSheet
      const Rect bottomSheetRect = Rect.fromLTRB(740.0, 370.0, 788.0, 418.0);
      // Positioned relative to SnackBar
      const Rect snackBarRect = Rect.fromLTRB(740.0, 494.0, 788.0, 542.0);
      await _runDockedTests(
        tester,
        FloatingActionButtonLocation.miniEndDocked,
        defaultRect: defaultRect,
        bottomNavigationBarRect: bottomNavigationBarRect,
        bottomSheetRect: bottomSheetRect,
        snackBarRect: snackBarRect,
        mini: true,
      );
    });

    // Test top locations, for each (6):
    //  - Default
    //  - with an AppBar
    Future<void> _runTopTests(
      WidgetTester tester,
      FloatingActionButtonLocation location, {
      required Rect defaultRect,
      required Rect appBarRect,
      bool mini = false,
    }) async  {
      const double viewPadding = 50.0;
      final Key floatingActionButton = UniqueKey();
      // Default
      await tester.pumpWidget(_buildTest(
        location,
        const MediaQueryData(viewPadding: EdgeInsets.only(top: viewPadding)),
        floatingActionButton,
        mini: mini,
      ));
      expect(
        tester.getRect(find.byKey(floatingActionButton)),
        rectMoreOrLessEquals(defaultRect),
      );

      // AppBar default
      await tester.pumpWidget(_buildTest(
        location,
        const MediaQueryData(viewPadding: EdgeInsets.only(top: viewPadding)),
        floatingActionButton,
        appBar: true,
        mini: mini,
      ));
      expect(
        tester.getRect(find.byKey(floatingActionButton)),
        rectMoreOrLessEquals(appBarRect),
      );
    }

    testWidgets('startTop', (WidgetTester tester) async {
      const Rect defaultRect = Rect.fromLTRB(16.0, 50.0, 72.0, 106.0);
      // Positioned relative to AppBar
      const Rect appBarRect = Rect.fromLTRB(16.0, 28.0, 72.0, 84.0);
      await _runTopTests(
        tester,
        FloatingActionButtonLocation.startTop,
        defaultRect: defaultRect,
        appBarRect: appBarRect,
      );
    });

    testWidgets('miniStartTop', (WidgetTester tester) async {
      const Rect defaultRect = Rect.fromLTRB(12.0, 50.0, 60.0, 98.0);
      // Positioned relative to AppBar
      const Rect appBarRect = Rect.fromLTRB(12.0, 32.0, 60.0, 80.0);
      await _runTopTests(
        tester,
        FloatingActionButtonLocation.miniStartTop,
        defaultRect: defaultRect,
        appBarRect: appBarRect,
        mini: true,
      );
    });

    testWidgets('centerTop', (WidgetTester tester) async {
      const Rect defaultRect = Rect.fromLTRB(372.0, 50.0, 428.0, 106.0);
      // Positioned relative to AppBar
      const Rect appBarRect = Rect.fromLTRB(372.0, 28.0, 428.0, 84.0);
      await _runTopTests(
        tester,
        FloatingActionButtonLocation.centerTop,
        defaultRect: defaultRect,
        appBarRect: appBarRect,
      );
    });

    testWidgets('miniCenterTop', (WidgetTester tester) async {
      const Rect defaultRect = Rect.fromLTRB(376.0, 50.0, 424.0, 98.0);
      // Positioned relative to AppBar
      const Rect appBarRect = Rect.fromLTRB(376.0, 32.0, 424.0, 80.0);
      await _runTopTests(
        tester,
        FloatingActionButtonLocation.miniCenterTop,
        defaultRect: defaultRect,
        appBarRect: appBarRect,
        mini: true,
      );
    });

    testWidgets('endTop', (WidgetTester tester) async {
      const Rect defaultRect = Rect.fromLTRB(728.0, 50.0, 784.0, 106.0);
      // Positioned relative to AppBar
      const Rect appBarRect = Rect.fromLTRB(728.0, 28.0, 784.0, 84.0);
      await _runTopTests(
        tester,
        FloatingActionButtonLocation.endTop,
        defaultRect: defaultRect,
        appBarRect: appBarRect,
      );
    });

    testWidgets('miniEndTop', (WidgetTester tester) async {
      const Rect defaultRect = Rect.fromLTRB(740.0, 50.0, 788.0, 98.0);
      // Positioned relative to AppBar
      const Rect appBarRect = Rect.fromLTRB(740.0, 32.0, 788.0, 80.0);
      await _runTopTests(
        tester,
        FloatingActionButtonLocation.miniEndTop,
        defaultRect: defaultRect,
        appBarRect: appBarRect,
        mini: true,
      );
    });
  });
}

class _GeometryListener extends StatefulWidget {
  @override
  State 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;
  }
}

const double _leftOffsetX = 44.0;
const double _centerOffsetX = 400.0;
const double _rightOffsetX = 756.0;
const double _miniLeftOffsetX = _leftOffsetX - kMiniButtonOffsetAdjustment;
const double _miniRightOffsetX = _rightOffsetX + kMiniButtonOffsetAdjustment;

const double _topOffsetY = 56.0;
const double _floatOffsetY = 500.0;
const double _dockedOffsetY = 544.0;
const double _miniFloatOffsetY = _floatOffsetY + kMiniButtonOffsetAdjustment;

Widget _singleFabScaffold(
  FloatingActionButtonLocation location,
  {
    FloatingActionButtonAnimator? animator,
    bool mini = false,
    TextDirection textDirection = TextDirection.ltr,
  }
) {
  return MaterialApp(
    home: Directionality(
      textDirection: textDirection,
      child: Scaffold(
        appBar: AppBar(
          title: const Text('FloatingActionButtonLocation Test.'),
        ),
        bottomNavigationBar: BottomNavigationBar(
          items: const <BottomNavigationBarItem>[
            BottomNavigationBarItem(
              icon: Icon(Icons.home),
              label: 'Home',
            ),
            BottomNavigationBarItem(
              icon: Icon(Icons.school),
              label: 'School',
            ),
          ],
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {},
          child: const Icon(Icons.beach_access),
          mini: mini,
        ),
        floatingActionButtonLocation: location,
        floatingActionButtonAnimator: animator,
      ),
    ),
  );
}

// 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;
  }
}

Widget buildFrame({
  FloatingActionButton? fab = const FloatingActionButton(
    onPressed: null,
    child: Text('1'),
  ),
  FloatingActionButtonLocation? location,
  _GeometryListener? listener,
  TextDirection textDirection = TextDirection.ltr,
  EdgeInsets viewInsets = const EdgeInsets.only(bottom: 200.0),
  Widget? bab,
}) {
  return Localizations(
    locale: const Locale('en', 'us'),
    delegates: const <LocalizationsDelegate<dynamic>>[
      DefaultWidgetsLocalizations.delegate,
      DefaultMaterialLocalizations.delegate,
    ],
    child: Directionality(
      textDirection: textDirection,
      child: MediaQuery(
        data: MediaQueryData(viewInsets: viewInsets),
        child: Scaffold(
          appBar: AppBar(title: const Text('FabLocation Test')),
          floatingActionButtonLocation: location,
          floatingActionButton: fab,
          bottomNavigationBar: bab,
          body: listener,
        ),
      ),
    ),
  );
}

class _StartTopFloatingActionButtonLocation extends FloatingActionButtonLocation {
  const _StartTopFloatingActionButtonLocation();

  @override
  Offset getOffset(ScaffoldPrelayoutGeometry scaffoldGeometry) {
    double fabX;
    assert(scaffoldGeometry.textDirection != null);
    switch (scaffoldGeometry.textDirection) {
      case TextDirection.rtl:
        final double startPadding = kFloatingActionButtonMargin + scaffoldGeometry.minInsets.right;
        fabX = scaffoldGeometry.scaffoldSize.width - scaffoldGeometry.floatingActionButtonSize.width - startPadding;
        break;
      case TextDirection.ltr:
        final double startPadding = kFloatingActionButtonMargin + scaffoldGeometry.minInsets.left;
        fabX = startPadding;
        break;
    }
    final double fabY = scaffoldGeometry.contentTop - (scaffoldGeometry.floatingActionButtonSize.height / 2.0);
    return Offset(fabX, fabY);
  }
}

class _AlmostEndFloatFabLocation extends StandardFabLocation
    with FabEndOffsetX, FabFloatOffsetY {
  @override
  double getOffsetX (ScaffoldPrelayoutGeometry scaffoldGeometry, double adjustment) {
    final double directionalAdjustment =
        scaffoldGeometry.textDirection == TextDirection.ltr ? -50.0 : 50.0;
    return super.getOffsetX(scaffoldGeometry, adjustment) + directionalAdjustment;
  }
}

class _QuarterEndTopFabLocation extends StandardFabLocation
    with FabEndOffsetX, FabTopOffsetY {
  @override
  double getOffsetX (ScaffoldPrelayoutGeometry scaffoldGeometry, double adjustment) {
    return super.getOffsetX(scaffoldGeometry, adjustment) * 0.75
        + (FloatingActionButtonLocation.startFloat as StandardFabLocation)
            .getOffsetX(scaffoldGeometry, adjustment) * 0.25;
  }
}

class _LinearMovementFabAnimator extends FloatingActionButtonAnimator {
  @override
  Offset getOffset({required Offset begin, required Offset end, required double progress}) {
    return Offset.lerp(begin, end, progress)!;
  }

  @override
  Animation<double> getScaleAnimation({required Animation<double> parent}) {
    return const AlwaysStoppedAnimation<double>(1.0);
  }

  @override
  Animation<double> getRotationAnimation({required Animation<double> parent}) {
    return const AlwaysStoppedAnimation<double>(1.0);
  }
}
