// 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')
import 'dart:ui';

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

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

void main() {
  late MockNavigatorObserver navigatorObserver;

  setUp(() {
    navigatorObserver = MockNavigatorObserver();
  });

  testWidgets('Middle auto-populates with title', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        home: Placeholder(),
      ),
    );

    tester.state<NavigatorState>(find.byType(Navigator)).push(
      CupertinoPageRoute<void>(
        title: 'An iPod',
        builder: (BuildContext context) {
          return const CupertinoPageScaffold(
            navigationBar: CupertinoNavigationBar(),
            child: Placeholder(),
          );
        },
      ),
    );

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

    // There should be a Text widget with the title in the nav bar even though
    // we didn't specify anything in the nav bar constructor.
    expect(find.widgetWithText(CupertinoNavigationBar, 'An iPod'), findsOneWidget);

    // As a title, it should also be centered.
    expect(tester.getCenter(find.text('An iPod')).dx, 400.0);
  });

  testWidgets('Large title auto-populates with title', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        home: Placeholder(),
      ),
    );

    tester.state<NavigatorState>(find.byType(Navigator)).push(
      CupertinoPageRoute<void>(
        title: 'An iPod',
        builder: (BuildContext context) {
          return const CupertinoPageScaffold(
            child: CustomScrollView(
              slivers: <Widget>[
                CupertinoSliverNavigationBar(),
              ],
            ),
          );
        },
      ),
    );

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

    // There should be 2 Text widget with the title in the nav bar. One in the
    // large title position and one in the middle position (though the middle
    // position Text is initially invisible while the sliver is expanded).
    expect(
      find.widgetWithText(CupertinoSliverNavigationBar, 'An iPod'),
      findsNWidgets(2),
    );

    final List<Element> titles = tester.elementList(find.text('An iPod'))
        .toList()
        ..sort((Element a, Element b) {
          final RenderParagraph aParagraph = a.renderObject! as RenderParagraph;
          final RenderParagraph bParagraph = b.renderObject! as RenderParagraph;
          return aParagraph.text.style!.fontSize!.compareTo(
            bParagraph.text.style!.fontSize!,
          );
        });

    final Iterable<double> opacities = titles.map<double>((Element element) {
      final RenderAnimatedOpacity renderOpacity =
          element.findAncestorRenderObjectOfType<RenderAnimatedOpacity>()!;
      return renderOpacity.opacity.value;
    });

    expect(opacities, <double> [
      0.0, // Initially the smaller font title is invisible.
      1.0, // The larger font title is visible.
    ]);

    // Check that the large font title is at the right spot.
    expect(
      tester.getTopLeft(find.byWidget(titles[1].widget)),
      const Offset(16.0, 54.0),
    );

    // The smaller, initially invisible title, should still be positioned in the
    // center.
    expect(tester.getCenter(find.byWidget(titles[0].widget)).dx, 400.0);
  });

  testWidgets('Leading auto-populates with back button with previous title', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        home: Placeholder(),
      ),
    );

    tester.state<NavigatorState>(find.byType(Navigator)).push(
      CupertinoPageRoute<void>(
        title: 'An iPod',
        builder: (BuildContext context) {
          return const CupertinoPageScaffold(
            navigationBar: CupertinoNavigationBar(),
            child: Placeholder(),
          );
        },
      ),
    );

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

    tester.state<NavigatorState>(find.byType(Navigator)).push(
      CupertinoPageRoute<void>(
        title: 'A Phone',
        builder: (BuildContext context) {
          return const CupertinoPageScaffold(
            navigationBar: CupertinoNavigationBar(),
            child: Placeholder(),
          );
        },
      ),
    );

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

    expect(find.widgetWithText(CupertinoNavigationBar, 'A Phone'), findsOneWidget);
    expect(tester.getCenter(find.text('A Phone')).dx, 400.0);

    // Also shows the previous page's title next to the back button.
    expect(find.widgetWithText(CupertinoButton, 'An iPod'), findsOneWidget);
    // 3 paddings + 1 ahem character at font size 34.0.
    expect(tester.getTopLeft(find.text('An iPod')).dx, 8.0 + 4.0 + 34.0 + 6.0);
  });

  testWidgets('Previous title is correct on first transition frame', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        home: Placeholder(),
      ),
    );

    tester.state<NavigatorState>(find.byType(Navigator)).push(
      CupertinoPageRoute<void>(
        title: 'An iPod',
        builder: (BuildContext context) {
          return const CupertinoPageScaffold(
            navigationBar: CupertinoNavigationBar(),
            child: Placeholder(),
          );
        },
      ),
    );

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

    tester.state<NavigatorState>(find.byType(Navigator)).push(
      CupertinoPageRoute<void>(
        title: 'A Phone',
        builder: (BuildContext context) {
          return const CupertinoPageScaffold(
            navigationBar: CupertinoNavigationBar(),
            child: Placeholder(),
          );
        },
      ),
    );

    // Trigger the route push
    await tester.pump();
    // Draw the first frame.
    await tester.pump();

    // Also shows the previous page's title next to the back button.
    expect(find.widgetWithText(CupertinoButton, 'An iPod'), findsOneWidget);
  });

  testWidgets('Previous title stays up to date with changing routes', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        home: Placeholder(),
      ),
    );

    final CupertinoPageRoute<void> route2 = CupertinoPageRoute<void>(
      title: 'An iPod',
      builder: (BuildContext context) {
        return const CupertinoPageScaffold(
          navigationBar: CupertinoNavigationBar(),
          child: Placeholder(),
        );
      },
    );

    final CupertinoPageRoute<void> route3 = CupertinoPageRoute<void>(
      title: 'A Phone',
      builder: (BuildContext context) {
        return const CupertinoPageScaffold(
          navigationBar: CupertinoNavigationBar(),
          child: Placeholder(),
        );
      },
    );

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

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

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

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

    tester.state<NavigatorState>(find.byType(Navigator)).replace(
      oldRoute: route2,
      newRoute: CupertinoPageRoute<void>(
        title: 'An Internet communicator',
        builder: (BuildContext context) {
          return const CupertinoPageScaffold(
            navigationBar: CupertinoNavigationBar(),
            child: Placeholder(),
          );
        },
      ),
    );

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

    expect(find.widgetWithText(CupertinoNavigationBar, 'A Phone'), findsOneWidget);
    expect(tester.getCenter(find.text('A Phone')).dx, 400.0);

    // After swapping the route behind the top one, the previous label changes
    // from An iPod to Back (since An Internet communicator is too long to
    // fit in the back button).
    expect(find.widgetWithText(CupertinoButton, 'Back'), findsOneWidget);
    expect(tester.getTopLeft(find.text('Back')).dx, 8.0 + 4.0 + 34.0 + 6.0);
  });

  testWidgets('Back swipe dismiss interrupted by route push', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/28728
    final GlobalKey scaffoldKey = GlobalKey();

    await tester.pumpWidget(
      CupertinoApp(
        home: CupertinoPageScaffold(
          key: scaffoldKey,
          child: Center(
            child: CupertinoButton(
              onPressed: () {
                Navigator.push<void>(scaffoldKey.currentContext!, CupertinoPageRoute<void>(
                  builder: (BuildContext context) {
                    return const CupertinoPageScaffold(
                      child: Center(child: Text('route')),
                    );
                  },
                ));
              },
              child: const Text('push'),
            ),
          ),
        ),
      ),
    );

    // Check the basic iOS back-swipe dismiss transition. Dragging the pushed
    // route halfway across the screen will trigger the iOS dismiss animation

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

    TestGesture gesture = await tester.startGesture(const Offset(5, 300));
    await gesture.moveBy(const Offset(400, 0));
    await gesture.up();
    await tester.pump();
    expect( // The 'route' route has been dragged to the right, halfway across the screen
      tester.getTopLeft(find.ancestor(of: find.text('route'), matching: find.byType(CupertinoPageScaffold))),
      const Offset(400, 0),
    );
    expect( // The 'push' route is sliding in from the left.
      tester.getTopLeft(find.ancestor(of: find.text('push'), matching: find.byType(CupertinoPageScaffold))).dx,
      lessThan(0),
    );
    await tester.pumpAndSettle();
    expect(find.text('push'), findsOneWidget);
    expect(
      tester.getTopLeft(find.ancestor(of: find.text('push'), matching: find.byType(CupertinoPageScaffold))),
      Offset.zero,
    );
    expect(find.text('route'), findsNothing);


    // Run the dismiss animation 60%, which exposes the route "push" button,
    // and then press the button.

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

    gesture = await tester.startGesture(const Offset(5, 300));
    await gesture.moveBy(const Offset(400, 0)); // Drag halfway.
    await gesture.up();
    // Trigger the snapping animation.
    // Since the back swipe drag was brought to >=50% of the screen, it will
    // self snap to finish the pop transition as the gesture is lifted.
    //
    // This drag drop animation is 400ms when dropped exactly halfway
    // (800 / [pixel distance remaining], see
    // _CupertinoBackGestureController.dragEnd). It follows a curve that is very
    // steep initially.
    await tester.pump();
    expect(
      tester.getTopLeft(find.ancestor(of: find.text('route'), matching: find.byType(CupertinoPageScaffold))),
      const Offset(400, 0),
    );
    // Let the dismissing snapping animation go 60%.
    await tester.pump(const Duration(milliseconds: 240));
    expect(
      tester.getTopLeft(find.ancestor(of: find.text('route'), matching: find.byType(CupertinoPageScaffold))).dx,
      moreOrLessEquals(798, epsilon: 1),
    );

    // Use the navigator to push a route instead of tapping the 'push' button.
    // The topmost route (the one that's animating away), ignores input while
    // the pop is underway because route.navigator.userGestureInProgress.
    Navigator.push<void>(scaffoldKey.currentContext!, CupertinoPageRoute<void>(
      builder: (BuildContext context) {
        return const CupertinoPageScaffold(
          child: Center(child: Text('route')),
        );
      },
    ));

    await tester.pumpAndSettle();
    expect(find.text('route'), findsOneWidget);
    expect(find.text('push'), findsNothing);
    expect(
      tester.state<NavigatorState>(find.byType(Navigator)).userGestureInProgress,
      false,
    );
  });

  testWidgets('Fullscreen route animates correct transform values over time', (WidgetTester tester) async {
    await tester.pumpWidget(
      CupertinoApp(
        home: Builder(
          builder: (BuildContext context) {
            return CupertinoButton(
              child: const Text('Button'),
              onPressed: () {
                Navigator.push<void>(context, CupertinoPageRoute<void>(
                  fullscreenDialog: true,
                  builder: (BuildContext context) {
                    return Column(
                      children: <Widget>[
                        const Placeholder(),
                        CupertinoButton(
                          child: const Text('Close'),
                          onPressed: () {
                            Navigator.pop<void>(context);
                          },
                        ),
                      ],
                    );
                  },
                ));
              },
            );
          },
        ),
      ),
    );

    // Enter animation.
    await tester.tap(find.text('Button'));
    await tester.pump();

    // We use a higher number of intervals since the animation has to scale the
    // entire screen.

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(443.7, epsilon: 0.1));

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(291.9, epsilon: 0.1));

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(168.2, epsilon: 0.1));

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(89.5, epsilon: 0.1));

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(48.1, epsilon: 0.1));

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(26.1, epsilon: 0.1));

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(14.3, epsilon: 0.1));

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(7.41, epsilon: 0.1));

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(3.0, epsilon: 0.1));

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(0.0, epsilon: 0.1));

    // Exit animation
    await tester.tap(find.text('Close'));
    await tester.pump();

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(156.3, epsilon: 0.1));

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(308.1, epsilon: 0.1));

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(431.7, epsilon: 0.1));

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(510.4, epsilon: 0.1));

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(551.8, epsilon: 0.1));

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(573.8, epsilon: 0.1));

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(585.6, epsilon: 0.1));

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(592.6, epsilon: 0.1));

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(596.9, epsilon: 0.1));

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dy, moreOrLessEquals(600.0, epsilon: 0.1));
  });

  Future<void> testParallax(WidgetTester tester, {required bool fromFullscreenDialog}) async {
    await tester.pumpWidget(
      CupertinoApp(
        onGenerateRoute: (RouteSettings settings) => CupertinoPageRoute<void>(
          fullscreenDialog: fromFullscreenDialog,
          settings: settings,
          builder: (BuildContext context) {
            return Column(
              children: <Widget>[
                const Placeholder(),
                CupertinoButton(
                  child: const Text('Button'),
                  onPressed: () {
                    Navigator.push<void>(context, CupertinoPageRoute<void>(
                      builder: (BuildContext context) {
                        return CupertinoButton(
                          child: const Text('Close'),
                          onPressed: () {
                            Navigator.pop<void>(context);
                          },
                        );
                      },
                    ));
                  },
                ),
              ],
            );
          },
        ),
      ),
    );

    // Enter animation.
    await tester.tap(find.text('Button'));
    expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(0.0, epsilon: 0.1));
    await tester.pump();

    // We use a higher number of intervals since the animation has to scale the
    // entire screen.

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-70.0, epsilon: 1.0));

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-137.0, epsilon: 1.0));

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-192.0, epsilon: 1.0));

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-227.0, epsilon: 1.0));

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-246.0, epsilon: 1.0));

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-255.0, epsilon: 1.0));

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-260.0, epsilon: 1.0));

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-264.0, epsilon: 1.0));

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-266.0, epsilon: 1.0));

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-267.0, epsilon: 1.0));

    // Exit animation
    await tester.tap(find.text('Close'));
    await tester.pump();

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-198.0, epsilon: 1.0));

    await tester.pump(const Duration(milliseconds: 360));
    expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(-0.0, epsilon: 1.0));
  }

  testWidgets('CupertinoPageRoute has parallax when non fullscreenDialog route is pushed on top', (WidgetTester tester) async {
    await testParallax(tester, fromFullscreenDialog: false);
  });

  testWidgets('FullscreenDialog CupertinoPageRoute has parallax when non fullscreenDialog route is pushed on top', (WidgetTester tester) async {
    await testParallax(tester, fromFullscreenDialog: true);
  });

  Future<void> testNoParallax(WidgetTester tester, {required bool fromFullscreenDialog}) async{
    await tester.pumpWidget(
      CupertinoApp(
        onGenerateRoute: (RouteSettings settings) => CupertinoPageRoute<void>(
          fullscreenDialog: fromFullscreenDialog,
          builder: (BuildContext context) {
            return Column(
              children: <Widget>[
                const Placeholder(),
                CupertinoButton(
                  child: const Text('Button'),
                  onPressed: () {
                    Navigator.push<void>(context, CupertinoPageRoute<void>(
                      fullscreenDialog: true,
                      builder: (BuildContext context) {
                        return CupertinoButton(
                          child: const Text('Close'),
                          onPressed: () {
                            Navigator.pop<void>(context);
                          },
                        );
                      },
                    ));
                  },
                ),
              ],
            );
          },
        ),
      ),
    );

    // Enter animation.
    await tester.tap(find.text('Button'));
    expect(tester.getTopLeft(find.byType(Placeholder)).dx, moreOrLessEquals(0.0, epsilon: 0.1));
    await tester.pump();

    // We use a higher number of intervals since the animation has to scale the
    // entire screen.

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dx, 0.0);

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dx, 0.0);

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dx, 0.0);

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dx, 0.0);

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dx, 0.0);

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dx, 0.0);

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dx, 0.0);

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dx, 0.0);

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dx, 0.0);

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dx, 0.0);

    // Exit animation
    await tester.tap(find.text('Close'));
    await tester.pump();

    await tester.pump(const Duration(milliseconds: 40));
    expect(tester.getTopLeft(find.byType(Placeholder)).dx, 0.0);

    await tester.pump(const Duration(milliseconds: 360));
    expect(tester.getTopLeft(find.byType(Placeholder)).dx, 0.0);
  }

  testWidgets('CupertinoPageRoute has no parallax when fullscreenDialog route is pushed on top', (WidgetTester tester) async {
    await testNoParallax(tester, fromFullscreenDialog: false);
  });

  testWidgets('FullscreenDialog CupertinoPageRoute has no parallax when fullscreenDialog route is pushed on top', (WidgetTester tester) async {
    await testNoParallax(tester, fromFullscreenDialog: true);
  });

  testWidgets('Animated push/pop is not linear', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        home: Text('1'),
      ),
    );

    final CupertinoPageRoute<void> route2 = CupertinoPageRoute<void>(
      builder: (BuildContext context) {
        return const CupertinoPageScaffold(
          child: Text('2'),
        );
      },
    );

    tester.state<NavigatorState>(find.byType(Navigator)).push(route2);
    // The whole transition is 400ms based on CupertinoPageRoute.transitionDuration.
    // Break it up into small chunks.

    await tester.pump();
    await tester.pump(const Duration(milliseconds: 50));
    expect(tester.getTopLeft(find.text('1')).dx, moreOrLessEquals(-87, epsilon: 1));
    expect(tester.getTopLeft(find.text('2')).dx, moreOrLessEquals(537, epsilon: 1));

    await tester.pump(const Duration(milliseconds: 50));
    expect(tester.getTopLeft(find.text('1')).dx, moreOrLessEquals(-166, epsilon: 1));
    expect(tester.getTopLeft(find.text('2')).dx, moreOrLessEquals(301, epsilon: 1));

    await tester.pump(const Duration(milliseconds: 50));
    // Translation slows down as time goes on.
    expect(tester.getTopLeft(find.text('1')).dx, moreOrLessEquals(-220, epsilon: 1));
    expect(tester.getTopLeft(find.text('2')).dx, moreOrLessEquals(141, epsilon: 1));

    // Finish the rest of the animation
    await tester.pump(const Duration(milliseconds: 250));

    tester.state<NavigatorState>(find.byType(Navigator)).pop();
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 50));
    expect(tester.getTopLeft(find.text('1')).dx, moreOrLessEquals(-179, epsilon: 1));
    expect(tester.getTopLeft(find.text('2')).dx, moreOrLessEquals(262, epsilon: 1));

    await tester.pump(const Duration(milliseconds: 50));
    expect(tester.getTopLeft(find.text('1')).dx, moreOrLessEquals(-100, epsilon: 1));
    expect(tester.getTopLeft(find.text('2')).dx, moreOrLessEquals(499, epsilon: 1));

    await tester.pump(const Duration(milliseconds: 50));
    // Translation slows down as time goes on.
    expect(tester.getTopLeft(find.text('1')).dx, moreOrLessEquals(-47, epsilon: 1));
    expect(tester.getTopLeft(find.text('2')).dx, moreOrLessEquals(659, epsilon: 1));
  });

  testWidgets('Dragged pop gesture is linear', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        home: Text('1'),
      ),
    );

    final CupertinoPageRoute<void> route2 = CupertinoPageRoute<void>(
      builder: (BuildContext context) {
        return const CupertinoPageScaffold(
          child: Text('2'),
        );
      },
    );

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

    await tester.pumpAndSettle();

    expect(find.text('1'), findsNothing);
    expect(tester.getTopLeft(find.text('2')).dx, moreOrLessEquals(0));

    final TestGesture swipeGesture = await tester.startGesture(const Offset(5, 100));

    await swipeGesture.moveBy(const Offset(100, 0));
    await tester.pump();
    expect(tester.getTopLeft(find.text('1')).dx, moreOrLessEquals(-233, epsilon: 1));
    expect(tester.getTopLeft(find.text('2')).dx, moreOrLessEquals(100));
    expect(
      tester.state<NavigatorState>(find.byType(Navigator)).userGestureInProgress,
      true,
    );

    await swipeGesture.moveBy(const Offset(100, 0));
    await tester.pump();
    expect(tester.getTopLeft(find.text('1')).dx, moreOrLessEquals(-200));
    expect(tester.getTopLeft(find.text('2')).dx, moreOrLessEquals(200));

    // Moving by the same distance each time produces linear movements on both
    // routes.
    await swipeGesture.moveBy(const Offset(100, 0));
    await tester.pump();
    expect(tester.getTopLeft(find.text('1')).dx, moreOrLessEquals(-166, epsilon: 1));
    expect(tester.getTopLeft(find.text('2')).dx, moreOrLessEquals(300));
  });

  testWidgets('Pop gesture snapping is not linear', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        home: Text('1'),
      ),
    );

    final CupertinoPageRoute<void> route2 = CupertinoPageRoute<void>(
      builder: (BuildContext context) {
        return const CupertinoPageScaffold(
          child: Text('2'),
        );
      },
    );

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

    await tester.pumpAndSettle();

    final TestGesture swipeGesture = await tester.startGesture(const Offset(5, 100));

    await swipeGesture.moveBy(const Offset(500, 0));
    await swipeGesture.up();
    await tester.pump();
    expect(tester.getTopLeft(find.text('1')).dx, moreOrLessEquals(-100));
    expect(tester.getTopLeft(find.text('2')).dx, moreOrLessEquals(500));
    expect(
      tester.state<NavigatorState>(find.byType(Navigator)).userGestureInProgress,
      true,
    );

    await tester.pump(const Duration(milliseconds: 50));
    expect(tester.getTopLeft(find.text('1')).dx, moreOrLessEquals(-19, epsilon: 1));
    expect(tester.getTopLeft(find.text('2')).dx, moreOrLessEquals(744, epsilon: 1));

    await tester.pump(const Duration(milliseconds: 50));
    // Rate of change is slowing down.
    expect(tester.getTopLeft(find.text('1')).dx, moreOrLessEquals(-4, epsilon: 1));
    expect(tester.getTopLeft(find.text('2')).dx, moreOrLessEquals(787, epsilon: 1));

    await tester.pumpAndSettle();
    expect(
      tester.state<NavigatorState>(find.byType(Navigator)).userGestureInProgress,
      false,
    );
  });

  testWidgets('Snapped drags forwards and backwards should signal didStart/StopUserGesture', (WidgetTester tester) async {
    final GlobalKey<NavigatorState> navigatorKey = GlobalKey();
    await tester.pumpWidget(
      CupertinoApp(
        navigatorObservers: <NavigatorObserver>[navigatorObserver],
        navigatorKey: navigatorKey,
        home: const Text('1'),
      ),
    );

    final CupertinoPageRoute<void> route2 = CupertinoPageRoute<void>(
      builder: (BuildContext context) {
        return const CupertinoPageScaffold(
          child: Text('2'),
        );
      },
    );

    navigatorKey.currentState!.push(route2);
    await tester.pumpAndSettle();
    expect(navigatorObserver.invocations.removeLast(), NavigatorInvocation.didPush);

    await tester.dragFrom(const Offset(5, 100), const Offset(100, 0));
    expect(navigatorObserver.invocations.removeLast(), NavigatorInvocation.didStartUserGesture);
    await tester.pump();
    expect(tester.getTopLeft(find.text('2')).dx, moreOrLessEquals(100));
    expect(navigatorKey.currentState!.userGestureInProgress, true);

    // Didn't drag far enough to snap into dismissing this route.
    // Each 100px distance takes 100ms to snap back.
    await tester.pump(const Duration(milliseconds: 101));
    // Back to the page covering the whole screen.
    expect(tester.getTopLeft(find.text('2')).dx, moreOrLessEquals(0));
    expect(navigatorKey.currentState!.userGestureInProgress, false);

    expect(navigatorObserver.invocations.removeLast(), NavigatorInvocation.didStopUserGesture);
    expect(navigatorObserver.invocations.removeLast(), isNot(NavigatorInvocation.didPop));

    await tester.dragFrom(const Offset(5, 100), const Offset(500, 0));
    await tester.pump();
    expect(tester.getTopLeft(find.text('2')).dx, moreOrLessEquals(500));
    expect(navigatorKey.currentState!.userGestureInProgress, true);
    expect(navigatorObserver.invocations.removeLast(), NavigatorInvocation.didPop);

    // Did go far enough to snap out of this route.
    await tester.pump(const Duration(milliseconds: 301));
    // Back to the page covering the whole screen.
    expect(find.text('2'), findsNothing);
    // First route covers the whole screen.
    expect(tester.getTopLeft(find.text('1')).dx, moreOrLessEquals(0));
    expect(navigatorKey.currentState!.userGestureInProgress, false);
  });

  /// Regression test for https://github.com/flutter/flutter/issues/29596.
  testWidgets('test edge swipe then drop back at ending point works', (WidgetTester tester) async {
    await tester.pumpWidget(
      CupertinoApp(
        navigatorObservers: <NavigatorObserver>[navigatorObserver],
        onGenerateRoute: (RouteSettings settings) {
          return CupertinoPageRoute<void>(
            settings: settings,
            builder: (BuildContext context) {
              final String pageNumber = settings.name == '/' ? '1' : '2';
              return Center(child: Text('Page $pageNumber'));
            },
          );
        },
      ),
    );

    tester.state<NavigatorState>(find.byType(Navigator)).pushNamed('/next');

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

    expect(find.text('Page 1'), findsNothing);
    expect(find.text('Page 2'), isOnstage);

    final TestGesture gesture = await tester.startGesture(const Offset(5, 200));
    // The width of the page.
    await gesture.moveBy(const Offset(800, 0));
    expect(navigatorObserver.invocations.removeLast(), NavigatorInvocation.didStartUserGesture);
    await gesture.up();
    await tester.pump();

    expect(find.text('Page 1'), isOnstage);
    expect(find.text('Page 2'), findsNothing);
    expect(navigatorObserver.invocations.removeLast(), NavigatorInvocation.didStopUserGesture);
    expect(navigatorObserver.invocations.removeLast(), NavigatorInvocation.didPop);
  });

  testWidgets('test edge swipe then drop back at starting point works', (WidgetTester tester) async {
    await tester.pumpWidget(
      CupertinoApp(
        navigatorObservers: <NavigatorObserver>[navigatorObserver],
        onGenerateRoute: (RouteSettings settings) {
          return CupertinoPageRoute<void>(
            settings: settings,
            builder: (BuildContext context) {
              final String pageNumber = settings.name == '/' ? '1' : '2';
              return Center(child: Text('Page $pageNumber'));
            },
          );
        },
      ),
    );

    tester.state<NavigatorState>(find.byType(Navigator)).pushNamed('/next');

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

    expect(find.text('Page 1'), findsNothing);
    expect(find.text('Page 2'), isOnstage);

    final TestGesture gesture = await tester.startGesture(const Offset(5, 200));
    // Move right a bit
    await gesture.moveBy(const Offset(300, 0));
    expect(navigatorObserver.invocations.removeLast(), NavigatorInvocation.didStartUserGesture);
    expect(
      tester.state<NavigatorState>(find.byType(Navigator)).userGestureInProgress,
      true,
    );
    await tester.pump();

    // Move back to where we started.
    await gesture.moveBy(const Offset(-300, 0));
    await gesture.up();
    await tester.pump();

    expect(find.text('Page 1'), findsNothing);
    expect(find.text('Page 2'), isOnstage);
    expect(navigatorObserver.invocations.removeLast(), NavigatorInvocation.didStopUserGesture);
    expect(navigatorObserver.invocations.removeLast(), isNot(NavigatorInvocation.didPop));
    expect(
      tester.state<NavigatorState>(find.byType(Navigator)).userGestureInProgress,
      false,
    );
  });

  group('Cupertino page transitions', () {
    CupertinoPageRoute<void> buildRoute({required bool fullscreenDialog}) {
      return CupertinoPageRoute<void>(
        fullscreenDialog: fullscreenDialog,
        builder: (_) => const SizedBox(),
      );
    }

    testWidgets('when route is not fullscreenDialog, it has a barrierColor', (WidgetTester tester) async {
      await tester.pumpWidget(
        const MaterialApp(
          home: SizedBox.expand(),
        ),
      );

      tester.state<NavigatorState>(find.byType(Navigator)).push(
        buildRoute(fullscreenDialog: false),
      );
      await tester.pumpAndSettle();

      expect(tester.widget<ModalBarrier>(find.byType(ModalBarrier).last).color, const Color(0x18000000));
    });

    testWidgets('when route is a fullscreenDialog, it has no barrierColor', (WidgetTester tester) async {
      await tester.pumpWidget(
        const MaterialApp(
          home: SizedBox.expand(),
        ),
      );

      tester.state<NavigatorState>(find.byType(Navigator)).push(
        buildRoute(fullscreenDialog: true),
      );
      await tester.pumpAndSettle();

      expect(tester.widget<ModalBarrier>(find.byType(ModalBarrier).last).color, isNull);
    });

    testWidgets('when route is not fullscreenDialog, it has a _CupertinoEdgeShadowDecoration', (WidgetTester tester) async {
      PaintPattern paintsShadowRect({required double dx, required Color color}) {
        return paints..everything((Symbol methodName, List<dynamic> arguments) {
          if (methodName != #drawRect) {
            return true;
          }
          final Rect rect = arguments[0] as Rect;
          final Color paintColor = (arguments[1] as Paint).color;
          // _CupertinoEdgeShadowDecoration draws the shadows with a series of
          // differently colored 1px-wide rects. Skip rects that aren't being
          // drawn by the _CupertinoEdgeShadowDecoration.
          if (rect.top != 0 || rect.width != 1.0 || rect.height != 600) {
            return true;
          }
          // Skip calls for rects until the one with the given position offset
          if ((rect.left - dx).abs() >= 1) {
            return true;
          }
          if (paintColor.value == color.value) {
            return true;
          }
          throw '''
  For a rect with an expected left-side position: $dx (drawn at ${rect.left}):
              Expected a rect with color: $color,
              And drew a rect with color: $paintColor.
          ''';
        });
      }

      await tester.pumpWidget(
        const MaterialApp(
          home: SizedBox.expand(),
        ),
      );

      tester.state<NavigatorState>(find.byType(Navigator)).push(
        buildRoute(fullscreenDialog: false),
      );
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 1));

      final RenderBox box = tester.firstRenderObject<RenderBox>(find.byType(CustomPaint));

      // Animation starts with effectively no shadow
      expect(box, paintsShadowRect(dx: 795, color: const Color(0x00000000)));
      expect(box, paintsShadowRect(dx: 785, color: const Color(0x00000000)));
      expect(box, paintsShadowRect(dx: 775, color: const Color(0x00000000)));
      expect(box, paintsShadowRect(dx: 765, color: const Color(0x00000000)));
      expect(box, paintsShadowRect(dx: 755, color: const Color(0x00000000)));

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

      // Part-way through the transition, the shadow is approaching the full gradient
      expect(box, paintsShadowRect(dx: 296, color: const Color(0x03000000)));
      expect(box, paintsShadowRect(dx: 286, color: const Color(0x02000000)));
      expect(box, paintsShadowRect(dx: 276, color: const Color(0x01000000)));
      expect(box, paintsShadowRect(dx: 266, color: const Color(0x00000000)));
      expect(box, paintsShadowRect(dx: 266, color: const Color(0x00000000)));

      await tester.pumpAndSettle();

      // At the end of the transition, the shadow is a gradient between
      // 0x04000000 and 0x00000000 and is now offscreen
      expect(box, paintsShadowRect(dx: -1, color: const Color(0x04000000)));
      expect(box, paintsShadowRect(dx: -10, color: const Color(0x03000000)));
      expect(box, paintsShadowRect(dx: -20, color: const Color(0x02000000)));
      expect(box, paintsShadowRect(dx: -30, color: const Color(0x01000000)));
      expect(box, paintsShadowRect(dx: -40, color: const Color(0x00000000)));

      // Start animation in reverse
      tester.state<NavigatorState>(find.byType(Navigator)).pop();
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 100));

      expect(box, paintsShadowRect(dx: 498, color: const Color(0x04000000)));
      expect(box, paintsShadowRect(dx: 488, color: const Color(0x03000000)));
      expect(box, paintsShadowRect(dx: 478, color: const Color(0x02000000)));
      expect(box, paintsShadowRect(dx: 468, color: const Color(0x01000000)));
      expect(box, paintsShadowRect(dx: 458, color: const Color(0x00000000)));

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

      // At the end of the animation, the shadow approaches full transparency
      expect(box, paintsShadowRect(dx: 794, color: const Color(0x01000000)));
      expect(box, paintsShadowRect(dx: 784, color: const Color(0x00000000)));
      expect(box, paintsShadowRect(dx: 774, color: const Color(0x00000000)));
      expect(box, paintsShadowRect(dx: 764, color: const Color(0x00000000)));
      expect(box, paintsShadowRect(dx: 754, color: const Color(0x00000000)));
    });

    testWidgets('when route is fullscreenDialog, it has no visible _CupertinoEdgeShadowDecoration', (WidgetTester tester) async {
      PaintPattern paintsNoShadows() {
        return paints..everything((Symbol methodName, List<dynamic> arguments) {
          if (methodName != #drawRect) {
            return true;
          }
          final Rect rect = arguments[0] as Rect;
          // _CupertinoEdgeShadowDecoration draws the shadows with a series of
          // differently colored 1px rects. Skip all rects not drawn by a
          // _CupertinoEdgeShadowDecoration.
          if (rect.width != 1.0) {
            return true;
          }
          throw '''
    Expected: no rects with a width of 1px.
          Found: $rect.
          ''';
        });
      }

      await tester.pumpWidget(
        const MaterialApp(
          home: SizedBox.expand(),
        ),
      );

      final RenderBox box = tester.firstRenderObject<RenderBox>(find.byType(CustomPaint));

      tester.state<NavigatorState>(find.byType(Navigator)).push(
        buildRoute(fullscreenDialog: true),
      );

      await tester.pumpAndSettle();
      expect(box, paintsNoShadows());

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

      await tester.pumpAndSettle();
      expect(box, paintsNoShadows());
    });
  });

  testWidgets('ModalPopup overlay dark mode', (WidgetTester tester) async {
    late StateSetter stateSetter;
    Brightness brightness = Brightness.light;

    await tester.pumpWidget(
      StatefulBuilder(
        builder: (BuildContext context, StateSetter setter) {
          stateSetter = setter;
          return CupertinoApp(
            theme: CupertinoThemeData(brightness: brightness),
            home: CupertinoPageScaffold(
              child: Builder(builder: (BuildContext context) {
                return GestureDetector(
                  onTap: () async {
                    await showCupertinoModalPopup<void>(
                      context: context,
                      builder: (BuildContext context) => const SizedBox(),
                    );
                  },
                  child: const Text('tap'),
                );
              }),
            ),
          );
        },
      ),
    );

    await tester.tap(find.text('tap'));
    await tester.pumpAndSettle();

    expect(
      tester.widget<ModalBarrier>(find.byType(ModalBarrier).last).color!.value,
      0x33000000,
    );

    stateSetter(() { brightness = Brightness.dark; });
    await tester.pump();

    // TODO(LongCatIsLooong): The background overlay SHOULD switch to dark color.
    expect(
      tester.widget<ModalBarrier>(find.byType(ModalBarrier).last).color!.value,
      0x33000000,
    );

    await tester.pumpWidget(
      CupertinoApp(
        theme: const CupertinoThemeData(brightness: Brightness.dark),
        home: CupertinoPageScaffold(
          child: Builder(builder: (BuildContext context) {
            return GestureDetector(
              onTap: () async {
                await showCupertinoModalPopup<void>(
                  context: context,
                  builder: (BuildContext context) => const SizedBox(),
                );
              },
              child: const Text('tap'),
            );
          }),
        ),
      ),
    );

    await tester.tap(find.text('tap'));
    await tester.pumpAndSettle();

    expect(
      tester.widget<ModalBarrier>(find.byType(ModalBarrier).last).color!.value,
      0x7A000000,
    );
  });

  testWidgets('During back swipe the route ignores input', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/39989

    final GlobalKey homeScaffoldKey = GlobalKey();
    final GlobalKey pageScaffoldKey = GlobalKey();
    int homeTapCount = 0;
    int pageTapCount = 0;

    await tester.pumpWidget(
      CupertinoApp(
        home: CupertinoPageScaffold(
          key: homeScaffoldKey,
          child: GestureDetector(
            onTap: () {
              homeTapCount += 1;
            },
          ),
        ),
      ),
    );

    await tester.tap(find.byKey(homeScaffoldKey));
    expect(homeTapCount, 1);
    expect(pageTapCount, 0);

    Navigator.push<void>(homeScaffoldKey.currentContext!, CupertinoPageRoute<void>(
      builder: (BuildContext context) {
        return CupertinoPageScaffold(
          key: pageScaffoldKey,
          child: Padding(
            padding: const EdgeInsets.all(16),
            child: GestureDetector(
              onTap: () {
                pageTapCount += 1;
              },
            ),
          ),
        );
      },
    ));

    await tester.pumpAndSettle();
    await tester.tap(find.byKey(pageScaffoldKey));
    expect(homeTapCount, 1);
    expect(pageTapCount, 1);

    // Start the basic iOS back-swipe dismiss transition. Drag the pushed
    // "page" route halfway across the screen. The underlying "home" will
    // start sliding in from the left.

    final TestGesture gesture = await tester.startGesture(const Offset(5, 300));
    await gesture.moveBy(const Offset(400, 0));
    await tester.pump();
    expect(tester.getTopLeft(find.byKey(pageScaffoldKey)), const Offset(400, 0));
    expect(tester.getTopLeft(find.byKey(homeScaffoldKey)).dx, lessThan(0));

    // Tapping on the "page" route doesn't trigger the GestureDetector because
    // it's being dragged.
    await tester.tap(find.byKey(pageScaffoldKey), warnIfMissed: false);
    expect(homeTapCount, 1);
    expect(pageTapCount, 1);
  });

  testWidgets('showCupertinoModalPopup uses root navigator by default', (WidgetTester tester) async {
    final PopupObserver rootObserver = PopupObserver();
    final PopupObserver nestedObserver = PopupObserver();

    await tester.pumpWidget(CupertinoApp(
      navigatorObservers: <NavigatorObserver>[rootObserver],
      home: Navigator(
        observers: <NavigatorObserver>[nestedObserver],
        onGenerateRoute: (RouteSettings settings) {
          return PageRouteBuilder<dynamic>(
            pageBuilder: (BuildContext context, Animation<double> _, Animation<double> __) {
              return GestureDetector(
                onTap: () async {
                  await showCupertinoModalPopup<void>(
                    context: context,
                    builder: (BuildContext context) => const SizedBox(),
                  );
                },
                child: const Text('tap'),
              );
            },
          );
        },
      ),
    ));

    // Open the dialog.
    await tester.tap(find.text('tap'));

    expect(rootObserver.popupCount, 1);
    expect(nestedObserver.popupCount, 0);
  });

  testWidgets('back swipe to screen edges does not dismiss the hero animation', (WidgetTester tester) async {
    final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
    final UniqueKey container = UniqueKey();
    await tester.pumpWidget(CupertinoApp(
      navigatorKey: navigator,
      routes: <String, WidgetBuilder>{
        '/': (BuildContext context) {
          return CupertinoPageScaffold(
            child: Center(
              child: Hero(
                tag: 'tag',
                transitionOnUserGestures: true,
                child: SizedBox(key: container, height: 150.0, width: 150.0),
              ),
            ),
          );
        },
        '/page2': (BuildContext context) {
          return CupertinoPageScaffold(
            child: Center(
              child: Padding(
                padding: const EdgeInsets.fromLTRB(100.0, 0.0, 0.0, 0.0),
                child: Hero(
                  tag: 'tag',
                  transitionOnUserGestures: true,
                  child: SizedBox(key: container, height: 150.0, width: 150.0),
                ),
              ),
            ),
          );
        },
      },
    ));

    RenderBox box = tester.renderObject(find.byKey(container)) as RenderBox;
    final double initialPosition = box.localToGlobal(Offset.zero).dx;

    navigator.currentState!.pushNamed('/page2');
    await tester.pumpAndSettle();
    box = tester.renderObject(find.byKey(container)) as RenderBox;
    final double finalPosition = box.localToGlobal(Offset.zero).dx;

    final TestGesture gesture = await tester.startGesture(const Offset(5, 300));
    await gesture.moveBy(const Offset(200, 0));
    await tester.pump();
    box = tester.renderObject(find.byKey(container)) as RenderBox;
    final double firstPosition = box.localToGlobal(Offset.zero).dx;
    // Checks the hero is in-transit.
    expect(finalPosition, greaterThan(firstPosition));
    expect(firstPosition, greaterThan(initialPosition));

    // Goes back to final position.
    await gesture.moveBy(const Offset(-200, 0));
    await tester.pump();
    box = tester.renderObject(find.byKey(container)) as RenderBox;
    final double secondPosition = box.localToGlobal(Offset.zero).dx;
    // There will be a small difference.
    expect(finalPosition - secondPosition, lessThan(0.001));

    await gesture.moveBy(const Offset(400, 0));
    await tester.pump();
    box = tester.renderObject(find.byKey(container)) as RenderBox;
    final double thirdPosition = box.localToGlobal(Offset.zero).dx;
    // Checks the hero is still in-transit and moves further away from the first
    // position.
    expect(finalPosition, greaterThan(thirdPosition));
    expect(thirdPosition, greaterThan(initialPosition));
    expect(firstPosition, greaterThan(thirdPosition));
  });

  testWidgets('showCupertinoModalPopup uses nested navigator if useRootNavigator is false', (WidgetTester tester) async {
    final PopupObserver rootObserver = PopupObserver();
    final PopupObserver nestedObserver = PopupObserver();

    await tester.pumpWidget(CupertinoApp(
      navigatorObservers: <NavigatorObserver>[rootObserver],
      home: Navigator(
        observers: <NavigatorObserver>[nestedObserver],
        onGenerateRoute: (RouteSettings settings) {
          return PageRouteBuilder<dynamic>(
            pageBuilder: (BuildContext context, Animation<double> _, Animation<double> __) {
              return GestureDetector(
                onTap: () async {
                  await showCupertinoModalPopup<void>(
                    context: context,
                    useRootNavigator: false,
                    builder: (BuildContext context) => const SizedBox(),
                  );
                },
                child: const Text('tap'),
              );
            },
          );
        },
      ),
    ));

    // Open the dialog.
    await tester.tap(find.text('tap'));

    expect(rootObserver.popupCount, 0);
    expect(nestedObserver.popupCount, 1);
  });

  testWidgets('showCupertinoDialog uses root navigator by default', (WidgetTester tester) async {
    final DialogObserver rootObserver = DialogObserver();
    final DialogObserver nestedObserver = DialogObserver();

    await tester.pumpWidget(CupertinoApp(
      navigatorObservers: <NavigatorObserver>[rootObserver],
      home: Navigator(
        observers: <NavigatorObserver>[nestedObserver],
        onGenerateRoute: (RouteSettings settings) {
          return PageRouteBuilder<dynamic>(
            pageBuilder: (BuildContext context, Animation<double> _, Animation<double> __) {
              return GestureDetector(
                onTap: () async {
                  await showCupertinoDialog<void>(
                    context: context,
                    builder: (BuildContext context) => const SizedBox(),
                  );
                },
                child: const Text('tap'),
              );
            },
          );
        },
      ),
    ));

    // Open the dialog.
    await tester.tap(find.text('tap'));

    expect(rootObserver.dialogCount, 1);
    expect(nestedObserver.dialogCount, 0);
  });

  testWidgets('showCupertinoDialog uses nested navigator if useRootNavigator is false', (WidgetTester tester) async {
    final DialogObserver rootObserver = DialogObserver();
    final DialogObserver nestedObserver = DialogObserver();

    await tester.pumpWidget(CupertinoApp(
      navigatorObservers: <NavigatorObserver>[rootObserver],
      home: Navigator(
        observers: <NavigatorObserver>[nestedObserver],
        onGenerateRoute: (RouteSettings settings) {
          return PageRouteBuilder<dynamic>(
            pageBuilder: (BuildContext context, Animation<double> _, Animation<double> __) {
              return GestureDetector(
                onTap: () async {
                  await showCupertinoDialog<void>(
                    context: context,
                    useRootNavigator: false,
                    builder: (BuildContext context) => const SizedBox(),
                  );
                },
                child: const Text('tap'),
              );
            },
          );
        },
      ),
    ));

    // Open the dialog.
    await tester.tap(find.text('tap'));

    expect(rootObserver.dialogCount, 0);
    expect(nestedObserver.dialogCount, 1);
  });

  testWidgets('showCupertinoModalPopup does not allow for semantics dismiss by default', (WidgetTester tester) async {
    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
    final SemanticsTester semantics = SemanticsTester(tester);
    await tester.pumpWidget(CupertinoApp(
      home: Navigator(
        onGenerateRoute: (RouteSettings settings) {
          return PageRouteBuilder<dynamic>(
            pageBuilder: (BuildContext context, Animation<double> _, Animation<double> __) {
              return GestureDetector(
                onTap: () async {
                  await showCupertinoModalPopup<void>(
                    context: context,
                    builder: (BuildContext context) => const SizedBox(),
                  );
                },
                child: const Text('tap'),
              );
            },
          );
        },
      ),
    ));

    // Push the route.
    await tester.tap(find.text('tap'));
    await tester.pumpAndSettle();

    expect(semantics, isNot(includesNodeWith(
      actions: <SemanticsAction>[SemanticsAction.tap],
      label: 'Dismiss',
    )));
    debugDefaultTargetPlatformOverride = null;
  });

  testWidgets('showCupertinoModalPopup allows for semantics dismiss when set', (WidgetTester tester) async {
    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
    final SemanticsTester semantics = SemanticsTester(tester);
    await tester.pumpWidget(CupertinoApp(
      home: Navigator(
        onGenerateRoute: (RouteSettings settings) {
          return PageRouteBuilder<dynamic>(
            pageBuilder: (BuildContext context, Animation<double> _, Animation<double> __) {
              return GestureDetector(
                onTap: () async {
                  await showCupertinoModalPopup<void>(
                    context: context,
                    semanticsDismissible: true,
                    builder: (BuildContext context) => const SizedBox(),
                  );
                },
                child: const Text('tap'),
              );
            },
          );
        },
      ),
    ));

    // Push the route.
    await tester.tap(find.text('tap'));
    await tester.pumpAndSettle();

    expect(semantics, includesNodeWith(
      actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.dismiss],
      label: 'Dismiss',
    ));
    debugDefaultTargetPlatformOverride = null;
  });

  testWidgets('showCupertinoModalPopup passes RouteSettings to PopupRoute', (WidgetTester tester) async {
    final RouteSettingsObserver routeSettingsObserver = RouteSettingsObserver();

    await tester.pumpWidget(CupertinoApp(
      navigatorObservers: <NavigatorObserver>[routeSettingsObserver],
      home: Navigator(
        onGenerateRoute: (RouteSettings settings) {
          return PageRouteBuilder<dynamic>(
            pageBuilder: (BuildContext context, Animation<double> _, Animation<double> __) {
              return GestureDetector(
                onTap: () async {
                  await showCupertinoModalPopup<void>(
                    context: context,
                    builder: (BuildContext context) => const SizedBox(),
                    routeSettings: const RouteSettings(name: '/modal'),
                  );
                },
                child: const Text('tap'),
              );
            },
          );
        },
      ),
    ));

    // Open the dialog.
    await tester.tap(find.text('tap'));

    expect(routeSettingsObserver.routeName, '/modal');
  });

  testWidgets('showCupertinoModalPopup transparent barrier color is transparent', (WidgetTester tester) async {
    const Color kTransparentColor = Color(0x00000000);

    await tester.pumpWidget(CupertinoApp(
      home: CupertinoPageScaffold(
        child: Builder(builder: (BuildContext context) {
          return GestureDetector(
            onTap: () async {
              await showCupertinoModalPopup<void>(
                context: context,
                builder: (BuildContext context) => const SizedBox(),
                barrierColor: kTransparentColor,
              );
            },
            child: const Text('tap'),
          );
        }),
      ),
    ));

    await tester.tap(find.text('tap'));
    await tester.pumpAndSettle();

    expect(tester.widget<ModalBarrier>(find.byType(ModalBarrier).last).color, null);
  });

  testWidgets('showCupertinoModalPopup null barrier color must be default gray barrier color', (WidgetTester tester) async {
    // Barrier color for a Cupertino modal barrier.
    // Extracted from https://developer.apple.com/design/resources/.
    const Color kModalBarrierColor = CupertinoDynamicColor.withBrightness(
      color: Color(0x33000000),
      darkColor: Color(0x7A000000),
    );

    await tester.pumpWidget(CupertinoApp(
      home: CupertinoPageScaffold(
        child: Builder(builder: (BuildContext context) {
          return GestureDetector(
            onTap: () async {
              await showCupertinoModalPopup<void>(
                context: context,
                builder: (BuildContext context) => const SizedBox(),
              );
            },
            child: const Text('tap'),
          );
        }),
      ),
    ));

    await tester.tap(find.text('tap'));
    await tester.pumpAndSettle();

    expect(tester.widget<ModalBarrier>(find.byType(ModalBarrier).last).color, kModalBarrierColor);
  });

  testWidgets('showCupertinoModalPopup custom barrier color', (WidgetTester tester) async {
    const Color customColor = Color(0x11223344);

    await tester.pumpWidget(CupertinoApp(
      home: CupertinoPageScaffold(
        child: Builder(builder: (BuildContext context) {
          return GestureDetector(
            onTap: () async {
              await showCupertinoModalPopup<void>(
                context: context,
                builder: (BuildContext context) => const SizedBox(),
                barrierColor: customColor,
              );
            },
            child: const Text('tap'),
          );
        }),
      ),
    ));

    await tester.tap(find.text('tap'));
    await tester.pumpAndSettle();

    expect(tester.widget<ModalBarrier>(find.byType(ModalBarrier).last).color, customColor);
  });

  testWidgets('showCupertinoModalPopup barrier dismissible', (WidgetTester tester) async {
    await tester.pumpWidget(CupertinoApp(
      home: CupertinoPageScaffold(
        child: Builder(builder: (BuildContext context) {
          return GestureDetector(
            onTap: () async {
              await showCupertinoModalPopup<void>(
                context: context,
                builder: (BuildContext context) => const Text('Visible'),
              );
            },
            child: const Text('tap'),
          );
        }),
      ),
    ));

    await tester.tap(find.text('tap'));
    await tester.pumpAndSettle();
    await tester.tapAt(tester.getTopLeft(find.ancestor(of: find.text('tap'), matching: find.byType(CupertinoPageScaffold))));
    await tester.pumpAndSettle();

    expect(find.text('Visible'), findsNothing);
  });

  testWidgets('showCupertinoModalPopup barrier not dismissible', (WidgetTester tester) async {
    await tester.pumpWidget(CupertinoApp(
      home: CupertinoPageScaffold(
        child: Builder(builder: (BuildContext context) {
          return GestureDetector(
            onTap: () async {
              await showCupertinoModalPopup<void>(
                context: context,
                builder: (BuildContext context) => const Text('Visible'),
                barrierDismissible: false,
              );
            },
            child: const Text('tap'),
          );
        }),
      ),
    ));

    await tester.tap(find.text('tap'));
    await tester.pumpAndSettle();
    await tester.tapAt(tester.getTopLeft(find.ancestor(of: find.text('tap'), matching: find.byType(CupertinoPageScaffold))));
    await tester.pumpAndSettle();

    expect(find.text('Visible'), findsOneWidget);
  });

  testWidgets('CupertinoPage works', (WidgetTester tester) async {
    final LocalKey pageKey = UniqueKey();
    final TransitionDetector detector = TransitionDetector();
    List<Page<void>> myPages = <Page<void>>[
      CupertinoPage<void>(
        key: pageKey,
        title: 'title one',
        child: CupertinoPageScaffold(
          navigationBar: CupertinoNavigationBar(key: UniqueKey()),
          child: const Text('first'),
        ),
      ),
    ];
    await tester.pumpWidget(
      buildNavigator(
        pages: myPages,
        onPopPage: (Route<dynamic> route, dynamic result) {
          assert(false); // The test shouldn't call this.
          return true;
        },
        transitionDelegate: detector,
      ),
    );

    expect(detector.hasTransition, isFalse);
    expect(find.widgetWithText(CupertinoNavigationBar, 'title one'), findsOneWidget);
    expect(find.text('first'), findsOneWidget);

    myPages = <Page<void>>[
      CupertinoPage<void>(
        key: pageKey,
        title: 'title two',
        child: CupertinoPageScaffold(
          navigationBar: CupertinoNavigationBar(key: UniqueKey()),
          child: const Text('second'),
        ),
      ),
    ];

    await tester.pumpWidget(
      buildNavigator(
        pages: myPages,
        onPopPage: (Route<dynamic> route, dynamic result) {
          assert(false); // The test shouldn't call this.
          return true;
        },
        transitionDelegate: detector,
      ),
    );

    // There should be no transition because the page has the same key.
    expect(detector.hasTransition, isFalse);
    // The content does update.
    expect(find.text('first'), findsNothing);
    expect(find.widgetWithText(CupertinoNavigationBar, 'title one'), findsNothing);
    expect(find.text('second'), findsOneWidget);
    expect(find.widgetWithText(CupertinoNavigationBar, 'title two'), findsOneWidget);
  });

  testWidgets('CupertinoPage can toggle MaintainState', (WidgetTester tester) async {
    final LocalKey pageKeyOne = UniqueKey();
    final LocalKey pageKeyTwo = UniqueKey();
    final TransitionDetector detector = TransitionDetector();
    List<Page<void>> myPages = <Page<void>>[
      CupertinoPage<void>(key: pageKeyOne, maintainState: false, child: const Text('first')),
      CupertinoPage<void>(key: pageKeyTwo, child: const Text('second')),
    ];
    await tester.pumpWidget(
      buildNavigator(
        pages: myPages,
        onPopPage: (Route<dynamic> route, dynamic result) {
          assert(false); // The test shouldn't call this.
          return true;
        },
        transitionDelegate: detector,
      ),
    );

    expect(detector.hasTransition, isFalse);
    // Page one does not maintain state.
    expect(find.text('first', skipOffstage: false), findsNothing);
    expect(find.text('second'), findsOneWidget);

    myPages = <Page<void>>[
      CupertinoPage<void>(key: pageKeyOne, child: const Text('first')),
      CupertinoPage<void>(key: pageKeyTwo, child: const Text('second')),
    ];

    await tester.pumpWidget(
      buildNavigator(
        pages: myPages,
        onPopPage: (Route<dynamic> route, dynamic result) {
          assert(false); // The test shouldn't call this.
          return true;
        },
        transitionDelegate: detector,
      ),
    );
    // There should be no transition because the page has the same key.
    expect(detector.hasTransition, isFalse);
    // Page one sets the maintain state to be true, its widget tree should be
    // built.
    expect(find.text('first', skipOffstage: false), findsOneWidget);
    expect(find.text('second'), findsOneWidget);
  });

  testWidgets('Popping routes should cancel down events', (WidgetTester tester) async {
    await tester.pumpWidget(const _TestPostRouteCancel());

    final TestGesture gesture = await tester.createGesture();
    await gesture.down(tester.getCenter(find.text('PointerCancelEvents: 0')));
    await gesture.up();

    await tester.pumpAndSettle();
    expect(find.byType(CupertinoButton), findsNothing);
    expect(find.text('Hold'), findsOneWidget);

    await gesture.down(tester.getCenter(find.text('Hold')));
    await tester.pump(const Duration(seconds: 2));
    await tester.pumpAndSettle();
    expect(find.text('Hold'), findsNothing);
    expect(find.byType(CupertinoButton), findsOneWidget);
    expect(find.text('PointerCancelEvents: 1'), findsOneWidget);
  });

  testWidgets('Popping routes during back swipe should not crash', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/63984#issuecomment-675679939

    final CupertinoPageRoute<void> r = CupertinoPageRoute<void>(builder: (BuildContext context) {
      return const Scaffold(
        body: Center(
          child: Text('child'),
        ),
      );
    });

    late NavigatorState navigator;

    await tester.pumpWidget(CupertinoApp(
      home: Center(
        child: Builder(builder: (BuildContext context) {
          return ElevatedButton(
            child: const Text('Home'),
            onPressed: () {
              navigator = Navigator.of(context);
              assert(navigator != null);
              navigator.push<void>(r);
            },
          );
        }),
      ),
    ));

    final TestGesture gesture = await tester.createGesture();
    await gesture.down(tester.getCenter(find.byType(ElevatedButton)));
    await gesture.up();

    await tester.pumpAndSettle();

    await gesture.down(const Offset(3, 300));

    // Need 2 events to form a valid drag
    await tester.pump(const Duration(milliseconds: 100));
    await gesture.moveTo(const Offset(30, 300), timeStamp: const Duration(milliseconds: 100));
    await tester.pump(const Duration(milliseconds: 200));
    await gesture.moveTo(const Offset(50, 300), timeStamp: const Duration(milliseconds: 200));

    // Pause a while so that the route is popped when the drag is canceled
    await tester.pump(const Duration(milliseconds: 1000));
    await gesture.moveTo(const Offset(51, 300), timeStamp: const Duration(milliseconds: 1200));

    // Remove the drag
    navigator.removeRoute(r);
    await tester.pump();
  });

  testWidgets('CupertinoModalPopupRoute is state restorable', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        restorationScopeId: 'app',
        home: _RestorableModalTestWidget(),
      ),
    );

    expect(find.byType(CupertinoActionSheet), findsNothing);

    await tester.tap(find.text('X'));
    await tester.pumpAndSettle();

    expect(find.byType(CupertinoActionSheet), findsOneWidget);
    final TestRestorationData restorationData = await tester.getRestorationData();

    await tester.restartAndRestore();

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

    // Tap on the barrier.
    await tester.tapAt(const Offset(10.0, 10.0));
    await tester.pumpAndSettle();

    expect(find.byType(CupertinoActionSheet), findsNothing);

    await tester.restoreFrom(restorationData);
    expect(find.byType(CupertinoActionSheet), findsOneWidget);
  }, skip: isBrowser); // https://github.com/flutter/flutter/issues/33615

  group('showCupertinoDialog avoids overlapping display features', () {
    testWidgets('positioning with anchorPoint', (WidgetTester tester) async {
      await tester.pumpWidget(
        CupertinoApp(
          builder: (BuildContext context, Widget? child) {
            return MediaQuery(
              // Display has a vertical hinge down the middle
              data: const MediaQueryData(
                size: Size(800, 600),
                displayFeatures: <DisplayFeature>[
                  DisplayFeature(
                    bounds: Rect.fromLTRB(390, 0, 410, 600),
                    type: DisplayFeatureType.hinge,
                    state: DisplayFeatureState.unknown,
                  ),
                ],
              ),
              child: child!,
            );
          },
          home: const Center(child: Text('Test')),
        ),
      );
      final BuildContext context = tester.element(find.text('Test'));

      showCupertinoDialog<void>(
        context: context,
        builder: (BuildContext context) {
          return const Placeholder();
        },
        anchorPoint: const Offset(1000, 0),
      );
      await tester.pumpAndSettle();

      // Should take the right side of the screen
      expect(tester.getTopLeft(find.byType(Placeholder)), const Offset(410.0, 0.0));
      expect(tester.getBottomRight(find.byType(Placeholder)), const Offset(800.0, 600.0));
    });

    testWidgets('positioning with Directionality', (WidgetTester tester) async {
      await tester.pumpWidget(
        CupertinoApp(
          builder: (BuildContext context, Widget? child) {
            return MediaQuery(
              // Display has a vertical hinge down the middle
              data: const MediaQueryData(
                size: Size(800, 600),
                displayFeatures: <DisplayFeature>[
                  DisplayFeature(
                    bounds: Rect.fromLTRB(390, 0, 410, 600),
                    type: DisplayFeatureType.hinge,
                    state: DisplayFeatureState.unknown,
                  ),
                ],
              ),
              child: Directionality(
                textDirection: TextDirection.rtl,
                child: child!,
              ),
            );
          },
          home: const Center(child: Text('Test')),
        ),
      );
      final BuildContext context = tester.element(find.text('Test'));

      showCupertinoDialog<void>(
        context: context,
        builder: (BuildContext context) {
          return const Placeholder();
        },
      );
      await tester.pumpAndSettle();

      // Since this is RTL, it should place the dialog on the right screen
      expect(tester.getTopLeft(find.byType(Placeholder)), const Offset(410.0, 0.0));
      expect(tester.getBottomRight(find.byType(Placeholder)), const Offset(800.0, 600.0));
    });

    testWidgets('positioning by default', (WidgetTester tester) async {
      await tester.pumpWidget(
        CupertinoApp(
          builder: (BuildContext context, Widget? child) {
            return MediaQuery(
              // Display has a vertical hinge down the middle
              data: const MediaQueryData(
                size: Size(800, 600),
                displayFeatures: <DisplayFeature>[
                  DisplayFeature(
                    bounds: Rect.fromLTRB(390, 0, 410, 600),
                    type: DisplayFeatureType.hinge,
                    state: DisplayFeatureState.unknown,
                  ),
                ],
              ),
              child: child!,
            );
          },
          home: const Center(child: Text('Test')),
        ),
      );
      final BuildContext context = tester.element(find.text('Test'));

      showCupertinoDialog<void>(
        context: context,
        builder: (BuildContext context) {
          return const Placeholder();
        },
      );
      await tester.pumpAndSettle();

      // By default it should place the dialog on the left screen
      expect(tester.getTopLeft(find.byType(Placeholder)), Offset.zero);
      expect(tester.getBottomRight(find.byType(Placeholder)), const Offset(390.0, 600.0));
    });
  });

  group('showCupertinoModalPopup avoids overlapping display features', () {
    testWidgets('positioning using anchorPoint', (WidgetTester tester) async {
      await tester.pumpWidget(
        CupertinoApp(
          builder: (BuildContext context, Widget? child) {
            return MediaQuery(
              // Display has a vertical hinge down the middle
              data: const MediaQueryData(
                size: Size(800, 600),
                displayFeatures: <DisplayFeature>[
                  DisplayFeature(
                    bounds: Rect.fromLTRB(390, 0, 410, 600),
                    type: DisplayFeatureType.hinge,
                    state: DisplayFeatureState.unknown,
                  ),
                ],
              ),
              child: child!,
            );
          },
          home: const Center(child: Text('Test')),
        ),
      );

      final BuildContext context = tester.element(find.text('Test'));
      showCupertinoModalPopup<void>(
        context: context,
        builder: (BuildContext context) {
          return const Placeholder();
        },
        anchorPoint: const Offset(1000, 0),
      );
      await tester.pumpAndSettle();

      // Should take the right side of the screen
      expect(tester.getTopLeft(find.byType(Placeholder)).dx, 410);
      expect(tester.getBottomRight(find.byType(Placeholder)).dx, 800);
    });

    testWidgets('positioning using Directionality', (WidgetTester tester) async {
      await tester.pumpWidget(
        CupertinoApp(
          builder: (BuildContext context, Widget? child) {
            return MediaQuery(
              // Display has a vertical hinge down the middle
              data: const MediaQueryData(
                size: Size(800, 600),
                displayFeatures: <DisplayFeature>[
                  DisplayFeature(
                    bounds: Rect.fromLTRB(390, 0, 410, 600),
                    type: DisplayFeatureType.hinge,
                    state: DisplayFeatureState.unknown,
                  ),
                ],
              ),
              child: Directionality(
                textDirection: TextDirection.rtl,
                child: child!,
              ),
            );
          },
          home: const Center(child: Text('Test')),
        ),
      );

      final BuildContext context = tester.element(find.text('Test'));
      showCupertinoModalPopup<void>(
        context: context,
        builder: (BuildContext context) {
          return const Placeholder();
        },
      );
      await tester.pumpAndSettle();

      // This is RTL, so it should place the dialog on the right screen
      expect(tester.getTopLeft(find.byType(Placeholder)).dx, 410);
      expect(tester.getBottomRight(find.byType(Placeholder)).dx, 800);
    });

    testWidgets('default positioning', (WidgetTester tester) async {
      await tester.pumpWidget(
        CupertinoApp(
          builder: (BuildContext context, Widget? child) {
            return MediaQuery(
              // Display has a vertical hinge down the middle
              data: const MediaQueryData(
                size: Size(800, 600),
                displayFeatures: <DisplayFeature>[
                  DisplayFeature(
                    bounds: Rect.fromLTRB(390, 0, 410, 600),
                    type: DisplayFeatureType.hinge,
                    state: DisplayFeatureState.unknown,
                  ),
                ],
              ),
              child: child!,
            );
          },
          home: const Center(child: Text('Test')),
        ),
      );

      final BuildContext context = tester.element(find.text('Test'));
      showCupertinoModalPopup<void>(
        context: context,
        builder: (BuildContext context) {
          return const Placeholder();
        },
      );
      await tester.pumpAndSettle();

      // By default it should place the dialog on the left screen
      expect(tester.getTopLeft(find.byType(Placeholder)).dx, 0.0);
      expect(tester.getBottomRight(find.byType(Placeholder)).dx, 390.0);
    });
  });
}

class MockNavigatorObserver extends NavigatorObserver {
  final List<NavigatorInvocation> invocations = <NavigatorInvocation>[];

  @override
  void didStartUserGesture(Route<dynamic> route, Route<dynamic>? previousRoute) {
    invocations.add(NavigatorInvocation.didStartUserGesture);
  }

  @override
  void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
    invocations.add(NavigatorInvocation.didPop);
  }

  @override
  void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
    invocations.add(NavigatorInvocation.didPush);
  }

  @override
  void didStopUserGesture() {
    invocations.add(NavigatorInvocation.didStopUserGesture);
  }
}

enum NavigatorInvocation {
  didStartUserGesture,
  didPop,
  didPush,
  didStopUserGesture,
}

class PopupObserver extends NavigatorObserver {
  int popupCount = 0;

  @override
  void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
    if (route is CupertinoModalPopupRoute) {
      popupCount++;
    }
    super.didPush(route, previousRoute);
  }
}

class DialogObserver extends NavigatorObserver {
  int dialogCount = 0;

  @override
  void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
    if (route is CupertinoDialogRoute) {
      dialogCount++;
    }
    super.didPush(route, previousRoute);
  }
}

class RouteSettingsObserver extends NavigatorObserver {
  String? routeName;

  @override
  void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
    if (route is CupertinoModalPopupRoute) {
      routeName = route.settings.name;
    }
    super.didPush(route, previousRoute);
  }
}

class TransitionDetector extends DefaultTransitionDelegate<void> {
  bool hasTransition = false;
  @override
  Iterable<RouteTransitionRecord> resolve({
    required List<RouteTransitionRecord> newPageRouteHistory,
    required Map<RouteTransitionRecord?, RouteTransitionRecord> locationToExitingPageRoute,
    required Map<RouteTransitionRecord?, List<RouteTransitionRecord>> pageRouteToPagelessRoutes,
  }) {
    hasTransition = true;
    return super.resolve(
      newPageRouteHistory: newPageRouteHistory,
      locationToExitingPageRoute: locationToExitingPageRoute,
      pageRouteToPagelessRoutes: pageRouteToPagelessRoutes,
    );
  }
}

Widget buildNavigator({
  required List<Page<dynamic>> pages,
  PopPageCallback? onPopPage,
  GlobalKey<NavigatorState>? key,
  TransitionDelegate<dynamic>? transitionDelegate,
}) {
  return MediaQuery(
    data: MediaQueryData.fromWindow(WidgetsBinding.instance.window),
    child: Localizations(
      locale: const Locale('en', 'US'),
      delegates: const <LocalizationsDelegate<dynamic>>[
        DefaultCupertinoLocalizations.delegate,
        DefaultWidgetsLocalizations.delegate,
      ],
      child: Directionality(
        textDirection: TextDirection.ltr,
        child: Navigator(
          key: key,
          pages: pages,
          onPopPage: onPopPage,
          transitionDelegate: transitionDelegate ?? const DefaultTransitionDelegate<dynamic>(),
        ),
      ),
    ),
  );
}


// A test target for post-route cancel events.
//
// It contains 2 routes:
//
//  * The initial route, 'home', displays a button showing 'PointerCancelEvents: #',
//    where # is the number of cancel events received. Tapping the button pushes
//    route 'sub'.
//  * The 'sub' route, displays a text showing 'Hold'. Holding the button (a down
//    event) will pop this route after 1 second.
//
// Holding the 'Hold' button at the moment of popping will force the navigator to
// cancel the down event, increasing the Home counter by 1.
class _TestPostRouteCancel extends StatefulWidget {
  const _TestPostRouteCancel();

  @override
  State<StatefulWidget> createState() => _TestPostRouteCancelState();
}

class _TestPostRouteCancelState extends State<_TestPostRouteCancel> {

  int counter = 0;

  Widget _buildHome(BuildContext context) {
    return Center(
      child: CupertinoButton(
        child: Text('PointerCancelEvents: $counter'),
        onPressed: () => Navigator.pushNamed<void>(context, 'sub'),
      ),
    );
  }

  Widget _buildSub(BuildContext context) {
    return Listener(
      onPointerDown: (_) {
        Future<void>.delayed(const Duration(seconds: 1)).then((_) {
          Navigator.pop(context);
        });
      },
      onPointerCancel: (_) {
        setState(() {
          counter += 1;
        });
      },
      child: const Center(
        child: Text('Hold', style: TextStyle(color: Colors.blue)),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return CupertinoApp(
      initialRoute: 'home',
      onGenerateRoute: (RouteSettings settings) {
        return CupertinoPageRoute<void>(
          settings: settings,
          builder: (BuildContext context) {
            switch (settings.name) {
              case 'home':
                return _buildHome(context);
              case 'sub':
                return _buildSub(context);
              default:
                throw UnimplementedError();
            }
          },
        );
      },
    );
  }
}

class _RestorableModalTestWidget extends StatelessWidget {
  const _RestorableModalTestWidget();

  static Route<void> _modalBuilder(BuildContext context, Object? arguments) {
    return CupertinoModalPopupRoute<void>(
      builder: (BuildContext context) {
        return CupertinoActionSheet(
          title: const Text('Title'),
          message: const Text('Message'),
          actions: <Widget>[
            CupertinoActionSheetAction(
              child: const Text('Action One'),
              onPressed: () {
                Navigator.pop(context);
              },
            ),
            CupertinoActionSheetAction(
              child: const Text('Action Two'),
              onPressed: () {
                Navigator.pop(context);
              },
            ),
          ],
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      navigationBar: const CupertinoNavigationBar(
        middle: Text('Home'),
      ),
      child: Center(child: CupertinoButton(
        onPressed: () {
          Navigator.of(context).restorablePush(_modalBuilder);
        },
        child: const Text('X'),
      )),
    );
  }
}
