// 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.

@TestOn('!chrome')
library;

import 'dart:async';

import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  late FakeBuilder mockHelper;

  setUp(() {
    mockHelper = FakeBuilder();
  });

  var testListLength = 10;
  SliverList buildAListOfStuff() {
    return SliverList.builder(
      itemCount: testListLength,
      itemBuilder: (BuildContext context, int index) {
        return SizedBox(height: 200.0, child: Center(child: Text(index.toString())));
      },
    );
  }

  void uiTestGroup() {
    testWidgets(
      "doesn't invoke anything without user interaction",
      (WidgetTester tester) async {
        await tester.pumpWidget(
          CupertinoApp(
            home: CustomScrollView(
              slivers: <Widget>[
                CupertinoSliverRefreshControl(builder: mockHelper.builder),
                buildAListOfStuff(),
              ],
            ),
          ),
        );

        expect(mockHelper.invocations, isEmpty);

        expect(tester.getTopLeft(find.widgetWithText(SizedBox, '0')), Offset.zero);
      },
      variant: const TargetPlatformVariant(<TargetPlatform>{
        TargetPlatform.iOS,
        TargetPlatform.macOS,
      }),
    );

    testWidgets(
      'calls the indicator builder when starting to overscroll',
      (WidgetTester tester) async {
        await tester.pumpWidget(
          CupertinoApp(
            home: CustomScrollView(
              slivers: <Widget>[
                CupertinoSliverRefreshControl(builder: mockHelper.builder),
                buildAListOfStuff(),
              ],
            ),
          ),
        );

        // Drag down but not enough to trigger the refresh.
        await tester.drag(find.text('0'), const Offset(0.0, 50.0), touchSlopY: 0);
        await tester.pump();

        // The function is referenced once while passing into CupertinoSliverRefreshControl
        // and is called.
        expect(
          mockHelper.invocations.first,
          matchesBuilder(
            refreshState: RefreshIndicatorMode.drag,
            pulledExtent: 50,
            refreshTriggerPullDistance: 100, // default value.
            refreshIndicatorExtent: 60, // default value.
          ),
        );
        expect(mockHelper.invocations, hasLength(1));

        expect(tester.getTopLeft(find.widgetWithText(SizedBox, '0')), const Offset(0.0, 50.0));
      },
      variant: const TargetPlatformVariant(<TargetPlatform>{
        TargetPlatform.iOS,
        TargetPlatform.macOS,
      }),
    );

    testWidgets(
      "don't call the builder if overscroll doesn't move slivers like on Android",
      (WidgetTester tester) async {
        await tester.pumpWidget(
          Directionality(
            textDirection: TextDirection.ltr,
            child: MediaQuery(
              data: const MediaQueryData(),
              child: CustomScrollView(
                slivers: <Widget>[
                  CupertinoSliverRefreshControl(builder: mockHelper.builder),
                  buildAListOfStuff(),
                ],
              ),
            ),
          ),
        );

        // Drag down but not enough to trigger the refresh.
        await tester.drag(find.text('0'), const Offset(0.0, 50.0));
        await tester.pump();

        expect(mockHelper.invocations, isEmpty);

        expect(tester.getTopLeft(find.widgetWithText(SizedBox, '0')), Offset.zero);
      },
      variant: TargetPlatformVariant.only(TargetPlatform.android),
    );

    testWidgets(
      'let the builder update as canceled drag scrolls away',
      (WidgetTester tester) async {
        await tester.pumpWidget(
          CupertinoApp(
            home: CustomScrollView(
              slivers: <Widget>[
                CupertinoSliverRefreshControl(builder: mockHelper.builder),
                buildAListOfStuff(),
              ],
            ),
          ),
        );

        // Drag down but not enough to trigger the refresh.
        await tester.drag(find.text('0'), const Offset(0.0, 50.0), touchSlopY: 0);
        await tester.pump();
        await tester.pump(const Duration(milliseconds: 20));
        await tester.pump(const Duration(milliseconds: 20));
        await tester.pump(const Duration(seconds: 3));

        expect(
          mockHelper.invocations,
          containsAllInOrder(<void>[
            matchesBuilder(
              refreshState: RefreshIndicatorMode.drag,
              pulledExtent: 50,
              refreshTriggerPullDistance: 100, // default value.
              refreshIndicatorExtent: 60, // default value.
            ),
            if (debugDefaultTargetPlatformOverride == TargetPlatform.macOS)
              matchesBuilder(
                refreshState: RefreshIndicatorMode.drag,
                pulledExtent: moreOrLessEquals(48.07979523362715),
                refreshTriggerPullDistance: 100, // default value.
                refreshIndicatorExtent: 60, // default value.
              )
            else
              matchesBuilder(
                refreshState: RefreshIndicatorMode.drag,
                pulledExtent: moreOrLessEquals(48.36801747187993),
                refreshTriggerPullDistance: 100, // default value.
                refreshIndicatorExtent: 60, // default value.
              ),
            if (debugDefaultTargetPlatformOverride == TargetPlatform.macOS)
              matchesBuilder(
                refreshState: RefreshIndicatorMode.drag,
                pulledExtent: moreOrLessEquals(43.98499220391114),
                refreshTriggerPullDistance: 100, // default value.
                refreshIndicatorExtent: 60, // default value.
              )
            else
              matchesBuilder(
                refreshState: RefreshIndicatorMode.drag,
                pulledExtent: moreOrLessEquals(44.63031931875867),
                refreshTriggerPullDistance: 100, // default value.
                refreshIndicatorExtent: 60, // default value.
              ),
          ]),
        );
        // The builder isn't called again when the sliver completely goes away.
        expect(mockHelper.invocations, hasLength(3));

        expect(tester.getTopLeft(find.widgetWithText(SizedBox, '0')), Offset.zero);
      },
      variant: const TargetPlatformVariant(<TargetPlatform>{
        TargetPlatform.iOS,
        TargetPlatform.macOS,
      }),
    );

    testWidgets(
      'drag past threshold triggers refresh task',
      (WidgetTester tester) async {
        final platformCallLog = <MethodCall>[];

        tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (
          MethodCall methodCall,
        ) async {
          platformCallLog.add(methodCall);
          return null;
        });

        await tester.pumpWidget(
          CupertinoApp(
            home: CustomScrollView(
              slivers: <Widget>[
                CupertinoSliverRefreshControl(
                  builder: mockHelper.builder,
                  onRefresh: mockHelper.refreshTask,
                ),
                buildAListOfStuff(),
              ],
            ),
          ),
        );

        final TestGesture gesture = await tester.startGesture(Offset.zero);
        await gesture.moveBy(const Offset(0.0, 99.0));
        await tester.pump();
        if (debugDefaultTargetPlatformOverride == TargetPlatform.macOS) {
          await gesture.moveBy(const Offset(0.0, -3.0));
        } else {
          await gesture.moveBy(const Offset(0.0, -30.0));
        }
        await tester.pump();
        if (debugDefaultTargetPlatformOverride == TargetPlatform.macOS) {
          await gesture.moveBy(const Offset(0.0, 90.0));
        } else {
          await gesture.moveBy(const Offset(0.0, 50.0));
        }
        await tester.pump();

        expect(
          mockHelper.invocations,
          containsAllInOrder(<void>[
            matchesBuilder(
              refreshState: RefreshIndicatorMode.drag,
              pulledExtent: 99,
              refreshTriggerPullDistance: 100, // default value.
              refreshIndicatorExtent: 60, // default value.
            ),
            if (debugDefaultTargetPlatformOverride == TargetPlatform.macOS)
              matchesBuilder(
                refreshState: RefreshIndicatorMode.drag,
                pulledExtent: moreOrLessEquals(96),
                refreshTriggerPullDistance: 100, // default value.
                refreshIndicatorExtent: 60, // default value.
              )
            else
              matchesBuilder(
                refreshState: RefreshIndicatorMode.drag,
                pulledExtent: moreOrLessEquals(86.78169),
                refreshTriggerPullDistance: 100, // default value.
                refreshIndicatorExtent: 60, // default value.
              ),
            if (debugDefaultTargetPlatformOverride == TargetPlatform.macOS)
              matchesBuilder(
                refreshState: RefreshIndicatorMode.armed,
                pulledExtent: moreOrLessEquals(112.51104),
                refreshTriggerPullDistance: 100, // default value.
                refreshIndicatorExtent: 60, // default value.
              )
            else
              matchesBuilder(
                refreshState: RefreshIndicatorMode.armed,
                pulledExtent: moreOrLessEquals(105.80452021305739),
                refreshTriggerPullDistance: 100, // default value.
                refreshIndicatorExtent: 60, // default value.
              ),
          ]),
        );
        // The refresh callback is triggered after the frame.
        expect(mockHelper.invocations.last, const RefreshTaskInvocation());
        expect(mockHelper.invocations, hasLength(4));

        expect(
          platformCallLog.last,
          isMethodCall('HapticFeedback.vibrate', arguments: 'HapticFeedbackType.mediumImpact'),
        );
      },
      variant: const TargetPlatformVariant(<TargetPlatform>{
        TargetPlatform.iOS,
        TargetPlatform.macOS,
      }),
    );

    testWidgets(
      'refreshing task keeps the sliver expanded forever until done',
      (WidgetTester tester) async {
        await tester.pumpWidget(
          CupertinoApp(
            home: CustomScrollView(
              slivers: <Widget>[
                CupertinoSliverRefreshControl(
                  builder: mockHelper.builder,
                  onRefresh: mockHelper.refreshTask,
                ),
                buildAListOfStuff(),
              ],
            ),
          ),
        );

        await tester.drag(find.text('0'), const Offset(0.0, 150.0), touchSlopY: 0);
        await tester.pump();
        // Let it start snapping back.
        await tester.pump(const Duration(milliseconds: 50));

        expect(
          mockHelper.invocations,
          containsAllInOrder(<Matcher>[
            matchesBuilder(
              refreshState: RefreshIndicatorMode.armed,
              pulledExtent: 150,
              refreshTriggerPullDistance: 100, // Default value.
              refreshIndicatorExtent: 60, // Default value.
            ),
            equals(const RefreshTaskInvocation()),
            if (debugDefaultTargetPlatformOverride == TargetPlatform.macOS)
              matchesBuilder(
                refreshState: RefreshIndicatorMode.armed,
                pulledExtent: moreOrLessEquals(124.87933920045268),
                refreshTriggerPullDistance: 100, // Default value.
                refreshIndicatorExtent: 60, // Default value.
              )
            else
              matchesBuilder(
                refreshState: RefreshIndicatorMode.armed,
                pulledExtent: moreOrLessEquals(127.10396988577114),
                refreshTriggerPullDistance: 100, // Default value.
                refreshIndicatorExtent: 60, // Default value.
              ),
          ]),
        );

        // Reaches refresh state and sliver's at 60.0 in height after a while.
        await tester.pump(const Duration(seconds: 1));

        expect(
          mockHelper.invocations,
          contains(
            matchesBuilder(
              refreshState: RefreshIndicatorMode.refresh,
              pulledExtent: 60,
              refreshIndicatorExtent: 60, // Default value.
              refreshTriggerPullDistance: 100, // Default value.
            ),
          ),
        );

        // Stays in that state forever until future completes.
        await tester.pump(const Duration(seconds: 1000));
        expect(tester.getTopLeft(find.widgetWithText(SizedBox, '0')), const Offset(0.0, 60.0));

        mockHelper.refreshCompleter.complete(null);
        await tester.pump();

        expect(
          mockHelper.invocations,
          contains(
            matchesBuilder(
              refreshState: RefreshIndicatorMode.done,
              pulledExtent: 60,
              refreshIndicatorExtent: 60, // Default value.
              refreshTriggerPullDistance: 100, // Default value.
            ),
          ),
        );
        expect(mockHelper.invocations, hasLength(5));
      },
      variant: const TargetPlatformVariant(<TargetPlatform>{
        TargetPlatform.iOS,
        TargetPlatform.macOS,
      }),
    );

    testWidgets(
      'refreshing task keeps the sliver expanded forever until completes with error',
      (WidgetTester tester) async {
        final error = FlutterError('Oops');
        double errorCount = 0;
        final TargetPlatform? platform =
            debugDefaultTargetPlatformOverride; // Will not be correct within the zone.

        runZonedGuarded(
          () async {
            mockHelper.refreshCompleter = Completer<void>.sync();
            await tester.pumpWidget(
              CupertinoApp(
                home: CustomScrollView(
                  slivers: <Widget>[
                    CupertinoSliverRefreshControl(
                      builder: mockHelper.builder,
                      onRefresh: mockHelper.refreshTask,
                    ),
                    buildAListOfStuff(),
                  ],
                ),
              ),
            );

            await tester.drag(find.text('0'), const Offset(0.0, 150.0), touchSlopY: 0);
            await tester.pump();
            // Let it start snapping back.
            await tester.pump(const Duration(milliseconds: 50));

            expect(
              mockHelper.invocations,
              containsAllInOrder(<Matcher>[
                matchesBuilder(
                  refreshState: RefreshIndicatorMode.armed,
                  pulledExtent: 150,
                  refreshIndicatorExtent: 60, // Default value.
                  refreshTriggerPullDistance: 100, // Default value.
                ),
                equals(const RefreshTaskInvocation()),
                if (platform == TargetPlatform.macOS)
                  matchesBuilder(
                    refreshState: RefreshIndicatorMode.armed,
                    pulledExtent: moreOrLessEquals(124.87933920045268),
                    refreshTriggerPullDistance: 100, // Default value.
                    refreshIndicatorExtent: 60, // Default value.
                  )
                else
                  matchesBuilder(
                    refreshState: RefreshIndicatorMode.armed,
                    pulledExtent: moreOrLessEquals(127.10396988577114),
                    refreshIndicatorExtent: 60, // Default value.
                    refreshTriggerPullDistance: 100, // Default value.
                  ),
              ]),
            );

            // Reaches refresh state and sliver's at 60.0 in height after a while.
            await tester.pump(const Duration(seconds: 1));
            expect(
              mockHelper.invocations,
              contains(
                matchesBuilder(
                  refreshState: RefreshIndicatorMode.refresh,
                  pulledExtent: 60,
                  refreshIndicatorExtent: 60, // Default value.
                  refreshTriggerPullDistance: 100, // Default value.
                ),
              ),
            );

            // Stays in that state forever until future completes.
            await tester.pump(const Duration(seconds: 1000));
            expect(tester.getTopLeft(find.widgetWithText(SizedBox, '0')), const Offset(0.0, 60.0));

            mockHelper.refreshCompleter.completeError(error);
            await tester.pump();

            expect(
              mockHelper.invocations,
              contains(
                matchesBuilder(
                  refreshState: RefreshIndicatorMode.done,
                  pulledExtent: 60,
                  refreshIndicatorExtent: 60, // Default value.
                  refreshTriggerPullDistance: 100, // Default value.
                ),
              ),
            );
            expect(mockHelper.invocations, hasLength(5));
          },
          (Object e, StackTrace stack) {
            expect(e, error);
            expect(errorCount, 0);
            errorCount++;
          },
        );
      },
      variant: const TargetPlatformVariant(<TargetPlatform>{
        TargetPlatform.iOS,
        TargetPlatform.macOS,
      }),
    );

    testWidgets(
      'expanded refreshing sliver scrolls normally',
      (WidgetTester tester) async {
        mockHelper.refreshIndicator = const Center(child: Text('-1'));

        await tester.pumpWidget(
          CupertinoApp(
            home: CustomScrollView(
              slivers: <Widget>[
                CupertinoSliverRefreshControl(
                  builder: mockHelper.builder,
                  onRefresh: mockHelper.refreshTask,
                ),
                buildAListOfStuff(),
              ],
            ),
          ),
        );

        await tester.drag(find.text('0'), const Offset(0.0, 150.0), touchSlopY: 0);
        await tester.pump();

        expect(
          mockHelper.invocations,
          contains(
            matchesBuilder(
              refreshState: RefreshIndicatorMode.armed,
              pulledExtent: 150,
              refreshIndicatorExtent: 60, // Default value.
              refreshTriggerPullDistance: 100, // Default value.
            ),
          ),
        );

        // Given a box constraint of 150, the Center will occupy all that height.
        expect(
          tester.getRect(find.widgetWithText(Center, '-1')),
          const Rect.fromLTRB(0.0, 0.0, 800.0, 150.0),
        );

        await tester.drag(
          find.text('0'),
          const Offset(0.0, -300.0),
          touchSlopY: 0,
          warnIfMissed: false,
        ); // hits the list
        await tester.pump();

        // Refresh indicator still being told to layout the same way.
        expect(
          mockHelper.invocations,
          contains(
            matchesBuilder(
              refreshState: RefreshIndicatorMode.refresh,
              pulledExtent: 60,
              refreshIndicatorExtent: 60, // Default value.
              refreshTriggerPullDistance: 100, // Default value.
            ),
          ),
        );

        // Now the sliver is scrolled off screen.
        if (debugDefaultTargetPlatformOverride == TargetPlatform.macOS) {
          expect(
            tester.getTopLeft(find.widgetWithText(Center, '-1', skipOffstage: false)).dy,
            moreOrLessEquals(-210.0),
          );
          expect(
            tester.getBottomLeft(find.widgetWithText(Center, '-1', skipOffstage: false)).dy,
            moreOrLessEquals(-150.0),
          );
          expect(tester.getTopLeft(find.widgetWithText(Center, '0')).dy, moreOrLessEquals(-150.0));
        } else {
          expect(
            tester.getTopLeft(find.widgetWithText(Center, '-1', skipOffstage: false)).dy,
            moreOrLessEquals(-175.38461538461536),
          );
          expect(
            tester.getBottomLeft(find.widgetWithText(Center, '-1', skipOffstage: false)).dy,
            moreOrLessEquals(-115.38461538461536),
          );
          expect(
            tester.getTopLeft(find.widgetWithText(Center, '0')).dy,
            moreOrLessEquals(-115.38461538461536),
          );
        }

        // Scroll the top of the refresh indicator back to overscroll, it will
        // snap to the size of the refresh indicator and stay there.
        await tester.drag(
          find.text('1'),
          const Offset(0.0, 200.0),
          warnIfMissed: false,
        ); // hits the list
        await tester.pump();
        await tester.pump(const Duration(seconds: 2));
        expect(
          tester.getRect(find.widgetWithText(Center, '-1')),
          const Rect.fromLTRB(0.0, 0.0, 800.0, 60.0),
        );
        expect(
          tester.getRect(find.widgetWithText(Center, '0')),
          const Rect.fromLTRB(0.0, 60.0, 800.0, 260.0),
        );
      },
      variant: const TargetPlatformVariant(<TargetPlatform>{
        TargetPlatform.iOS,
        TargetPlatform.macOS,
      }),
    );

    testWidgets(
      'expanded refreshing sliver goes away when done',
      (WidgetTester tester) async {
        mockHelper.refreshIndicator = const Center(child: Text('-1'));

        await tester.pumpWidget(
          CupertinoApp(
            home: CustomScrollView(
              slivers: <Widget>[
                CupertinoSliverRefreshControl(
                  builder: mockHelper.builder,
                  onRefresh: mockHelper.refreshTask,
                ),
                buildAListOfStuff(),
              ],
            ),
          ),
        );

        await tester.drag(find.text('0'), const Offset(0.0, 150.0), touchSlopY: 0);
        await tester.pump();
        expect(
          mockHelper.invocations,
          contains(
            matchesBuilder(
              refreshState: RefreshIndicatorMode.armed,
              pulledExtent: 150,
              refreshIndicatorExtent: 60, // Default value.
              refreshTriggerPullDistance: 100, // Default value.
            ),
          ),
        );
        expect(
          tester.getRect(find.widgetWithText(Center, '-1')),
          const Rect.fromLTRB(0.0, 0.0, 800.0, 150.0),
        );
        expect(mockHelper.invocations, contains(const RefreshTaskInvocation()));

        // Rebuilds the sliver with a layout extent now.
        await tester.pump();
        // Let it snap back to occupy the indicator's final sliver space only.
        await tester.pump(const Duration(seconds: 2));

        expect(
          mockHelper.invocations,
          contains(
            matchesBuilder(
              refreshState: RefreshIndicatorMode.refresh,
              pulledExtent: 60,
              refreshIndicatorExtent: 60, // Default value.
              refreshTriggerPullDistance: 100, // Default value.
            ),
          ),
        );
        expect(
          tester.getRect(find.widgetWithText(Center, '-1')),
          const Rect.fromLTRB(0.0, 0.0, 800.0, 60.0),
        );
        expect(
          tester.getRect(find.widgetWithText(Center, '0')),
          const Rect.fromLTRB(0.0, 60.0, 800.0, 260.0),
        );

        mockHelper.refreshCompleter.complete(null);
        await tester.pump();
        expect(
          mockHelper.invocations,
          contains(
            matchesBuilder(
              refreshState: RefreshIndicatorMode.done,
              pulledExtent: 60,
              refreshIndicatorExtent: 60, // Default value.
              refreshTriggerPullDistance: 100, // Default value.
            ),
          ),
        );

        await tester.pump(const Duration(seconds: 5));
        expect(find.text('-1'), findsNothing);
        expect(
          tester.getRect(find.widgetWithText(Center, '0')),
          const Rect.fromLTRB(0.0, 0.0, 800.0, 200.0),
        );
      },
      variant: const TargetPlatformVariant(<TargetPlatform>{
        TargetPlatform.iOS,
        TargetPlatform.macOS,
      }),
    );

    testWidgets(
      'builder still called when sliver snapped back more than 90%',
      (WidgetTester tester) async {
        mockHelper.refreshIndicator = const Center(child: Text('-1'));

        await tester.pumpWidget(
          CupertinoApp(
            home: CustomScrollView(
              slivers: <Widget>[
                CupertinoSliverRefreshControl(
                  builder: mockHelper.builder,
                  onRefresh: mockHelper.refreshTask,
                ),
                buildAListOfStuff(),
              ],
            ),
          ),
        );

        await tester.drag(find.text('0'), const Offset(0.0, 150.0), touchSlopY: 0);
        await tester.pump();
        expect(
          mockHelper.invocations,
          contains(
            matchesBuilder(
              refreshState: RefreshIndicatorMode.armed,
              pulledExtent: 150,
              refreshTriggerPullDistance: 100, // default value.
              refreshIndicatorExtent: 60, // default value.
            ),
          ),
        );
        expect(
          tester.getRect(find.widgetWithText(Center, '-1')),
          const Rect.fromLTRB(0.0, 0.0, 800.0, 150.0),
        );
        expect(mockHelper.invocations, contains(const RefreshTaskInvocation()));

        // Rebuilds the sliver with a layout extent now.
        await tester.pump();
        // Let it snap back to occupy the indicator's final sliver space only.
        await tester.pump(const Duration(seconds: 2));
        expect(
          mockHelper.invocations,
          contains(
            matchesBuilder(
              refreshState: RefreshIndicatorMode.refresh,
              pulledExtent: 60,
              refreshTriggerPullDistance: 100, // default value.
              refreshIndicatorExtent: 60, // default value.
            ),
          ),
        );
        expect(
          tester.getRect(find.widgetWithText(Center, '-1')),
          const Rect.fromLTRB(0.0, 0.0, 800.0, 60.0),
        );
        expect(
          tester.getRect(find.widgetWithText(Center, '0')),
          const Rect.fromLTRB(0.0, 60.0, 800.0, 260.0),
        );

        mockHelper.refreshCompleter.complete(null);
        await tester.pump();

        expect(
          mockHelper.invocations,
          contains(
            matchesBuilder(
              refreshState: RefreshIndicatorMode.done,
              pulledExtent: 60,
              refreshTriggerPullDistance: 100, // default value.
              refreshIndicatorExtent: 60, // default value.
            ),
          ),
        );

        // Waiting for refresh control to reach approximately 5% of height
        await tester.pump(const Duration(milliseconds: 400));

        if (debugDefaultTargetPlatformOverride == TargetPlatform.macOS) {
          expect(
            tester.getRect(find.widgetWithText(Center, '0')).top,
            moreOrLessEquals(3.9543032206542765, epsilon: 4e-1),
          );
          expect(
            tester.getRect(find.widgetWithText(Center, '-1')).height,
            moreOrLessEquals(3.9543032206542765, epsilon: 4e-1),
          );
          expect(
            mockHelper.invocations,
            contains(
              matchesBuilder(
                refreshState: RefreshIndicatorMode.inactive,
                pulledExtent: 3.9543032206542765, // ~5% of 60.0
                refreshTriggerPullDistance: 100, // default value.
                refreshIndicatorExtent: 60, // default value.
              ),
            ),
          );
        } else {
          expect(
            tester.getRect(find.widgetWithText(Center, '0')).top,
            moreOrLessEquals(3.0, epsilon: 4e-1),
          );
          expect(
            tester.getRect(find.widgetWithText(Center, '-1')).height,
            moreOrLessEquals(3.0, epsilon: 4e-1),
          );
          expect(
            mockHelper.invocations,
            contains(
              matchesBuilder(
                refreshState: RefreshIndicatorMode.inactive,
                pulledExtent: 2.6980688300546443, // ~5% of 60.0
                refreshTriggerPullDistance: 100, // default value.
                refreshIndicatorExtent: 60, // default value.
              ),
            ),
          );
        }
        expect(find.text('-1'), findsOneWidget);
      },
      variant: const TargetPlatformVariant(<TargetPlatform>{
        TargetPlatform.iOS,
        TargetPlatform.macOS,
      }),
    );

    testWidgets(
      'retracting sliver during done cannot be pulled to refresh again until fully retracted',
      (WidgetTester tester) async {
        mockHelper.refreshIndicator = const Center(child: Text('-1'));

        await tester.pumpWidget(
          CupertinoApp(
            home: CustomScrollView(
              slivers: <Widget>[
                CupertinoSliverRefreshControl(
                  builder: mockHelper.builder,
                  onRefresh: mockHelper.refreshTask,
                ),
                buildAListOfStuff(),
              ],
            ),
          ),
        );

        await tester.drag(find.text('0'), const Offset(0.0, 150.0), pointer: 1, touchSlopY: 0.0);
        await tester.pump();
        expect(mockHelper.invocations, contains(const RefreshTaskInvocation()));

        mockHelper.refreshCompleter.complete(null);
        await tester.pump();
        expect(
          mockHelper.invocations,
          contains(
            matchesBuilder(
              refreshState: RefreshIndicatorMode.done,
              pulledExtent: 150.0, // Still overscrolled here.
              refreshTriggerPullDistance: 100, // default value.
              refreshIndicatorExtent: 60, // default value.
            ),
          ),
        );

        // Let it start going away but not fully.
        await tester.pump(const Duration(milliseconds: 100));
        // The refresh indicator is still building.
        if (debugDefaultTargetPlatformOverride == TargetPlatform.macOS) {
          expect(
            mockHelper.invocations,
            contains(
              matchesBuilder(
                refreshState: RefreshIndicatorMode.done,
                pulledExtent: 90.13497854600749,
                refreshTriggerPullDistance: 100, // default value.
                refreshIndicatorExtent: 60, // default value.
              ),
            ),
          );
          expect(
            tester.getBottomLeft(find.widgetWithText(Center, '-1')).dy,
            moreOrLessEquals(90.13497854600749),
          );
        } else {
          expect(
            mockHelper.invocations,
            contains(
              matchesBuilder(
                refreshState: RefreshIndicatorMode.done,
                pulledExtent: 91.31180913199277,
                refreshTriggerPullDistance: 100, // default value.
                refreshIndicatorExtent: 60, // default value.
              ),
            ),
          );
          expect(
            tester.getBottomLeft(find.widgetWithText(Center, '-1')).dy,
            moreOrLessEquals(91.311809131992776),
          );
        }

        // Start another drag by an amount that would have been enough to
        // trigger another refresh if it were in the right state.
        await tester.drag(
          find.text('0'),
          const Offset(0.0, 150.0),
          pointer: 1,
          touchSlopY: 0.0,
          warnIfMissed: false,
        );
        await tester.pump();

        // Instead, it's still in the done state because the sliver never
        // fully retracted.
        if (debugDefaultTargetPlatformOverride == TargetPlatform.macOS) {
          expect(
            mockHelper.invocations,
            contains(
              matchesBuilder(
                refreshState: RefreshIndicatorMode.done,
                pulledExtent: 118.29756539042118,
                refreshTriggerPullDistance: 100, // default value.
                refreshIndicatorExtent: 60, // default value.
              ),
            ),
          );
        } else {
          expect(
            mockHelper.invocations,
            contains(
              matchesBuilder(
                refreshState: RefreshIndicatorMode.done,
                pulledExtent: 147.3772721631821,
                refreshTriggerPullDistance: 100, // default value.
                refreshIndicatorExtent: 60, // default value.
              ),
            ),
          );
        }

        // Now let it fully go away.
        await tester.pump(const Duration(seconds: 5));
        expect(find.text('-1'), findsNothing);
        expect(
          tester.getRect(find.widgetWithText(Center, '0')),
          const Rect.fromLTRB(0.0, 0.0, 800.0, 200.0),
        );

        // Start another drag. It's now in drag mode.
        await tester.drag(find.text('0'), const Offset(0.0, 40.0), pointer: 1, touchSlopY: 0.0);
        await tester.pump();
        expect(
          mockHelper.invocations,
          contains(
            matchesBuilder(
              refreshState: RefreshIndicatorMode.drag,
              pulledExtent: 40,
              refreshTriggerPullDistance: 100, // default value.
              refreshIndicatorExtent: 60, // default value.
            ),
          ),
        );
      },
      variant: const TargetPlatformVariant(<TargetPlatform>{
        TargetPlatform.iOS,
        TargetPlatform.macOS,
      }),
    );

    testWidgets(
      'sliver held in overscroll when task finishes completes normally',
      (WidgetTester tester) async {
        mockHelper.refreshIndicator = const Center(child: Text('-1'));

        await tester.pumpWidget(
          CupertinoApp(
            home: CustomScrollView(
              slivers: <Widget>[
                CupertinoSliverRefreshControl(
                  builder: mockHelper.builder,
                  onRefresh: mockHelper.refreshTask,
                ),
                buildAListOfStuff(),
              ],
            ),
          ),
        );

        final TestGesture gesture = await tester.startGesture(Offset.zero);
        // Start a refresh.
        await gesture.moveBy(const Offset(0.0, 150.0));
        await tester.pump();
        expect(mockHelper.invocations, contains(const RefreshTaskInvocation()));

        // Complete the task while held down.
        mockHelper.refreshCompleter.complete(null);
        await tester.pump();

        expect(
          mockHelper.invocations,
          contains(
            matchesBuilder(
              refreshState: RefreshIndicatorMode.done,
              pulledExtent: 150.0, // Still overscrolled here.
              refreshTriggerPullDistance: 100, // default value.
              refreshIndicatorExtent: 60, // default value.
            ),
          ),
        );
        expect(
          tester.getRect(find.widgetWithText(Center, '0')),
          const Rect.fromLTRB(0.0, 150.0, 800.0, 350.0),
        );

        await gesture.up();
        await tester.pump();
        await tester.pump(const Duration(seconds: 5));
        expect(find.text('-1'), findsNothing);
        expect(
          tester.getRect(find.widgetWithText(Center, '0')),
          const Rect.fromLTRB(0.0, 0.0, 800.0, 200.0),
        );
      },
      variant: const TargetPlatformVariant(<TargetPlatform>{
        TargetPlatform.iOS,
        TargetPlatform.macOS,
      }),
    );

    testWidgets(
      'sliver scrolled away when task completes properly removes itself',
      (WidgetTester tester) async {
        if (testListLength < 4) {
          // This test only makes sense when the list is long enough that
          // the indicator can be scrolled away while refreshing.
          return;
        }
        mockHelper.refreshIndicator = const Center(child: Text('-1'));

        await tester.pumpWidget(
          CupertinoApp(
            home: CustomScrollView(
              slivers: <Widget>[
                CupertinoSliverRefreshControl(
                  builder: mockHelper.builder,
                  onRefresh: mockHelper.refreshTask,
                ),
                buildAListOfStuff(),
              ],
            ),
          ),
        );

        // Start a refresh.
        await tester.drag(find.text('0'), const Offset(0.0, 150.0));
        await tester.pump();
        expect(mockHelper.invocations, contains(const RefreshTaskInvocation()));

        await tester.drag(find.text('0'), const Offset(0.0, -300.0));
        await tester.pump();

        // Refresh indicator still being told to layout the same way.
        expect(
          mockHelper.invocations,
          contains(
            matchesBuilder(
              refreshState: RefreshIndicatorMode.done,
              pulledExtent: 60,
              refreshTriggerPullDistance: 100, // default value.
              refreshIndicatorExtent: 60, // default value.
            ),
          ),
        );

        // Now the sliver is scrolled off screen.
        expect(
          tester.getTopLeft(find.widgetWithText(Center, '-1', skipOffstage: false)).dy,
          moreOrLessEquals(-175.38461538461536),
        );
        expect(
          tester.getBottomLeft(find.widgetWithText(Center, '-1', skipOffstage: false)).dy,
          moreOrLessEquals(-115.38461538461536),
        );

        // Complete the task while scrolled away.
        mockHelper.refreshCompleter.complete(null);
        // The sliver is instantly gone since there is no overscroll physics
        // simulation.
        await tester.pump();

        // The next item's position is not disturbed.
        expect(
          tester.getTopLeft(find.widgetWithText(Center, '0')).dy,
          moreOrLessEquals(-115.38461538461536),
        );

        // Scrolling past the first item still results in a new overscroll.
        // The layout extent is gone.
        await tester.drag(find.text('1'), const Offset(0.0, 120.0));
        await tester.pump();

        expect(
          mockHelper.invocations,
          contains(
            matchesBuilder(
              refreshState: RefreshIndicatorMode.done,
              pulledExtent: 4.615384615384642,
              refreshTriggerPullDistance: 100, // default value.
              refreshIndicatorExtent: 60, // default value.
            ),
          ),
        );

        // Snaps away normally.
        await tester.pump();
        await tester.pump(const Duration(seconds: 2));
        expect(find.text('-1'), findsNothing);
        expect(
          tester.getRect(find.widgetWithText(Center, '0')),
          const Rect.fromLTRB(0.0, 0.0, 800.0, 200.0),
        );
      },
      variant: const TargetPlatformVariant(<TargetPlatform>{
        TargetPlatform.iOS,
        TargetPlatform.macOS,
      }),
    );

    testWidgets(
      "don't do anything unless it can be overscrolled at the start of the list",
      (WidgetTester tester) async {
        mockHelper.refreshIndicator = const Center(child: Text('-1'));

        await tester.pumpWidget(
          CupertinoApp(
            home: CustomScrollView(
              slivers: <Widget>[
                buildAListOfStuff(),
                CupertinoSliverRefreshControl(
                  // it's in the middle now.
                  builder: mockHelper.builder,
                  onRefresh: mockHelper.refreshTask,
                ),
                buildAListOfStuff(),
              ],
            ),
          ),
        );

        await tester.fling(find.byType(SizedBox).first, const Offset(0.0, 200.0), 2000.0);
        await tester.fling(
          find.byType(SizedBox).first,
          const Offset(0.0, -200.0),
          3000.0,
          warnIfMissed: false,
        ); // IgnorePointer is enabled while scroll is ballistic.

        expect(mockHelper.invocations, isEmpty);
      },
      variant: const TargetPlatformVariant(<TargetPlatform>{
        TargetPlatform.iOS,
        TargetPlatform.macOS,
      }),
    );

    testWidgets(
      'without an onRefresh, builder is called with arm for one frame then sliver goes away',
      (WidgetTester tester) async {
        mockHelper.refreshIndicator = const Center(child: Text('-1'));

        await tester.pumpWidget(
          CupertinoApp(
            home: CustomScrollView(
              slivers: <Widget>[
                CupertinoSliverRefreshControl(builder: mockHelper.builder),
                buildAListOfStuff(),
              ],
            ),
          ),
        );

        await tester.drag(find.text('0'), const Offset(0.0, 150.0), touchSlopY: 0.0);
        await tester.pump();

        expect(
          mockHelper.invocations.first,
          matchesBuilder(
            refreshState: RefreshIndicatorMode.armed,
            pulledExtent: 150.0,
            refreshTriggerPullDistance: 100.0, // Default value.
            refreshIndicatorExtent: 60.0, // Default value.
          ),
        );

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

        if (debugDefaultTargetPlatformOverride == TargetPlatform.macOS) {
          expect(
            mockHelper.invocations.last,
            matchesBuilder(
              refreshState: RefreshIndicatorMode.done,
              pulledExtent: moreOrLessEquals(148.36088180097366),
              refreshTriggerPullDistance: 100.0, // Default value.
              refreshIndicatorExtent: 60.0, // Default value.
            ),
          );
        } else {
          expect(
            mockHelper.invocations.last,
            matchesBuilder(
              refreshState: RefreshIndicatorMode.done,
              pulledExtent: moreOrLessEquals(148.6463892921364),
              refreshTriggerPullDistance: 100.0, // Default value.
              refreshIndicatorExtent: 60.0, // Default value.
            ),
          );
        }

        await tester.pump(const Duration(seconds: 5));
        expect(find.text('-1'), findsNothing);
        expect(
          tester.getRect(find.widgetWithText(Center, '0')),
          const Rect.fromLTRB(0.0, 0.0, 800.0, 200.0),
        );
      },
      variant: const TargetPlatformVariant(<TargetPlatform>{
        TargetPlatform.iOS,
        TargetPlatform.macOS,
      }),
    );

    testWidgets(
      'Should not crash when dragged',
      (WidgetTester tester) async {
        await tester.pumpWidget(
          CupertinoApp(
            home: CustomScrollView(
              physics: const BouncingScrollPhysics(),
              slivers: <Widget>[
                CupertinoSliverRefreshControl(
                  onRefresh: () async => Future<void>.delayed(const Duration(days: 2000)),
                ),
              ],
            ),
          ),
        );

        await tester.dragFrom(const Offset(100, 10), const Offset(0.0, 50.0), touchSlopY: 0);
        await tester.pump();

        await tester.dragFrom(const Offset(100, 10), const Offset(0, 500), touchSlopY: 0);
        await tester.pump();

        expect(tester.takeException(), isNull);
      },
      variant: const TargetPlatformVariant(<TargetPlatform>{
        TargetPlatform.iOS,
        TargetPlatform.macOS,
      }),
    );

    // Test to make sure the refresh sliver's overscroll isn't eaten by the
    // nav bar sliver https://github.com/flutter/flutter/issues/74516.
    testWidgets(
      'properly displays when the refresh sliver is behind the large title nav bar sliver',
      (WidgetTester tester) async {
        await tester.pumpWidget(
          CupertinoApp(
            home: CustomScrollView(
              slivers: <Widget>[
                const CupertinoSliverNavigationBar(largeTitle: Text('Title')),
                CupertinoSliverRefreshControl(builder: mockHelper.builder),
                buildAListOfStuff(),
              ],
            ),
          ),
        );

        final double initialFirstCellY = tester.getTopLeft(find.widgetWithText(SizedBox, '0')).dy;

        // Drag down but not enough to trigger the refresh.
        await tester.drag(find.text('0'), const Offset(0.0, 50.0), touchSlopY: 0);
        await tester.pump();

        expect(
          mockHelper.invocations.first,
          matchesBuilder(
            refreshState: RefreshIndicatorMode.drag,
            pulledExtent: 50,
            refreshTriggerPullDistance: 100, // default value.
            refreshIndicatorExtent: 60, // default value.
          ),
        );
        expect(mockHelper.invocations, hasLength(1));

        expect(tester.getTopLeft(find.widgetWithText(SizedBox, '0')).dy, initialFirstCellY + 50);
      },
      variant: const TargetPlatformVariant(<TargetPlatform>{
        TargetPlatform.iOS,
        TargetPlatform.macOS,
      }),
    );
  }

  void stateMachineTestGroup() {
    testWidgets(
      'starts in inactive state',
      (WidgetTester tester) async {
        await tester.pumpWidget(
          CupertinoApp(
            home: CustomScrollView(
              slivers: <Widget>[
                CupertinoSliverRefreshControl(builder: mockHelper.builder),
                buildAListOfStuff(),
              ],
            ),
          ),
        );

        expect(
          CupertinoSliverRefreshControl.state(
            tester.element(find.byType(LayoutBuilder, skipOffstage: false)),
          ),
          RefreshIndicatorMode.inactive,
        );
      },
      variant: const TargetPlatformVariant(<TargetPlatform>{
        TargetPlatform.iOS,
        TargetPlatform.macOS,
      }),
    );

    testWidgets(
      'goes to drag and returns to inactive in a small drag',
      (WidgetTester tester) async {
        await tester.pumpWidget(
          CupertinoApp(
            home: CustomScrollView(
              slivers: <Widget>[
                CupertinoSliverRefreshControl(builder: mockHelper.builder),
                buildAListOfStuff(),
              ],
            ),
          ),
        );

        await tester.drag(find.text('0'), const Offset(0.0, 20.0));
        await tester.pump();

        expect(
          CupertinoSliverRefreshControl.state(tester.element(find.byType(LayoutBuilder))),
          RefreshIndicatorMode.drag,
        );

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

        expect(
          CupertinoSliverRefreshControl.state(
            tester.element(find.byType(LayoutBuilder, skipOffstage: false)),
          ),
          RefreshIndicatorMode.inactive,
        );
      },
      variant: const TargetPlatformVariant(<TargetPlatform>{
        TargetPlatform.iOS,
        TargetPlatform.macOS,
      }),
    );

    testWidgets(
      'goes to armed the frame it passes the threshold',
      (WidgetTester tester) async {
        await tester.pumpWidget(
          CupertinoApp(
            home: CustomScrollView(
              slivers: <Widget>[
                CupertinoSliverRefreshControl(
                  builder: mockHelper.builder,
                  refreshTriggerPullDistance: 80.0,
                ),
                buildAListOfStuff(),
              ],
            ),
          ),
        );

        final TestGesture gesture = await tester.startGesture(Offset.zero);
        await gesture.moveBy(const Offset(0.0, 79.0));
        await tester.pump();
        expect(
          CupertinoSliverRefreshControl.state(tester.element(find.byType(LayoutBuilder))),
          RefreshIndicatorMode.drag,
        );
        if (debugDefaultTargetPlatformOverride == TargetPlatform.macOS) {
          await gesture.moveBy(
            const Offset(0.0, 20.0),
          ); // Overscrolling, need to move more than 1px.
        } else {
          await gesture.moveBy(
            const Offset(0.0, 3.0),
          ); // Overscrolling, need to move more than 1px.
        }
        await tester.pump();
        expect(
          CupertinoSliverRefreshControl.state(tester.element(find.byType(LayoutBuilder))),
          RefreshIndicatorMode.armed,
        );
      },
      variant: const TargetPlatformVariant(<TargetPlatform>{
        TargetPlatform.iOS,
        TargetPlatform.macOS,
      }),
    );

    testWidgets(
      'goes to refresh the frame it crossed back the refresh threshold',
      (WidgetTester tester) async {
        await tester.pumpWidget(
          CupertinoApp(
            home: CustomScrollView(
              slivers: <Widget>[
                CupertinoSliverRefreshControl(
                  builder: mockHelper.builder,
                  onRefresh: mockHelper.refreshTask,
                  refreshTriggerPullDistance: 90.0,
                  refreshIndicatorExtent: 50.0,
                ),
                buildAListOfStuff(),
              ],
            ),
          ),
        );

        final TestGesture gesture = await tester.startGesture(Offset.zero);
        await gesture.moveBy(const Offset(0.0, 90.0)); // Arm it.
        await tester.pump();
        expect(
          CupertinoSliverRefreshControl.state(tester.element(find.byType(LayoutBuilder))),
          RefreshIndicatorMode.armed,
        );

        await gesture.moveBy(
          const Offset(0.0, -80.0),
        ); // Overscrolling, need to move more than -40.
        await tester.pump();
        if (debugDefaultTargetPlatformOverride == TargetPlatform.macOS) {
          expect(
            tester.getTopLeft(find.widgetWithText(SizedBox, '0')).dy,
            moreOrLessEquals(10.0), // Below 50 now.
          );
        } else {
          expect(
            tester.getTopLeft(find.widgetWithText(SizedBox, '0')).dy,
            moreOrLessEquals(49.775111111111116), // Below 50 now.
          );
        }
        expect(
          CupertinoSliverRefreshControl.state(tester.element(find.byType(LayoutBuilder))),
          RefreshIndicatorMode.refresh,
        );
      },
      variant: const TargetPlatformVariant(<TargetPlatform>{
        TargetPlatform.iOS,
        TargetPlatform.macOS,
      }),
    );

    testWidgets(
      'goes to done internally as soon as the task finishes',
      (WidgetTester tester) async {
        await tester.pumpWidget(
          CupertinoApp(
            home: CustomScrollView(
              slivers: <Widget>[
                CupertinoSliverRefreshControl(
                  builder: mockHelper.builder,
                  onRefresh: mockHelper.refreshTask,
                ),
                buildAListOfStuff(),
              ],
            ),
          ),
        );

        await tester.drag(find.text('0'), const Offset(0.0, 100.0), touchSlopY: 0.0);
        await tester.pump();
        expect(
          CupertinoSliverRefreshControl.state(tester.element(find.byType(LayoutBuilder))),
          RefreshIndicatorMode.armed,
        );
        // The sliver scroll offset correction is applied on the next frame.
        await tester.pump();

        await tester.pump(const Duration(seconds: 2));
        expect(
          CupertinoSliverRefreshControl.state(tester.element(find.byType(LayoutBuilder))),
          RefreshIndicatorMode.refresh,
        );
        expect(
          tester.getRect(find.widgetWithText(SizedBox, '0')),
          const Rect.fromLTRB(0.0, 60.0, 800.0, 260.0),
        );

        mockHelper.refreshCompleter.complete(null);
        // The task completed between frames. The internal state goes to done
        // right away even though the sliver gets a new offset correction the
        // next frame.
        expect(
          CupertinoSliverRefreshControl.state(tester.element(find.byType(LayoutBuilder))),
          RefreshIndicatorMode.done,
        );
      },
      variant: const TargetPlatformVariant(<TargetPlatform>{
        TargetPlatform.iOS,
        TargetPlatform.macOS,
      }),
    );

    testWidgets(
      'goes back to inactive when retracting back past 10% of arming distance',
      (WidgetTester tester) async {
        await tester.pumpWidget(
          CupertinoApp(
            home: CustomScrollView(
              slivers: <Widget>[
                CupertinoSliverRefreshControl(
                  builder: mockHelper.builder,
                  onRefresh: mockHelper.refreshTask,
                ),
                buildAListOfStuff(),
              ],
            ),
          ),
        );

        final TestGesture gesture = await tester.startGesture(Offset.zero);
        await gesture.moveBy(const Offset(0.0, 150.0));
        await tester.pump();
        expect(
          CupertinoSliverRefreshControl.state(tester.element(find.byType(LayoutBuilder))),
          RefreshIndicatorMode.armed,
        );

        mockHelper.refreshCompleter.complete(null);
        expect(
          CupertinoSliverRefreshControl.state(tester.element(find.byType(LayoutBuilder))),
          RefreshIndicatorMode.done,
        );
        await tester.pump();

        // Now back in overscroll mode.
        if (debugDefaultTargetPlatformOverride == TargetPlatform.macOS) {
          await gesture.moveBy(const Offset(0.0, -125.0));
        } else {
          await gesture.moveBy(const Offset(0.0, -200.0));
        }
        await tester.pump();
        if (debugDefaultTargetPlatformOverride == TargetPlatform.macOS) {
          expect(tester.getTopLeft(find.widgetWithText(SizedBox, '0')).dy, moreOrLessEquals(25.0));
        } else {
          expect(
            tester.getTopLeft(find.widgetWithText(SizedBox, '0')).dy,
            moreOrLessEquals(27.944444444444457),
          );
        }
        // Need to bring it to 100 * 0.1 to reset to inactive.
        expect(
          CupertinoSliverRefreshControl.state(tester.element(find.byType(LayoutBuilder))),
          RefreshIndicatorMode.done,
        );

        if (debugDefaultTargetPlatformOverride == TargetPlatform.macOS) {
          await gesture.moveBy(const Offset(0.0, -16.0));
        } else {
          await gesture.moveBy(const Offset(0.0, -35.0));
        }
        await tester.pump();
        if (debugDefaultTargetPlatformOverride == TargetPlatform.macOS) {
          expect(tester.getTopLeft(find.widgetWithText(SizedBox, '0')).dy, moreOrLessEquals(9.0));
        } else {
          expect(
            tester.getTopLeft(find.widgetWithText(SizedBox, '0')).dy,
            moreOrLessEquals(9.313890708161875),
          );
        }
        expect(
          CupertinoSliverRefreshControl.state(tester.element(find.byType(LayoutBuilder))),
          RefreshIndicatorMode.inactive,
        );
      },
      variant: const TargetPlatformVariant(<TargetPlatform>{
        TargetPlatform.iOS,
        TargetPlatform.macOS,
      }),
    );

    testWidgets(
      'goes back to inactive if already scrolled away when task completes',
      (WidgetTester tester) async {
        await tester.pumpWidget(
          CupertinoApp(
            home: CustomScrollView(
              slivers: <Widget>[
                CupertinoSliverRefreshControl(
                  builder: mockHelper.builder,
                  onRefresh: mockHelper.refreshTask,
                ),
                buildAListOfStuff(),
              ],
            ),
          ),
        );

        final TestGesture gesture = await tester.startGesture(Offset.zero);
        await gesture.moveBy(const Offset(0.0, 150.0));
        await tester.pump();
        expect(
          CupertinoSliverRefreshControl.state(tester.element(find.byType(LayoutBuilder))),
          RefreshIndicatorMode.armed,
        );
        await tester.pump(); // Sliver scroll offset correction is applied one frame later.

        await gesture.moveBy(const Offset(0.0, -300.0));
        var indicatorDestinationPosition = -145.0332383665717;
        if (debugDefaultTargetPlatformOverride == TargetPlatform.macOS) {
          indicatorDestinationPosition = -150.0;
        }
        await tester.pump();
        // The refresh indicator is offscreen now.
        expect(
          tester.getTopLeft(find.widgetWithText(SizedBox, '0')).dy,
          moreOrLessEquals(indicatorDestinationPosition),
        );
        expect(
          CupertinoSliverRefreshControl.state(
            tester.element(find.byType(LayoutBuilder, skipOffstage: false)),
          ),
          RefreshIndicatorMode.refresh,
        );

        mockHelper.refreshCompleter.complete(null);
        // The sliver layout extent is removed on next frame.
        await tester.pump();
        expect(
          CupertinoSliverRefreshControl.state(
            tester.element(find.byType(LayoutBuilder, skipOffstage: false)),
          ),
          RefreshIndicatorMode.inactive,
        );
        // Nothing moved.
        expect(
          tester.getTopLeft(find.widgetWithText(SizedBox, '0')).dy,
          moreOrLessEquals(indicatorDestinationPosition),
        );
        await tester.pump(const Duration(seconds: 2));
        // Everything stayed as is.
        expect(
          tester.getTopLeft(find.widgetWithText(SizedBox, '0')).dy,
          moreOrLessEquals(indicatorDestinationPosition),
        );
      },
      variant: const TargetPlatformVariant(<TargetPlatform>{
        TargetPlatform.iOS,
        TargetPlatform.macOS,
      }),
    );

    testWidgets(
      "don't have to build any indicators or occupy space during refresh",
      (WidgetTester tester) async {
        mockHelper.refreshIndicator = const Center(child: Text('-1'));

        await tester.pumpWidget(
          CupertinoApp(
            home: CustomScrollView(
              slivers: <Widget>[
                CupertinoSliverRefreshControl(
                  builder: null,
                  onRefresh: mockHelper.refreshTask,
                  refreshIndicatorExtent: 0.0,
                ),
                buildAListOfStuff(),
              ],
            ),
          ),
        );

        await tester.drag(find.text('0'), const Offset(0.0, 150.0));
        await tester.pump();
        expect(
          CupertinoSliverRefreshControl.state(tester.element(find.byType(LayoutBuilder))),
          RefreshIndicatorMode.armed,
        );

        await tester.pump();
        await tester.pump(const Duration(seconds: 5));
        // In refresh mode but has no UI.
        expect(
          CupertinoSliverRefreshControl.state(
            tester.element(find.byType(LayoutBuilder, skipOffstage: false)),
          ),
          RefreshIndicatorMode.refresh,
        );
        expect(
          tester.getRect(find.widgetWithText(Center, '0')),
          const Rect.fromLTRB(0.0, 0.0, 800.0, 200.0),
        );

        mockHelper.refreshCompleter.complete(null);
        await tester.pump();
        // Goes to inactive right away since the sliver is already collapsed.
        expect(
          CupertinoSliverRefreshControl.state(
            tester.element(find.byType(LayoutBuilder, skipOffstage: false)),
          ),
          RefreshIndicatorMode.inactive,
        );
      },
      variant: const TargetPlatformVariant(<TargetPlatform>{
        TargetPlatform.iOS,
        TargetPlatform.macOS,
      }),
    );

    testWidgets('buildRefreshIndicator progress', (WidgetTester tester) async {
      await tester.pumpWidget(
        CupertinoApp(
          home: Builder(
            builder: (BuildContext context) {
              return CupertinoSliverRefreshControl.buildRefreshIndicator(
                context,
                RefreshIndicatorMode.drag,
                10,
                100,
                10,
              );
            },
          ),
        ),
      );
      expect(
        tester.widget<CupertinoActivityIndicator>(find.byType(CupertinoActivityIndicator)).progress,
        10.0 / 100.0,
      );

      await tester.pumpWidget(
        CupertinoApp(
          home: Builder(
            builder: (BuildContext context) {
              return CupertinoSliverRefreshControl.buildRefreshIndicator(
                context,
                RefreshIndicatorMode.drag,
                26,
                100,
                10,
              );
            },
          ),
        ),
      );
      expect(
        tester.widget<CupertinoActivityIndicator>(find.byType(CupertinoActivityIndicator)).progress,
        26.0 / 100.0,
      );

      await tester.pumpWidget(
        CupertinoApp(
          home: Builder(
            builder: (BuildContext context) {
              return CupertinoSliverRefreshControl.buildRefreshIndicator(
                context,
                RefreshIndicatorMode.drag,
                100,
                100,
                10,
              );
            },
          ),
        ),
      );
      expect(
        tester.widget<CupertinoActivityIndicator>(find.byType(CupertinoActivityIndicator)).progress,
        100.0 / 100.0,
      );
    });

    testWidgets('indicator should not become larger when overscrolled', (
      WidgetTester tester,
    ) async {
      // test for https://github.com/flutter/flutter/issues/79841
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: Builder(
            builder: (BuildContext context) {
              return CupertinoSliverRefreshControl.buildRefreshIndicator(
                context,
                RefreshIndicatorMode.done,
                120,
                100,
                10,
              );
            },
          ),
        ),
      );

      expect(
        tester.widget<CupertinoActivityIndicator>(find.byType(CupertinoActivityIndicator)).radius,
        14.0,
      );
    });
  }

  group('UI tests long list', uiTestGroup);

  // Test the internal state machine directly to make sure the UI aren't just
  // correct by coincidence.
  group('state machine test long list', stateMachineTestGroup);

  // Retest everything and make sure that it still works when the whole list
  // is smaller than the viewport size.
  testListLength = 2;
  group('UI tests short list', uiTestGroup);

  // Test the internal state machine directly to make sure the UI aren't just
  // correct by coincidence.
  group('state machine test short list', stateMachineTestGroup);

  testWidgets('Does not crash when paintExtent > remainingPaintExtent', (
    WidgetTester tester,
  ) async {
    // Regression test for https://github.com/flutter/flutter/issues/46871.
    await tester.pumpWidget(
      CupertinoApp(
        home: CustomScrollView(
          physics: const BouncingScrollPhysics(),
          slivers: <Widget>[
            const CupertinoSliverRefreshControl(),
            SliverList.builder(
              itemCount: 20,
              itemBuilder: (BuildContext context, int index) => const SizedBox(height: 100),
            ),
          ],
        ),
      ),
    );

    // Drag the content down far enough so that
    // geometry.paintExtent > constraints.maxPaintExtent
    await tester.dragFrom(const Offset(10, 10), const Offset(0, 500));
    await tester.pump();

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

class FakeBuilder {
  Completer<void> refreshCompleter = Completer<void>.sync();
  final List<MockHelperInvocation> invocations = <MockHelperInvocation>[];

  Widget refreshIndicator = Container();

  Widget builder(
    BuildContext context,
    RefreshIndicatorMode refreshState,
    double pulledExtent,
    double refreshTriggerPullDistance,
    double refreshIndicatorExtent,
  ) {
    if (pulledExtent < 0.0) {
      throw TestFailure('The pulledExtent should never be less than 0.0');
    }
    if (refreshTriggerPullDistance < 0.0) {
      throw TestFailure('The refreshTriggerPullDistance should never be less than 0.0');
    }
    if (refreshIndicatorExtent < 0.0) {
      throw TestFailure('The refreshIndicatorExtent should never be less than 0.0');
    }
    invocations.add(
      BuilderInvocation(
        refreshState: refreshState,
        pulledExtent: pulledExtent,
        refreshTriggerPullDistance: refreshTriggerPullDistance,
        refreshIndicatorExtent: refreshIndicatorExtent,
      ),
    );
    return refreshIndicator;
  }

  Future<void> refreshTask() {
    invocations.add(const RefreshTaskInvocation());
    return refreshCompleter.future;
  }
}

abstract class MockHelperInvocation {
  const MockHelperInvocation();
}

@immutable
class RefreshTaskInvocation extends MockHelperInvocation {
  const RefreshTaskInvocation();
}

@immutable
class BuilderInvocation extends MockHelperInvocation {
  const BuilderInvocation({
    required this.refreshState,
    required this.pulledExtent,
    required this.refreshIndicatorExtent,
    required this.refreshTriggerPullDistance,
  });

  final RefreshIndicatorMode refreshState;
  final double pulledExtent;
  final double refreshTriggerPullDistance;
  final double refreshIndicatorExtent;

  @override
  String toString() =>
      '{refreshState: $refreshState, pulledExtent: $pulledExtent, refreshTriggerPullDistance: $refreshTriggerPullDistance, refreshIndicatorExtent: $refreshIndicatorExtent}';
}

Matcher matchesBuilder({
  required RefreshIndicatorMode refreshState,
  required dynamic pulledExtent,
  required dynamic refreshTriggerPullDistance,
  required dynamic refreshIndicatorExtent,
}) {
  return isA<BuilderInvocation>()
      .having(
        (BuilderInvocation invocation) => invocation.refreshState,
        'refreshState',
        refreshState,
      )
      .having(
        (BuilderInvocation invocation) => invocation.pulledExtent,
        'pulledExtent',
        pulledExtent,
      )
      .having(
        (BuilderInvocation invocation) => invocation.refreshTriggerPullDistance,
        'refreshTriggerPullDistance',
        refreshTriggerPullDistance,
      )
      .having(
        (BuilderInvocation invocation) => invocation.refreshIndicatorExtent,
        'refreshIndicatorExtent',
        refreshIndicatorExtent,
      );
}
