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

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

void main() {

  // Helpers
  final Widget sliverBox = SliverToBoxAdapter(
    child: Container(
      color: Colors.amber,
      height: 150.0,
      width: 150,
    ),
  );
  Widget boilerplate(
    List<Widget> slivers, {
      ScrollController? controller,
      Axis scrollDirection = Axis.vertical,
    }) {
    return MaterialApp(
      theme:  ThemeData(
        materialTapTargetSize: MaterialTapTargetSize.padded,
      ),
      home: Scaffold(
        body: CustomScrollView(
          scrollDirection: scrollDirection,
          slivers: slivers,
          controller: controller,
        ),
      ),
    );
  }

  group('SliverFillRemaining', () {
    group('hasScrollBody: true, default', () {
      testWidgets('no siblings', (WidgetTester tester) async {
        final ScrollController controller = ScrollController();
        await tester.pumpWidget(
          Directionality(
            textDirection: TextDirection.ltr,
            child: CustomScrollView(
              controller: controller,
              slivers: <Widget>[
                SliverFillRemaining(child: Container()),
              ],
            ),
          ),
        );
        expect(
          tester.renderObject<RenderBox>(find.byType(Container)).size.height,
          equals(600.0),
        );

        controller.jumpTo(50.0);
        await tester.pump();
        expect(
          tester.renderObject<RenderBox>(find.byType(Container)).size.height,
          equals(600.0),
        );

        controller.jumpTo(-100.0);
        await tester.pump();
        expect(
          tester.renderObject<RenderBox>(find.byType(Container)).size.height,
          equals(600.0),
        );

        controller.jumpTo(0.0);
        await tester.pump();
        expect(
          tester.renderObject<RenderBox>(find.byType(Container)).size.height,
          equals(600.0),
        );
      });

      testWidgets('one sibling', (WidgetTester tester) async {
        final ScrollController controller = ScrollController();
        await tester.pumpWidget(
          Directionality(
            textDirection: TextDirection.ltr,
            child: CustomScrollView(
              controller: controller,
              slivers: <Widget>[
                const SliverToBoxAdapter(child: SizedBox(height: 100.0)),
                SliverFillRemaining(child: Container()),
              ],
            ),
          ),
        );
        expect(
          tester.renderObject<RenderBox>(find.byType(Container)).size.height,
          equals(500.0),
        );

        controller.jumpTo(50.0);
        await tester.pump();
        expect(
          tester.renderObject<RenderBox>(find.byType(Container)).size.height,
          equals(550.0),
        );

        controller.jumpTo(-100.0);
        await tester.pump();
        expect(
          tester.renderObject<RenderBox>(find.byType(Container)).size.height,
          equals(400.0),
        );

        controller.jumpTo(0.0);
        await tester.pump();
        expect(
          tester.renderObject<RenderBox>(find.byType(Container)).size.height,
          equals(500.0),
        );
      });

      testWidgets('scrolls beyond viewportMainAxisExtent', (WidgetTester tester) async {
        final ScrollController controller = ScrollController();
        final List<Widget> slivers = <Widget>[
          sliverBox,
          SliverFillRemaining(
            child: Container(color: Colors.white),
          ),
        ];
        await tester.pumpWidget(boilerplate(slivers, controller: controller));
        expect(controller.offset, 0.0);
        expect(find.byType(Container), findsNWidgets(2));
        controller.jumpTo(150.0);
        await tester.pumpAndSettle();
        expect(controller.offset, 150.0);
        expect(find.byType(Container), findsOneWidget);
      });
    });

    group('hasScrollBody: false', () {
      testWidgets('does not extend past viewportMainAxisExtent', (WidgetTester tester) async {
        final ScrollController controller = ScrollController();
        final List<Widget> slivers = <Widget>[
          sliverBox,
          SliverFillRemaining(
            hasScrollBody: false,
            child: Container(color: Colors.white),
          ),
        ];

        await tester.pumpWidget(boilerplate(slivers, controller: controller));
        expect(controller.offset, 0.0);
        expect(find.byType(Container), findsNWidgets(2));
        controller.jumpTo(150.0);
        await tester.pumpAndSettle();
        expect(controller.offset, 0.0);
        expect(find.byType(Container), findsNWidgets(2));
      });

      testWidgets('child without size is sized by extent', (WidgetTester tester) async {
        final List<Widget> slivers = <Widget>[
          sliverBox,
          SliverFillRemaining(
            hasScrollBody: false,
            child: Container(color: Colors.blue),
          ),
        ];

        await tester.pumpWidget(boilerplate(slivers));
        RenderBox box = tester.renderObject<RenderBox>(find.byType(Container).last);
        expect(box.size.height, equals(450));

        await tester.pumpWidget(boilerplate(
          slivers,
          scrollDirection: Axis.horizontal,
        ));
        box = tester.renderObject<RenderBox>(find.byType(Container).last);
        expect(box.size.width, equals(650));
      });

      testWidgets('child with smaller size is sized by extent', (WidgetTester tester) async {
        final GlobalKey key = GlobalKey();
        final List<Widget> slivers = <Widget>[
          sliverBox,
          SliverFillRemaining(
            hasScrollBody: false,
            child: Container(
              key: key,
              color: Colors.blue,
              child: Align(
                alignment: Alignment.bottomCenter,
                child: ElevatedButton(
                  child: const Text('bottomCenter button'),
                  onPressed: () {},
                ),
              ),
            ),
          ),
        ];
        await tester.pumpWidget(boilerplate(slivers));
        expect(
          tester.renderObject<RenderBox>(find.byKey(key)).size.height,
          equals(450),
        );

        // Also check that the button alignment is true to expectations
        final Finder button = find.byType(ElevatedButton);
        expect(tester.getBottomLeft(button).dy, equals(600.0));
        expect(tester.getCenter(button).dx, equals(400.0));

        // Check Axis.horizontal
        await tester.pumpWidget(boilerplate(
          slivers,
          scrollDirection: Axis.horizontal,
        ));
        expect(
          tester.renderObject<RenderBox>(find.byKey(key)).size.width,
          equals(650),
        );
      });

      testWidgets('extent is overridden by child with larger size', (WidgetTester tester) async {
        final List<Widget> slivers = <Widget>[
          sliverBox,
          SliverFillRemaining(
            hasScrollBody: false,
            child: Container(
              color: Colors.blue,
              height: 600,
              width: 1000,
            ),
          ),
        ];
        await tester.pumpWidget(boilerplate(slivers));
        RenderBox box = tester.renderObject<RenderBox>(find.byType(Container).last);
        expect(box.size.height, equals(600));

        await tester.pumpWidget(boilerplate(
          slivers,
          scrollDirection: Axis.horizontal,
        ));
        box = tester.renderObject<RenderBox>(find.byType(Container).last);
        expect(box.size.width, equals(1000));
      });

      testWidgets('extent is overridden by child size if precedingScrollExtent > viewportMainAxisExtent', (WidgetTester tester) async {
        final GlobalKey key = GlobalKey();
        final List<Widget> slivers = <Widget>[
          SliverFixedExtentList(
            itemExtent: 150,
            delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) => Container(color: Colors.amber),
              childCount: 5,
            ),
          ),
          SliverFillRemaining(
            hasScrollBody: false,
            child: Container(
              key: key,
              color: Colors.blue[300],
              child: Align(
                child: Padding(
                  padding: const EdgeInsets.all(50.0),
                  child: ElevatedButton(
                    child: const Text('center button'),
                    onPressed: () {},
                  ),
                ),
              ),
            ),
          ),
        ];
        await tester.pumpWidget(boilerplate(slivers));
        await tester.drag(find.byType(Scrollable), const Offset(0.0, -750.0));
        await tester.pump();
        expect(
          tester.renderObject<RenderBox>(find.byKey(key)).size.height,
          equals(148.0),
        );

        // Also check that the button alignment is true to expectations
        final Finder button = find.byType(ElevatedButton);
        expect(tester.getBottomLeft(button).dy, equals(550.0));
        expect(tester.getCenter(button).dx, equals(400.0));
      });

      testWidgets('alignment with a flexible works', (WidgetTester tester) async {
        final GlobalKey key = GlobalKey();
        final List<Widget> slivers = <Widget>[
          sliverBox,
          SliverFillRemaining(
            hasScrollBody: false,
            child: Column(
              key: key,
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                const Flexible(
                  child: Center(child: FlutterLogo(size: 100)),
                ),
                ElevatedButton(
                  child: const Text('Bottom'),
                  onPressed: () {},
                ),
              ],
            ),
          ),
        ];

        await tester.pumpWidget(boilerplate(slivers));
        expect(
          tester.renderObject<RenderBox>(find.byKey(key)).size.height,
          equals(450),
        );

        // Check that the logo alignment is true to expectations
        final Finder logo = find.byType(FlutterLogo);
        expect(
          tester.renderObject<RenderBox>(logo).size,
          const Size(100.0, 100.0),
        );
        final VisualDensity density = VisualDensity.adaptivePlatformDensity;
        expect(tester.getCenter(logo), Offset(400.0, 351.0 - density.vertical * 2.0));

        // Also check that the button alignment is true to expectations
        // Buttons do not decrease their horizontal padding per the VisualDensity.
        final Finder button = find.byType(ElevatedButton);
        expect(
          tester.renderObject<RenderBox>(button).size,
          Size(116.0 + math.max(0, density.horizontal) * 8.0, 48.0 + density.vertical * 4.0),
        );
        expect(tester.getBottomLeft(button).dy, equals(600.0));
        expect(tester.getCenter(button).dx, equals(400.0));

        // Overscroll and see that alignment and size is maintained
        await tester.drag(find.byType(Scrollable), const Offset(0.0, -50.0));
        await tester.pump();
        expect(
          tester.renderObject<RenderBox>(find.byKey(key)).size.height,
          equals(450),
        );
        expect(
          tester.renderObject<RenderBox>(logo).size,
          const Size(100.0, 100.0),
        );
        expect(tester.getCenter(logo).dy, lessThan(351.0));
        expect(
          tester.renderObject<RenderBox>(button).size,
          // Buttons do not decrease their horizontal padding per the VisualDensity.
          Size(116.0 + math.max(0, density.horizontal) * 8.0, 48.0 + density.vertical * 4.0),
        );
        expect(tester.getBottomLeft(button).dy, lessThan(600.0));
        expect(tester.getCenter(button).dx, equals(400.0));
      }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));

      group('fillOverscroll: true, relevant platforms', () {
        testWidgets('child without size is sized by extent and overscroll', (WidgetTester tester) async {
          final List<Widget> slivers = <Widget>[
            sliverBox,
            SliverFillRemaining(
              hasScrollBody: false,
              fillOverscroll: true,
              child: Container(color: Colors.blue),
            ),
          ];

          // Check size
          await tester.pumpWidget(boilerplate(slivers));
          final RenderBox box1 = tester.renderObject<RenderBox>(find.byType(Container).last);
          expect(box1.size.height, equals(450));

          // Overscroll and check size
          await tester.drag(find.byType(Scrollable), const Offset(0.0, -50.0));
          await tester.pump();
          final RenderBox box2 = tester.renderObject<RenderBox>(find.byType(Container).last);
          expect(box2.size.height, greaterThan(450));

          // Ensure overscroll retracts to original size after releasing gesture
          await tester.pumpAndSettle();
          final RenderBox box3 = tester.renderObject<RenderBox>(find.byType(Container).last);
          expect(box3.size.height, equals(450));
    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));

        testWidgets('child with smaller size is overridden and sized by extent and overscroll', (WidgetTester tester) async {
          final GlobalKey key = GlobalKey();
          final List<Widget> slivers = <Widget>[
            sliverBox,
            SliverFillRemaining(
              hasScrollBody: false,
              fillOverscroll: true,
              child: Container(
                key: key,
                color: Colors.blue,
                child: Align(
                  alignment: Alignment.bottomCenter,
                  child: ElevatedButton(
                    child: const Text('bottomCenter button'),
                    onPressed: () {},
                  ),
                ),
              ),
            ),
          ];
          await tester.pumpWidget(boilerplate(slivers));
          expect(
            tester.renderObject<RenderBox>(find.byKey(key)).size.height,
            equals(450),
          );

          await tester.drag(find.byType(Scrollable), const Offset(0.0, -50.0));
          await tester.pump();
          expect(
            tester.renderObject<RenderBox>(find.byKey(key)).size.height,
            greaterThan(450),
          );

          // Also check that the button alignment is true to expectations, even with
          // child stretching to fill overscroll
          final Finder button = find.byType(ElevatedButton);
          expect(tester.getBottomLeft(button).dy, equals(600.0));
          expect(tester.getCenter(button).dx, equals(400.0));

          // Ensure overscroll retracts to original size after releasing gesture
          await tester.pumpAndSettle();
          expect(
            tester.renderObject<RenderBox>(find.byKey(key)).size.height,
            equals(450),
          );
        }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));

        testWidgets('extent is overridden by child size and overscroll if precedingScrollExtent > viewportMainAxisExtent', (WidgetTester tester) async {
          final GlobalKey key = GlobalKey();
          final ScrollController controller = ScrollController();
          final List<Widget> slivers = <Widget>[
            SliverFixedExtentList(
              itemExtent: 150,
              delegate: SliverChildBuilderDelegate(
                  (BuildContext context, int index) =>
                  Container(color: Colors.amber),
                childCount: 5,
              ),
            ),
            SliverFillRemaining(
              hasScrollBody: false,
              fillOverscroll: true,
              child: Container(
                key: key,
                color: Colors.blue[300],
                child: Align(
                  child: Padding(
                    padding: const EdgeInsets.all(50.0),
                    child: ElevatedButton(
                      child: const Text('center button'),
                      onPressed: () {},
                    ),
                  ),
                ),
              ),
            ),
          ];
          await tester.pumpWidget(boilerplate(slivers, controller: controller));

          // Scroll to the end
          controller.jumpTo(controller.position.maxScrollExtent);
          await tester.pump();
          expect(
            tester.renderObject<RenderBox>(find.byKey(key)).size.height,
            equals(148.0 + VisualDensity.adaptivePlatformDensity.vertical * 4.0),
          );
          // Check that the button alignment is true to expectations
          final Finder button = find.byType(ElevatedButton);
          expect(tester.getBottomLeft(button).dy, equals(550.0));
          expect(tester.getCenter(button).dx, equals(400.0));

          // Drag for overscroll
          await tester.drag(find.byType(Scrollable), const Offset(0.0, -50.0));
          await tester.pump();
          expect(
            tester.renderObject<RenderBox>(find.byKey(key)).size.height,
            greaterThan(148.0),
          );

          // Check that the button alignment is still centered in stretched child
          expect(tester.getBottomLeft(button).dy, lessThan(550.0));
          expect(tester.getCenter(button).dx, equals(400.0));

          // Ensure overscroll retracts to original size after releasing gesture
          await tester.pumpAndSettle();
          expect(
            tester.renderObject<RenderBox>(find.byKey(key)).size.height,
            equals(148.0 + VisualDensity.adaptivePlatformDensity.vertical * 4.0),
          );
        }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));

        testWidgets('fillOverscroll works when child has no size and precedingScrollExtent > viewportMainAxisExtent', (WidgetTester tester) async {
          final GlobalKey key = GlobalKey();
          final ScrollController controller = ScrollController();
          final List<Widget> slivers = <Widget>[
            SliverFixedExtentList(
              itemExtent: 150,
              delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
                  return Semantics(label: index.toString(), child: Container(color: Colors.amber));
                },
                childCount: 5,
              ),
            ),
            SliverFillRemaining(
              hasScrollBody: false,
              fillOverscroll: true,
              child: Container(
                key: key,
                color: Colors.blue,
              ),
            ),
          ];

          await tester.pumpWidget(boilerplate(slivers, controller: controller));

          expect(find.byKey(key), findsNothing);
          expect(
            find.bySemanticsLabel('4'),
            findsNothing,
          );

          // Scroll to bottom
          controller.jumpTo(controller.position.maxScrollExtent);
          await tester.pump();

          // Check item at the end of the list
          expect(find.byKey(key), findsNothing);
          expect(
            find.bySemanticsLabel('4'),
            findsOneWidget,
          );

          // Overscroll
          await tester.drag(find.byType(Scrollable), const Offset(0.0, -50.0));
          await tester.pump();

          // Check for new item at the end of the now overscrolled list
          expect(find.byKey(key), findsOneWidget);
          expect(
            find.bySemanticsLabel('4'),
            findsOneWidget,
          );

          // Ensure overscroll retracts to original size after releasing gesture
          await tester.pumpAndSettle();
          expect(find.byKey(key), findsNothing);
          expect(
            find.bySemanticsLabel('4'),
            findsOneWidget,
          );
        }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));

        testWidgets('alignment with a flexible works with fillOverscroll', (WidgetTester tester) async {
          final GlobalKey key = GlobalKey();
          final List<Widget> slivers = <Widget>[
            sliverBox,
            SliverFillRemaining(
              hasScrollBody: false,
              fillOverscroll: true,
              child: Column(
                key: key,
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[
                  const Flexible(
                    child: Center(child: FlutterLogo(size: 100)),
                  ),
                  ElevatedButton(
                    child: const Text('Bottom'),
                    onPressed: () {},
                  ),
                ],
              ),
            ),
          ];

          await tester.pumpWidget(boilerplate(slivers));
          expect(
            tester.renderObject<RenderBox>(find.byKey(key)).size.height,
            equals(450),
          );

          // Check that the logo alignment is true to expectations.
          final Finder logo = find.byType(FlutterLogo);
          expect(
            tester.renderObject<RenderBox>(logo).size,
            const Size(100.0, 100.0),
          );
          final VisualDensity density = VisualDensity.adaptivePlatformDensity;
          expect(tester.getCenter(logo), Offset(400.0, 351.0 - density.vertical * 2.0));

          // Also check that the button alignment is true to expectations.
          // Buttons do not decrease their horizontal padding per the VisualDensity.
          final Finder button = find.byType(ElevatedButton);
          expect(
            tester.renderObject<RenderBox>(button).size,
            Size(116.0 + math.max(0, density.horizontal) * 8.0, 48.0 + density.vertical * 4.0),
          );
          expect(tester.getBottomLeft(button).dy, equals(600.0));
          expect(tester.getCenter(button).dx, equals(400.0));

          // Overscroll and see that logo alignment shifts to maintain center as
          // container stretches with overscroll, button remains aligned at the
          // bottom.
          await tester.drag(find.byType(Scrollable), const Offset(0.0, -50.0));
          await tester.pump();
          expect(
            tester.renderObject<RenderBox>(find.byKey(key)).size.height,
            greaterThan(450),
          );
          expect(
            tester.renderObject<RenderBox>(logo).size,
            const Size(100.0, 100.0),
          );
          expect(tester.getCenter(logo).dy, lessThan(351.0));
          expect(
            tester.renderObject<RenderBox>(button).size,
            // Buttons do not decrease their horizontal padding per the VisualDensity.
            Size(116.0 + math.max(0, density.horizontal) * 8.0, 48.0 + density.vertical * 4.0),
          );
          expect(tester.getBottomLeft(button).dy, equals(600.0));
          expect(tester.getCenter(button).dx, equals(400.0));

          // Ensure overscroll retracts to original position when gesture is
          // released.
          await tester.pumpAndSettle();
          expect(
            tester.renderObject<RenderBox>(find.byKey(key)).size.height,
            equals(450),
          );
          expect(
            tester.renderObject<RenderBox>(logo).size,
            const Size(100.0, 100.0),
          );
          expect(tester.getCenter(logo), Offset(400.0, 351.0 - density.vertical * 2.0));
          expect(
            tester.renderObject<RenderBox>(button).size,
            // Buttons do not decrease their horizontal padding per the VisualDensity.
            Size(116.0 + math.max(0, density.horizontal) * 8.0, 48.0 + density.vertical * 4.0),
          );
          expect(tester.getBottomLeft(button).dy, equals(600.0));
          expect(tester.getCenter(button).dx, equals(400.0));
        }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
      });

      group('fillOverscroll: true, is ignored on irrelevant platforms', () {
        // Android/Other scroll physics when hasScrollBody: false, ignores fillOverscroll: true
        testWidgets('child without size is sized by extent', (WidgetTester tester) async {
          final List<Widget> slivers = <Widget>[
            sliverBox,
            SliverFillRemaining(
              hasScrollBody: false,
              fillOverscroll: true,
              child: Container(color: Colors.blue),
            ),
          ];
          await tester.pumpWidget(boilerplate(slivers));
          final RenderBox box1 = tester.renderObject<RenderBox>(find.byType(Container).last);
          expect(box1.size.height, equals(450));

          await tester.drag(find.byType(Scrollable), const Offset(0.0, -50.0));
          await tester.pump();
          final RenderBox box2 = tester.renderObject<RenderBox>(find.byType(Container).last);
          expect(box2.size.height, equals(450));
        });

        testWidgets('child with size is overridden and sized by extent', (WidgetTester tester) async {
          final GlobalKey key = GlobalKey();
          final List<Widget> slivers = <Widget>[
            sliverBox,
            SliverFillRemaining(
              hasScrollBody: false,
              fillOverscroll: true,
              child: Container(
                key: key,
                color: Colors.blue,
                child: Align(
                  alignment: Alignment.bottomCenter,
                  child: ElevatedButton(
                    child: const Text('bottomCenter button'),
                    onPressed: () {},
                  ),
                ),
              ),
            ),
          ];
          await tester.pumpWidget(boilerplate(slivers));
          expect(
            tester.renderObject<RenderBox>(find.byKey(key)).size.height,
            equals(450),
          );

          await tester.drag(find.byType(Scrollable), const Offset(0.0, -50.0));
          await tester.pump();
          expect(
            tester.renderObject<RenderBox>(find.byKey(key)).size.height,
            equals(450),
          );

          // Also check that the button alignment is true to expectations
          final Finder button = find.byType(ElevatedButton);
          expect(tester.getBottomLeft(button).dy, equals(600.0));
          expect(tester.getCenter(button).dx, equals(400.0));
        });

        testWidgets('extent is overridden by child size if precedingScrollExtent > viewportMainAxisExtent', (WidgetTester tester) async {
          final GlobalKey key = GlobalKey();
          final ScrollController controller = ScrollController();
          final List<Widget> slivers = <Widget>[
            SliverFixedExtentList(
              itemExtent: 150,
              delegate: SliverChildBuilderDelegate(
                  (BuildContext context, int index) =>
                  Container(color: Colors.amber),
                childCount: 5,
              ),
            ),
            SliverFillRemaining(
              hasScrollBody: false,
              fillOverscroll: true,
              child: Container(
                key: key,
                color: Colors.blue[300],
                child: Align(
                  child: Padding(
                    padding: const EdgeInsets.all(50.0),
                    child: ElevatedButton(
                      child: const Text('center button'),
                      onPressed: () {},
                    ),
                  ),
                ),
              ),
            ),
          ];
          await tester.pumpWidget(boilerplate(slivers, controller: controller));

          // Scroll to the end
          controller.jumpTo(controller.position.maxScrollExtent);
          await tester.pump();
          expect(
            tester.renderObject<RenderBox>(find.byKey(key)).size.height,
            equals(148.0),
          );

          // Check that the button alignment is true to expectations
          final Finder button = find.byType(ElevatedButton);
          expect(tester.getBottomLeft(button).dy, equals(550.0));
          expect(tester.getCenter(button).dx, equals(400.0));

          await tester.drag(find.byType(Scrollable), const Offset(0.0, -50.0));
          await tester.pump();
          expect(
            tester.renderObject<RenderBox>(find.byKey(key)).size.height,
            equals(148.0),
          );

          // Check that the button alignment is still centered
          expect(tester.getBottomLeft(button).dy, equals(550.0));
          expect(tester.getCenter(button).dx, equals(400.0));
        });

        testWidgets('child has no size and precedingScrollExtent > viewportMainAxisExtent', (WidgetTester tester) async {
          final GlobalKey key = GlobalKey();
          final ScrollController controller = ScrollController();
          final List<Widget> slivers = <Widget>[
            SliverFixedExtentList(
              itemExtent: 150,
              delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
                  return Semantics(label: index.toString(), child: Container(color: Colors.amber));
                },
                childCount: 5,
              ),
            ),
            SliverFillRemaining(
              hasScrollBody: false,
              fillOverscroll: true,
              child: Container(
                key: key,
                color: Colors.blue,
              ),
            ),
          ];

          await tester.pumpWidget(boilerplate(slivers, controller: controller));

          expect(find.byKey(key), findsNothing);
          expect(
            find.bySemanticsLabel('4'),
            findsNothing,
          );

          // Scroll to bottom
          controller.jumpTo(controller.position.maxScrollExtent);
          await tester.pump();

          // End of list
          expect(find.byKey(key), findsNothing);
          expect(
            find.bySemanticsLabel('4'),
            findsOneWidget,
          );

          // Overscroll
          await tester.drag(find.byType(Scrollable), const Offset(0.0, -50.0));
          await tester.pump();

          expect(find.byKey(key), findsNothing);
          expect(
            find.bySemanticsLabel('4'),
            findsOneWidget,
          );
        });
      });
    });
  });
}
