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

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

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

void main() {
  testWidgets('test page transition (_FadeUpwardsPageTransition)', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: const Material(child: Text('Page 1')),
        theme: ThemeData(
          pageTransitionsTheme: const PageTransitionsTheme(
            builders: <TargetPlatform, PageTransitionsBuilder>{
              TargetPlatform.android: FadeUpwardsPageTransitionsBuilder(),
            },
          ),
        ),
        routes: <String, WidgetBuilder>{
          '/next': (BuildContext context) {
            return const Material(child: Text('Page 2'));
          },
        },
      ),
    );

    final Offset widget1TopLeft = tester.getTopLeft(find.text('Page 1'));

    tester.state<NavigatorState>(find.byType(Navigator)).pushNamed('/next');
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 1));

    FadeTransition widget2Opacity =
        tester.element(find.text('Page 2')).findAncestorWidgetOfExactType<FadeTransition>()!;
    Offset widget2TopLeft = tester.getTopLeft(find.text('Page 2'));
    final Size widget2Size = tester.getSize(find.text('Page 2'));

    // Android transition is vertical only.
    expect(widget1TopLeft.dx == widget2TopLeft.dx, true);
    // Page 1 is above page 2 mid-transition.
    expect(widget1TopLeft.dy < widget2TopLeft.dy, true);
    // Animation begins 3/4 of the way up the page.
    expect(widget2TopLeft.dy < widget2Size.height / 4.0, true);
    // Animation starts with page 2 being near transparent.
    expect(widget2Opacity.opacity.value < 0.01, true);

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

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

    tester.state<NavigatorState>(find.byType(Navigator)).pop();
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 1));

    widget2Opacity =
        tester.element(find.text('Page 2')).findAncestorWidgetOfExactType<FadeTransition>()!;
    widget2TopLeft = tester.getTopLeft(find.text('Page 2'));

    // Page 2 starts to move down.
    expect(widget1TopLeft.dy < widget2TopLeft.dy, true);
    // Page 2 starts to lose opacity.
    expect(widget2Opacity.opacity.value < 1.0, true);

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

    expect(find.text('Page 1'), isOnstage);
    expect(find.text('Page 2'), findsNothing);
  }, variant: TargetPlatformVariant.only(TargetPlatform.android));

  testWidgets('test page transition (CupertinoPageTransition)', (WidgetTester tester) async {
    final Key page2Key = UniqueKey();
    await tester.pumpWidget(
      MaterialApp(
        home: const Material(child: Text('Page 1')),
        routes: <String, WidgetBuilder>{
          '/next': (BuildContext context) {
            return Material(
              key: page2Key,
              child: const Text('Page 2'),
            );
          },
        },
      ),
    );

    final Offset widget1InitialTopLeft = tester.getTopLeft(find.text('Page 1'));

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

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

    Offset widget1TransientTopLeft = tester.getTopLeft(find.text('Page 1'));
    Offset widget2TopLeft = tester.getTopLeft(find.text('Page 2'));
    final RenderDecoratedBox box = tester.element(find.byKey(page2Key))
        .findAncestorRenderObjectOfType<RenderDecoratedBox>()!;

    // Page 1 is moving to the left.
    expect(widget1TransientTopLeft.dx < widget1InitialTopLeft.dx, true);
    // Page 1 isn't moving vertically.
    expect(widget1TransientTopLeft.dy == widget1InitialTopLeft.dy, true);
    // iOS transition is horizontal only.
    expect(widget1InitialTopLeft.dy == widget2TopLeft.dy, true);
    // Page 2 is coming in from the right.
    expect(widget2TopLeft.dx > widget1InitialTopLeft.dx, true);
    // As explained in _CupertinoEdgeShadowPainter.paint the shadow is drawn
    // as a bunch of rects. The rects are covering an area to the left of
    // where the page 2 box is and a width of 5% of the page 2 box width.
    // `paints` tests relative to the painter's given canvas
    // rather than relative to the screen so assert that the shadow starts at
    // offset.dx = 0.
    final PaintPattern paintsShadow = paints;
    for (int i = 0; i < 0.05 * 800; i += 1) {
      paintsShadow.rect(rect: Rect.fromLTWH(-i.toDouble() - 1.0 , 0.0, 1.0, 600));
    }
    expect(box, paintsShadow);

    await tester.pumpAndSettle();

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

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

    widget1TransientTopLeft = tester.getTopLeft(find.text('Page 1'));
    widget2TopLeft = tester.getTopLeft(find.text('Page 2'));

    // Page 1 is coming back from the left.
    expect(widget1TransientTopLeft.dx < widget1InitialTopLeft.dx, true);
    // Page 1 isn't moving vertically.
    expect(widget1TransientTopLeft.dy == widget1InitialTopLeft.dy, true);
    // iOS transition is horizontal only.
    expect(widget1InitialTopLeft.dy == widget2TopLeft.dy, true);
    // Page 2 is leaving towards the right.
    expect(widget2TopLeft.dx > widget1InitialTopLeft.dx, true);

    await tester.pumpAndSettle();

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

    widget1TransientTopLeft = tester.getTopLeft(find.text('Page 1'));

    // Page 1 is back where it started.
    expect(widget1InitialTopLeft == widget1TransientTopLeft, true);
  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));

  testWidgets('test page transition (_ZoomPageTransition) without rasterization', (WidgetTester tester) async {
    Iterable<Layer> findLayers(Finder of) {
      return tester.layerListOf(
        find.ancestor(of: of, matching: find.byType(SnapshotWidget)).first,
      );
    }

    OpacityLayer findForwardFadeTransition(Finder of) {
      return findLayers(of).whereType<OpacityLayer>().first;
    }

    TransformLayer findForwardScaleTransition(Finder of) {
      return findLayers(of).whereType<TransformLayer>().first;
    }

    await tester.pumpWidget(
      MaterialApp(
        onGenerateRoute: (RouteSettings settings) {
          return MaterialPageRoute<void>(
            allowSnapshotting: false,
            builder: (BuildContext context) {
              if (settings.name == '/') {
                return const Material(child: Text('Page 1'));
              }
              return const Material(child: Text('Page 2'));
            },
          );
        },
      ),
    );

    tester.state<NavigatorState>(find.byType(Navigator)).pushNamed('/next');
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 50));

    TransformLayer widget1Scale = findForwardScaleTransition(find.text('Page 1'));
    TransformLayer widget2Scale = findForwardScaleTransition(find.text('Page 2'));
    OpacityLayer widget2Opacity = findForwardFadeTransition(find.text('Page 2'));

    double getScale(TransformLayer layer) {
      return layer.transform!.storage[0];
    }

    // Page 1 is enlarging, starts from 1.0.
    expect(getScale(widget1Scale), greaterThan(1.0));
    // Page 2 is enlarging from the value less than 1.0.
    expect(getScale(widget2Scale), lessThan(1.0));
    // Page 2 is becoming none transparent.
    expect(widget2Opacity.alpha, lessThan(255));

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

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

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

    widget1Scale = findForwardScaleTransition(find.text('Page 1'));
    widget2Scale = findForwardScaleTransition(find.text('Page 2'));
    widget2Opacity = findForwardFadeTransition(find.text('Page 2'));

    // Page 1 is narrowing down, but still larger than 1.0.
    expect(getScale(widget1Scale), greaterThan(1.0));
    // Page 2 is smaller than 1.0.
    expect(getScale(widget2Scale), lessThan(1.0));
    // Page 2 is becoming transparent.
    expect(widget2Opacity.alpha, lessThan(255));

    await tester.pump(const Duration(milliseconds: 200));
    await tester.pump(const Duration(milliseconds: 1));

    expect(find.text('Page 1'), isOnstage);
    expect(find.text('Page 2'), findsNothing);
  }, variant: TargetPlatformVariant.only(TargetPlatform.android));

  testWidgets('test fullscreen dialog transition', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        home: Material(child: Text('Page 1')),
      ),
    );

    final Offset widget1InitialTopLeft = tester.getTopLeft(find.text('Page 1'));

    tester.state<NavigatorState>(find.byType(Navigator)).push(MaterialPageRoute<void>(
      builder: (BuildContext context) {
        return const Material(child: Text('Page 2'));
      },
      fullscreenDialog: true,
    ));

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

    Offset widget1TransientTopLeft = tester.getTopLeft(find.text('Page 1'));
    Offset widget2TopLeft = tester.getTopLeft(find.text('Page 2'));

    // Page 1 doesn't move.
    expect(widget1TransientTopLeft == widget1InitialTopLeft, true);
    // Fullscreen dialogs transitions vertically only.
    expect(widget1InitialTopLeft.dx == widget2TopLeft.dx, true);
    // Page 2 is coming in from the bottom.
    expect(widget2TopLeft.dy > widget1InitialTopLeft.dy, true);

    await tester.pumpAndSettle();

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

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

    widget1TransientTopLeft = tester.getTopLeft(find.text('Page 1'));
    widget2TopLeft = tester.getTopLeft(find.text('Page 2'));

    // Page 1 doesn't move.
    expect(widget1TransientTopLeft == widget1InitialTopLeft, true);
    // Fullscreen dialogs transitions vertically only.
    expect(widget1InitialTopLeft.dx == widget2TopLeft.dx, true);
    // Page 2 is leaving towards the bottom.
    expect(widget2TopLeft.dy > widget1InitialTopLeft.dy, true);

    await tester.pumpAndSettle();

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

    widget1TransientTopLeft = tester.getTopLeft(find.text('Page 1'));

    // Page 1 is back where it started.
    expect(widget1InitialTopLeft == widget1TransientTopLeft, true);
  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));

  testWidgets('test no back gesture on Android', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: const Scaffold(body: Text('Page 1')),
        routes: <String, WidgetBuilder>{
          '/next': (BuildContext context) {
            return const Scaffold(body: Text('Page 2'));
          },
        },
      ),
    );

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

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

    // Drag from left edge to invoke the gesture.
    final TestGesture gesture = await tester.startGesture(const Offset(5.0, 100.0));
    await gesture.moveBy(const Offset(400.0, 0.0));
    await tester.pump();

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

    // Page 2 didn't move
    expect(tester.getTopLeft(find.text('Page 2')), Offset.zero);
  }, variant: TargetPlatformVariant.only(TargetPlatform.android));

  testWidgets('test back gesture', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: const Scaffold(body: Text('Page 1')),
        routes: <String, WidgetBuilder>{
          '/next': (BuildContext context) {
            return const Scaffold(body: Text('Page 2'));
          },
        },
      ),
    );

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

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

    // Drag from left edge to invoke the gesture.
    final TestGesture gesture = await tester.startGesture(const Offset(5.0, 100.0));
    await gesture.moveBy(const Offset(400.0, 0.0));
    await tester.pump();

    // Page 1 is now visible.
    expect(find.text('Page 1'), isOnstage);
    expect(find.text('Page 2'), isOnstage);

    // The route widget position needs to track the finger position very exactly.
    expect(tester.getTopLeft(find.text('Page 2')), const Offset(400.0, 0.0));

    await gesture.moveBy(const Offset(-200.0, 0.0));
    await tester.pump();

    expect(tester.getTopLeft(find.text('Page 2')), const Offset(200.0, 0.0));

    await gesture.moveBy(const Offset(-100.0, 200.0));
    await tester.pump();

    expect(tester.getTopLeft(find.text('Page 2')), const Offset(100.0, 0.0));
  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));

  testWidgets('back gesture while OS changes', (WidgetTester tester) async {
    final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
      '/': (BuildContext context) => Material(
        child: TextButton(
          child: const Text('PUSH'),
          onPressed: () { Navigator.of(context).pushNamed('/b'); },
        ),
      ),
      '/b': (BuildContext context) => const Text('HELLO'),
    };
    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(platform: TargetPlatform.iOS),
        routes: routes,
      ),
    );
    await tester.tap(find.text('PUSH'));
    expect(await tester.pumpAndSettle(const Duration(minutes: 1)), 2);
    expect(find.text('PUSH'), findsNothing);
    expect(find.text('HELLO'), findsOneWidget);
    final Offset helloPosition1 = tester.getCenter(find.text('HELLO'));
    final TestGesture gesture = await tester.startGesture(const Offset(2.5, 300.0));
    await tester.pump(const Duration(milliseconds: 20));
    await gesture.moveBy(const Offset(100.0, 0.0));
    expect(find.text('PUSH'), findsNothing);
    expect(find.text('HELLO'), findsOneWidget);
    await tester.pump(const Duration(milliseconds: 20));
    expect(find.text('PUSH'), findsOneWidget);
    expect(find.text('HELLO'), findsOneWidget);
    final Offset helloPosition2 = tester.getCenter(find.text('HELLO'));
    expect(helloPosition1.dx, lessThan(helloPosition2.dx));
    expect(helloPosition1.dy, helloPosition2.dy);
    expect(Theme.of(tester.element(find.text('HELLO'))).platform, TargetPlatform.iOS);
    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(platform: TargetPlatform.android),
        routes: routes,
      ),
    );
    // Now we have to let the theme animation run through.
    // This takes three frames (including the first one above):
    //  1. Start the Theme animation. It's at t=0 so everything else is identical.
    //  2. Start any animations that are informed by the Theme, for example, the
    //     DefaultTextStyle, on the first frame that the theme is not at t=0. In
    //     this case, it's at t=1.0 of the theme animation, so this is also the
    //     frame in which the theme animation ends.
    //  3. End all the other animations.
    expect(await tester.pumpAndSettle(const Duration(minutes: 1)), 2);
    expect(Theme.of(tester.element(find.text('HELLO'))).platform, TargetPlatform.android);
    final Offset helloPosition3 = tester.getCenter(find.text('HELLO'));
    expect(helloPosition3, helloPosition2);
    expect(find.text('PUSH'), findsOneWidget);
    expect(find.text('HELLO'), findsOneWidget);
    await gesture.moveBy(const Offset(100.0, 0.0));
    await tester.pump(const Duration(milliseconds: 20));
    expect(find.text('PUSH'), findsOneWidget);
    expect(find.text('HELLO'), findsOneWidget);
    final Offset helloPosition4 = tester.getCenter(find.text('HELLO'));
    expect(helloPosition3.dx, lessThan(helloPosition4.dx));
    expect(helloPosition3.dy, helloPosition4.dy);
    await gesture.moveBy(const Offset(500.0, 0.0));
    await gesture.up();
    expect(await tester.pumpAndSettle(const Duration(minutes: 1)), 3);
    expect(find.text('PUSH'), findsOneWidget);
    expect(find.text('HELLO'), findsNothing);

    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(platform: TargetPlatform.macOS),
        routes: routes,
      ),
    );
    await tester.tap(find.text('PUSH'));
    expect(await tester.pumpAndSettle(const Duration(minutes: 1)), 2);
    expect(find.text('PUSH'), findsNothing);
    expect(find.text('HELLO'), findsOneWidget);
    final Offset helloPosition5 = tester.getCenter(find.text('HELLO'));
    await gesture.down(const Offset(2.5, 300.0));
    await tester.pump(const Duration(milliseconds: 20));
    await gesture.moveBy(const Offset(100.0, 0.0));
    expect(find.text('PUSH'), findsNothing);
    expect(find.text('HELLO'), findsOneWidget);
    await tester.pump(const Duration(milliseconds: 20));
    expect(find.text('PUSH'), findsOneWidget);
    expect(find.text('HELLO'), findsOneWidget);
    final Offset helloPosition6 = tester.getCenter(find.text('HELLO'));
    expect(helloPosition5.dx, lessThan(helloPosition6.dx));
    expect(helloPosition5.dy, helloPosition6.dy);
    expect(Theme.of(tester.element(find.text('HELLO'))).platform, TargetPlatform.macOS);
  });

  testWidgets('test no back gesture on fullscreen dialogs', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        home: Scaffold(body: Text('Page 1')),
      ),
    );

    tester.state<NavigatorState>(find.byType(Navigator)).push(MaterialPageRoute<void>(
      builder: (BuildContext context) {
        return const Scaffold(body: Text('Page 2'));
      },
      fullscreenDialog: true,
    ));
    await tester.pumpAndSettle();

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

    // Drag from left edge to invoke the gesture.
    final TestGesture gesture = await tester.startGesture(const Offset(5.0, 100.0));
    await gesture.moveBy(const Offset(400.0, 0.0));
    await tester.pump();

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

    // Page 2 didn't move
    expect(tester.getTopLeft(find.text('Page 2')), Offset.zero);
  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));

  testWidgets('test adaptable transitions switch during execution', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(
          platform: TargetPlatform.android,
          pageTransitionsTheme: const PageTransitionsTheme(
            builders: <TargetPlatform, PageTransitionsBuilder>{
              TargetPlatform.android: FadeUpwardsPageTransitionsBuilder(),
            },
          ),
        ),
        home: const Material(child: Text('Page 1')),
        routes: <String, WidgetBuilder>{
          '/next': (BuildContext context) {
            return const Material(child: Text('Page 2'));
          },
        },
      ),
    );

    final Offset widget1InitialTopLeft = tester.getTopLeft(find.text('Page 1'));

    tester.state<NavigatorState>(find.byType(Navigator)).pushNamed('/next');
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 100));

    Offset widget2TopLeft = tester.getTopLeft(find.text('Page 2'));
    final Size widget2Size = tester.getSize(find.text('Page 2'));

    // Android transition is vertical only.
    expect(widget1InitialTopLeft.dx == widget2TopLeft.dx, true);
    // Page 1 is above page 2 mid-transition.
    expect(widget1InitialTopLeft.dy < widget2TopLeft.dy, true);
    // Animation begins from the top of the page.
    expect(widget2TopLeft.dy < widget2Size.height, true);

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

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

    // Re-pump the same app but with iOS instead of Android.
    await tester.pumpWidget(
      MaterialApp(
        home: const Material(child: Text('Page 1')),
        routes: <String, WidgetBuilder>{
          '/next': (BuildContext context) {
            return const Material(child: Text('Page 2'));
          },
        },
      ),
    );

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

    Offset widget1TransientTopLeft = tester.getTopLeft(find.text('Page 1'));
    widget2TopLeft = tester.getTopLeft(find.text('Page 2'));

    // Page 1 is coming back from the left.
    expect(widget1TransientTopLeft.dx < widget1InitialTopLeft.dx, true);
    // Page 1 isn't moving vertically.
    expect(widget1TransientTopLeft.dy == widget1InitialTopLeft.dy, true);
    // iOS transition is horizontal only.
    expect(widget1InitialTopLeft.dy == widget2TopLeft.dy, true);
    // Page 2 is leaving towards the right.
    expect(widget2TopLeft.dx > widget1InitialTopLeft.dx, true);

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

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

    widget1TransientTopLeft = tester.getTopLeft(find.text('Page 1'));

    // Page 1 is back where it started.
    expect(widget1InitialTopLeft == widget1TransientTopLeft, true);
  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));

  testWidgets('test edge swipe then drop back at starting point works', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        onGenerateRoute: (RouteSettings settings) {
          return MaterialPageRoute<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));
    await gesture.moveBy(const Offset(300, 0));
    await tester.pump();
    // Bring it exactly back such that there's nothing to animate when releasing.
    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);
  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));

  testWidgets('test edge swipe then drop back at ending point works', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        onGenerateRoute: (RouteSettings settings) {
          return MaterialPageRoute<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));
    await gesture.up();
    await tester.pump();

    expect(find.text('Page 1'), isOnstage);
    expect(find.text('Page 2'), findsNothing);
  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));

  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(
      MaterialApp(
        home: Scaffold(
          key: scaffoldKey,
          body: Center(
            child: ElevatedButton(
              onPressed: () {
                Navigator.push<void>(scaffoldKey.currentContext!, MaterialPageRoute<void>(
                  builder: (BuildContext context) {
                    return const Scaffold(
                      body: 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(Scaffold))),
      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(Scaffold))).dx,
      lessThan(0),
    );
    await tester.pumpAndSettle();
    expect(find.text('push'), findsOneWidget);
    expect(
      tester.getTopLeft(find.ancestor(of: find.text('push'), matching: find.byType(Scaffold))),
      Offset.zero,
    );
    expect(find.text('route'), findsNothing);


    // Run the dismiss animation 60%, which exposes the route "push" button,
    // and then press the button. A drag dropped animation is 400ms when dropped
    // exactly halfway. It follows a curve that is very steep initially.

    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();
    await tester.pump(); // Trigger the dropped snapping animation.
    expect(
      tester.getTopLeft(find.ancestor(of: find.text('route'), matching: find.byType(Scaffold))),
      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(Scaffold))).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!, MaterialPageRoute<void>(
      builder: (BuildContext context) {
        return const Scaffold(
          body: Center(child: Text('route')),
        );
      },
    ));

    await tester.pumpAndSettle();
    expect(find.text('route'), findsOneWidget);
    expect(find.text('push'), findsNothing);
  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));

  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(
      MaterialApp(
        home: Scaffold(
          key: homeScaffoldKey,
          body: GestureDetector(
            onTap: () {
              homeTapCount += 1;
            },
          ),
        ),
      ),
    );

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

    Navigator.push<void>(homeScaffoldKey.currentContext!, MaterialPageRoute<void>(
      builder: (BuildContext context) {
        return Scaffold(
          key: pageScaffoldKey,
          appBar: AppBar(title: const Text('Page')),
          body: 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);

    // Tapping the "page" route's back button doesn't do anything either.
    await tester.tap(find.byTooltip('Back'), warnIfMissed: false);
    await tester.pumpAndSettle();
    expect(tester.getTopLeft(find.byKey(pageScaffoldKey)), const Offset(400, 0));
    expect(tester.getTopLeft(find.byKey(homeScaffoldKey)).dx, lessThan(0));
  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));

  testWidgets('After a pop caused by a back-swipe, input reaches the exposed route', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/41024

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

    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          key: homeScaffoldKey,
          body: GestureDetector(
            onTap: () {
              homeTapCount += 1;
            },
          ),
        ),
      ),
    );

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

    final ValueNotifier<bool> notifier = Navigator.of(homeScaffoldKey.currentContext!).userGestureInProgressNotifier;
    expect(notifier.value, false);

    Navigator.push<void>(homeScaffoldKey.currentContext!, MaterialPageRoute<void>(
      builder: (BuildContext context) {
        return Scaffold(
          key: pageScaffoldKey,
          appBar: AppBar(title: const Text('Page')),
          body: 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);

    // Trigger the basic iOS back-swipe dismiss transition. Drag the pushed
    // "page" route more than halfway across the screen and then release it.

    final TestGesture gesture = await tester.startGesture(const Offset(5, 300));
    await gesture.moveBy(const Offset(500, 0));
    await tester.pump();
    expect(tester.getTopLeft(find.byKey(pageScaffoldKey)), const Offset(500, 0));
    expect(tester.getTopLeft(find.byKey(homeScaffoldKey)).dx, lessThan(0));
    expect(notifier.value, true);
    await gesture.up();
    await tester.pumpAndSettle();
    expect(notifier.value, false);
    expect(find.byKey(pageScaffoldKey), findsNothing);

    // The back-swipe dismiss pop transition has finished and input on the
    // home page still works.
    await tester.tap(find.byKey(homeScaffoldKey));
    expect(homeTapCount, 2);
    expect(pageTapCount, 1);
  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));

  testWidgets('A MaterialPageRoute should slide out with CupertinoPageTransition when a compatible PageRoute is pushed on top of it', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/44864.

    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(platform: TargetPlatform.iOS),
        home: Scaffold(
          appBar: AppBar(title: const Text('Title')),
        ),
      ),
    );

    final Offset titleInitialTopLeft = tester.getTopLeft(find.text('Title'));

    tester.state<NavigatorState>(find.byType(Navigator)).push<void>(
      CupertinoPageRoute<void>(builder: (BuildContext context) => const Placeholder()),
    );

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

    final Offset titleTransientTopLeft = tester.getTopLeft(find.text('Title'));

    // Title of the first route slides to the left.
    expect(titleInitialTopLeft.dy, equals(titleTransientTopLeft.dy));
    expect(titleInitialTopLeft.dx, greaterThan(titleTransientTopLeft.dx));
  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));

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

    expect(detector.hasTransition, isFalse);
    expect(find.text('first'), findsOneWidget);

    myPages = <Page<void>>[
      MaterialPage<void>(key: pageKey, child: const Text('second')),
    ];

    await tester.pumpWidget(
      buildNavigator(
        pages: myPages,
        onPopPage: (Route<dynamic> route, dynamic result) {
          assert(false); // The test should never execute 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.text('second'), findsOneWidget);
  });

  testWidgets('MaterialPage can toggle MaintainState', (WidgetTester tester) async {
    final LocalKey pageKeyOne = UniqueKey();
    final LocalKey pageKeyTwo = UniqueKey();
    final TransitionDetector detector = TransitionDetector();
    List<Page<void>> myPages = <Page<void>>[
      MaterialPage<void>(key: pageKeyOne, maintainState: false, child: const Text('first')),
      MaterialPage<void>(key: pageKeyTwo, child: const Text('second')),
    ];
    await tester.pumpWidget(
      buildNavigator(
        pages: myPages,
        onPopPage: (Route<dynamic> route, dynamic result) {
          assert(false); // The test should never execute 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>>[
      MaterialPage<void>(key: pageKeyOne, child: const Text('first')),
      MaterialPage<void>(key: pageKeyTwo, child: const Text('second')),
    ];

    await tester.pumpWidget(
      buildNavigator(
        pages: myPages,
        onPopPage: (Route<dynamic> route, dynamic result) {
          assert(false); // The test should never execute 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('MaterialPage does not lose its state when transitioning out', (WidgetTester tester) async {
    final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
    await tester.pumpWidget(KeepsStateTestWidget(navigatorKey: navigator));
    expect(find.text('subpage'), findsOneWidget);
    expect(find.text('home'), findsNothing);

    navigator.currentState!.pop();
    await tester.pump();

    expect(find.text('subpage'), findsOneWidget);
    expect(find.text('home'), findsOneWidget);
  });

  testWidgets('MaterialPage restores its state', (WidgetTester tester) async {
    await tester.pumpWidget(
      RootRestorationScope(
        restorationId: 'root',
        child: TestDependencies(
          child: Navigator(
            onPopPage: (Route<dynamic> route, dynamic result) { return false; },
            pages: const <Page<Object?>>[
              MaterialPage<void>(
                restorationId: 'p1',
                child: TestRestorableWidget(restorationId: 'p1'),
              ),
            ],
            restorationScopeId: 'nav',
            onGenerateRoute: (RouteSettings settings) {
              return MaterialPageRoute<void>(
                settings: settings,
                builder: (BuildContext context) {
                  return TestRestorableWidget(restorationId: settings.name!);
                },
              );
            },
          ),
        ),
      ),
    );

    expect(find.text('p1'), findsOneWidget);
    expect(find.text('count: 0'), findsOneWidget);

    await tester.tap(find.text('increment'));
    await tester.pump();
    expect(find.text('count: 1'), findsOneWidget);

    tester.state<NavigatorState>(find.byType(Navigator)).restorablePushNamed('p2');
    await tester.pumpAndSettle();

    expect(find.text('p1'), findsNothing);
    expect(find.text('p2'), findsOneWidget);

    await tester.tap(find.text('increment'));
    await tester.pump();
    await tester.tap(find.text('increment'));
    await tester.pump();
    expect(find.text('count: 2'), findsOneWidget);

    await tester.restartAndRestore();

    expect(find.text('p2'), findsOneWidget);
    expect(find.text('count: 2'), findsOneWidget);

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

    expect(find.text('p1'), findsOneWidget);
    expect(find.text('count: 1'), findsOneWidget);
  });
}

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,
  required 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>>[
        DefaultMaterialLocalizations.delegate,
        DefaultWidgetsLocalizations.delegate,
      ],
      child: Directionality(
        textDirection: TextDirection.ltr,
        child: Navigator(
          key: key,
          pages: pages,
          onPopPage: onPopPage,
          transitionDelegate: transitionDelegate ?? const DefaultTransitionDelegate<dynamic>(),
        ),
      ),
    ),
  );
}

class KeepsStateTestWidget extends StatefulWidget {
  const KeepsStateTestWidget({super.key, this.navigatorKey});

  final Key? navigatorKey;

  @override
  State<KeepsStateTestWidget> createState() => _KeepsStateTestWidgetState();
}

class _KeepsStateTestWidgetState extends State<KeepsStateTestWidget> {
  String? _subpage = 'subpage';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Navigator(
        key: widget.navigatorKey,
        pages: <Page<void>>[
          const MaterialPage<void>(child: Text('home')),
          if (_subpage != null) MaterialPage<void>(child: Text(_subpage!)),
        ],
        onPopPage: (Route<dynamic> route, dynamic result) {
          if (!route.didPop(result)) {
            return false;
          }
          setState(() {
            _subpage = null;
          });
          return true;
        },
      ),
    );
  }
}

class TestRestorableWidget extends StatefulWidget {
  const TestRestorableWidget({super.key, required this.restorationId});

  final String restorationId;

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

class _TestRestorableWidgetState extends State<TestRestorableWidget> with RestorationMixin {
  @override
  String? get restorationId => widget.restorationId;

  final RestorableInt counter = RestorableInt(0);

  @override
  void restoreState(RestorationBucket? oldBucket, bool initialRestore) {
    registerForRestoration(counter, 'counter');
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        Text(widget.restorationId),
        Text('count: ${counter.value}'),
        ElevatedButton(
          onPressed: () {
            setState(() {
              counter.value++;
            });
          },
          child: const Text('increment'),
        ),
      ],
    );
  }
}

class TestDependencies extends StatelessWidget {
  const TestDependencies({required this.child, super.key});

  final Widget child;

  @override
  Widget build(BuildContext context) {
    return Directionality(
      textDirection: TextDirection.ltr,
      child: MediaQuery(
        data: MediaQueryData.fromWindow(WidgetsBinding.instance.window),
        child: child,
      ),
    );
  }
}
