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

import 'dart:collection';
import 'dart:ui';

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

import 'semantics_tester.dart';

final List<String> results = <String>[];

Set<TestRoute> routes = HashSet<TestRoute>();

class TestRoute extends Route<String?> with LocalHistoryRoute<String?> {
  TestRoute(this.name);
  final String name;

  @override
  List<OverlayEntry> get overlayEntries => _entries;

  final List<OverlayEntry> _entries = <OverlayEntry>[];

  void log(String s) {
    results.add('$name: $s');
  }

  @override
  void install() {
    log('install');
    final OverlayEntry entry = OverlayEntry(
      builder: (BuildContext context) => Container(),
      opaque: true,
    );
    _entries.add(entry);
    routes.add(this);
    super.install();
  }

  @override
  TickerFuture didPush() {
    log('didPush');
    return super.didPush();
  }

  @override
  void didAdd() {
    log('didAdd');
    super.didAdd();
  }

  @override
  void didReplace(Route<dynamic>? oldRoute) {
    expect(oldRoute, isA<TestRoute>());
    final TestRoute castRoute = oldRoute! as TestRoute;
    log('didReplace ${castRoute.name}');
    super.didReplace(castRoute);
  }

  @override
  bool didPop(String? result) {
    log('didPop $result');
    bool returnValue;
    if (returnValue = super.didPop(result)) {
      navigator!.finalizeRoute(this);
    }
    return returnValue;
  }

  @override
  void didPopNext(Route<dynamic> nextRoute) {
    expect(nextRoute, isA<TestRoute>());
    final TestRoute castRoute = nextRoute as TestRoute;
    log('didPopNext ${castRoute.name}');
    super.didPopNext(castRoute);
  }

  @override
  void didChangeNext(Route<dynamic>? nextRoute) {
    expect(nextRoute, anyOf(isNull, isA<TestRoute>()));
    final TestRoute? castRoute = nextRoute as TestRoute?;
    log('didChangeNext ${castRoute?.name}');
    super.didChangeNext(castRoute);
  }

  @override
  void dispose() {
    log('dispose');
    for (final OverlayEntry e in _entries) {
      e.dispose();
    }
    _entries.clear();
    routes.remove(this);
    super.dispose();
  }

}

Future<void> runNavigatorTest(
  WidgetTester tester,
  NavigatorState host,
  VoidCallback test,
  List<String> expectations, [
  List<String> expectationsAfterAnotherPump = const <String>[],
]) async {
  expect(host, isNotNull);
  test();
  expect(results, equals(expectations));
  results.clear();
  await tester.pump();
  expect(results, equals(expectationsAfterAnotherPump));
  results.clear();
}

void main() {
  testWidgets('Route settings', (WidgetTester tester) async {
    const RouteSettings settings = RouteSettings(name: 'A');
    expect(settings, hasOneLineDescription);
  });

  testWidgets('Route settings arguments', (WidgetTester tester) async {
    const RouteSettings settings = RouteSettings(name: 'A');
    expect(settings.arguments, isNull);

    final Object arguments = Object();
    final RouteSettings settings2 = RouteSettings(name: 'A', arguments: arguments);
    expect(settings2.arguments, same(arguments));
  });

  testWidgets('Route management - push, replace, pop sequence', (WidgetTester tester) async {
    final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Navigator(
          key: navigatorKey,
          onGenerateRoute: (_) => TestRoute('initial'),
        ),
      ),
    );
    final NavigatorState host = navigatorKey.currentState!;
    await runNavigatorTest(
      tester,
      host,
      () { },
      <String>[
        'initial: install',
        'initial: didAdd',
        'initial: didChangeNext null',
      ],
    );
    late TestRoute second;
    await runNavigatorTest(
      tester,
      host,
      () { host.push(second = TestRoute('second')); },
      <String>[ // stack is: initial, second
        'second: install',
        'second: didPush',
        'second: didChangeNext null',
        'initial: didChangeNext second',
      ],
    );
    await runNavigatorTest(
      tester,
      host,
      () { host.push(TestRoute('third')); },
      <String>[ // stack is: initial, second, third
        'third: install',
        'third: didPush',
        'third: didChangeNext null',
        'second: didChangeNext third',
      ],
    );
    await runNavigatorTest(
      tester,
      host,
      () { host.replace(oldRoute: second, newRoute: TestRoute('two')); },
      <String>[ // stack is: initial, two, third
        'two: install',
        'two: didReplace second',
        'two: didChangeNext third',
        'initial: didChangeNext two',
        'second: dispose',
      ],
    );
    await runNavigatorTest(
      tester,
      host,
      () { host.pop('hello'); },
      <String>[ // stack is: initial, two
        'third: didPop hello',
        'two: didPopNext third',
      ],
      <String>[
        'third: dispose',
      ],
    );
    await runNavigatorTest(
      tester,
      host,
      () { host.pop('good bye'); },
      <String>[ // stack is: initial
        'two: didPop good bye',
        'initial: didPopNext two',
      ],
      <String>[
        'two: dispose',
      ],
    );
    await tester.pumpWidget(Container());
    expect(results, equals(<String>['initial: dispose']));
    expect(routes.isEmpty, isTrue);
    results.clear();
  });

  testWidgets('Route management - push, remove, pop', (WidgetTester tester) async {
    final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Navigator(
          key: navigatorKey,
          onGenerateRoute: (_) => TestRoute('first'),
        ),
      ),
    );
    final NavigatorState host = navigatorKey.currentState!;
    await runNavigatorTest(
      tester,
      host,
      () { },
      <String>[
        'first: install',
        'first: didAdd',
        'first: didChangeNext null',
      ],
    );
    late TestRoute second;
    await runNavigatorTest(
      tester,
      host,
      () { host.push(second = TestRoute('second')); },
      <String>[
        'second: install',
        'second: didPush',
        'second: didChangeNext null',
        'first: didChangeNext second',
      ],
    );
    await runNavigatorTest(
      tester,
      host,
      () { host.push(TestRoute('third')); },
      <String>[
        'third: install',
        'third: didPush',
        'third: didChangeNext null',
        'second: didChangeNext third',
      ],
    );
    await runNavigatorTest(
      tester,
      host,
      () { host.removeRouteBelow(second); },
      <String>[
        'first: dispose',
      ],
    );
    await runNavigatorTest(
      tester,
      host,
      () { host.pop('good bye'); },
      <String>[
        'third: didPop good bye',
        'second: didPopNext third',
      ],
      <String>[
        'third: dispose',
      ],
    );
    await runNavigatorTest(
      tester,
      host,
      () { host.push(TestRoute('three')); },
      <String>[
        'three: install',
        'three: didPush',
        'three: didChangeNext null',
        'second: didChangeNext three',
      ],
    );
    late TestRoute four;
    await runNavigatorTest(
      tester,
      host,
      () { host.push(four = TestRoute('four')); },
      <String>[
        'four: install',
        'four: didPush',
        'four: didChangeNext null',
        'three: didChangeNext four',
      ],
    );
    await runNavigatorTest(
      tester,
      host,
      () { host.removeRouteBelow(four); },
      <String>[
        'second: didChangeNext four',
        'three: dispose',
      ],
    );
    await runNavigatorTest(
      tester,
      host,
      () { host.pop('the end'); },
      <String>[
        'four: didPop the end',
        'second: didPopNext four',
      ],
      <String>[
        'four: dispose',
      ],
    );
    await tester.pumpWidget(Container());
    expect(results, equals(<String>['second: dispose']));
    expect(routes.isEmpty, isTrue);
    results.clear();
  });

  testWidgets('Route management - push, replace, popUntil', (WidgetTester tester) async {
    final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Navigator(
          key: navigatorKey,
          onGenerateRoute: (_) => TestRoute('A'),
        ),
      ),
    );
    final NavigatorState host = navigatorKey.currentState!;
    await runNavigatorTest(
      tester,
      host,
      () { },
      <String>[
        'A: install',
        'A: didAdd',
        'A: didChangeNext null',
      ],
    );
    await runNavigatorTest(
      tester,
      host,
      () { host.push(TestRoute('B')); },
      <String>[
        'B: install',
        'B: didPush',
        'B: didChangeNext null',
        'A: didChangeNext B',
      ],
    );
    late TestRoute routeC;
    await runNavigatorTest(
      tester,
      host,
      () { host.push(routeC = TestRoute('C')); },
      <String>[
        'C: install',
        'C: didPush',
        'C: didChangeNext null',
        'B: didChangeNext C',
      ],
    );
    expect(routeC.isActive, isTrue);
    late TestRoute routeB;
    await runNavigatorTest(
      tester,
      host,
      () { host.replaceRouteBelow(anchorRoute: routeC, newRoute: routeB = TestRoute('b')); },
      <String>[
        'b: install',
        'b: didReplace B',
        'b: didChangeNext C',
        'A: didChangeNext b',
        'B: dispose',
      ],
    );
    await runNavigatorTest(
      tester,
      host,
      () { host.popUntil((Route<dynamic> route) => route == routeB); },
      <String>[
        'C: didPop null',
        'b: didPopNext C',
      ],
      <String>[
        'C: dispose',
      ],
    );
    await tester.pumpWidget(Container());
    expect(results, equals(<String>['b: dispose', 'A: dispose']));
    expect(routes.isEmpty, isTrue);
    results.clear();
  });

  testWidgets('Route localHistory - popUntil', (WidgetTester tester) async {
    final TestRoute routeA = TestRoute('A');
    routeA.addLocalHistoryEntry(LocalHistoryEntry(
      onRemove: () { routeA.log('onRemove 0'); },
    ));
    routeA.addLocalHistoryEntry(LocalHistoryEntry(
      onRemove: () { routeA.log('onRemove 1'); },
    ));
    final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Navigator(
          key: navigatorKey,
          onGenerateRoute: (_) => routeA,
        ),
      ),
    );
    final NavigatorState host = navigatorKey.currentState!;
    await runNavigatorTest(
      tester,
      host,
      () { host.popUntil((Route<dynamic> route) => !route.willHandlePopInternally); },
      <String>[
        'A: install',
        'A: didAdd',
        'A: didChangeNext null',
        'A: didPop null',
        'A: onRemove 1',
        'A: didPop null',
        'A: onRemove 0',
      ],
    );

    await runNavigatorTest(
      tester,
      host,
      () { host.popUntil((Route<dynamic> route) => !route.willHandlePopInternally); },
      <String>[
      ],
    );
    await tester.pumpWidget(Container());
    expect(routes.isEmpty, isTrue);
    results.clear();
  });

  group('PageRouteObserver', () {
    test('calls correct listeners', () {
      final RouteObserver<PageRoute<dynamic>> observer = RouteObserver<PageRoute<dynamic>>();
      final MockRouteAware pageRouteAware1 = MockRouteAware();
      final MockPageRoute route1 = MockPageRoute();
      observer.subscribe(pageRouteAware1, route1);
      expect(pageRouteAware1.didPushCount, 1);

      final MockRouteAware pageRouteAware2 = MockRouteAware();
      final MockPageRoute route2 = MockPageRoute();
      observer.didPush(route2, route1);
      expect(pageRouteAware1.didPushNextCount, 1);

      observer.subscribe(pageRouteAware2, route2);
      expect(pageRouteAware2.didPushCount, 1);

      observer.didPop(route2, route1);
      expect(pageRouteAware2.didPopCount, 1);
      expect(pageRouteAware1.didPopNextCount, 1);
    });

    test('does not call listeners for non-PageRoute', () {
      final RouteObserver<PageRoute<dynamic>> observer = RouteObserver<PageRoute<dynamic>>();
      final MockRouteAware pageRouteAware = MockRouteAware();
      final MockPageRoute pageRoute = MockPageRoute();
      final MockRoute route = MockRoute();
      observer.subscribe(pageRouteAware, pageRoute);
      expect(pageRouteAware.didPushCount, 1);

      observer.didPush(route, pageRoute);
      observer.didPop(route, pageRoute);

      expect(pageRouteAware.didPushCount, 1);
      expect(pageRouteAware.didPopCount, 0);
    });

    test('does not call listeners when already subscribed', () {
      final RouteObserver<PageRoute<dynamic>> observer = RouteObserver<PageRoute<dynamic>>();
      final MockRouteAware pageRouteAware = MockRouteAware();
      final MockPageRoute pageRoute = MockPageRoute();
      observer.subscribe(pageRouteAware, pageRoute);
      observer.subscribe(pageRouteAware, pageRoute);
      expect(pageRouteAware.didPushCount, 1);
    });

    test('does not call listeners when unsubscribed', () {
      final RouteObserver<PageRoute<dynamic>> observer = RouteObserver<PageRoute<dynamic>>();
      final MockRouteAware pageRouteAware = MockRouteAware();
      final MockPageRoute pageRoute = MockPageRoute();
      final MockPageRoute nextPageRoute = MockPageRoute();
      observer.subscribe(pageRouteAware, pageRoute);
      observer.subscribe(pageRouteAware, nextPageRoute);
      expect(pageRouteAware.didPushCount, 2);

      observer.unsubscribe(pageRouteAware);

      observer.didPush(nextPageRoute, pageRoute);
      observer.didPop(nextPageRoute, pageRoute);

      expect(pageRouteAware.didPushCount, 2);
      expect(pageRouteAware.didPopCount, 0);
    });

    test('releases reference to route when unsubscribed', () {
      final RouteObserver<PageRoute<dynamic>> observer = RouteObserver<PageRoute<dynamic>>();
      final MockRouteAware pageRouteAware = MockRouteAware();
      final MockRouteAware page2RouteAware = MockRouteAware();
      final MockPageRoute pageRoute = MockPageRoute();
      final MockPageRoute nextPageRoute = MockPageRoute();
      observer.subscribe(pageRouteAware, pageRoute);
      observer.subscribe(pageRouteAware, nextPageRoute);
      observer.subscribe(page2RouteAware, pageRoute);
      observer.subscribe(page2RouteAware, nextPageRoute);
      expect(pageRouteAware.didPushCount, 2);
      expect(page2RouteAware.didPushCount, 2);

      expect(observer.debugObservingRoute(pageRoute), true);
      expect(observer.debugObservingRoute(nextPageRoute), true);

      observer.unsubscribe(pageRouteAware);

      expect(observer.debugObservingRoute(pageRoute), true);
      expect(observer.debugObservingRoute(nextPageRoute), true);

      observer.unsubscribe(page2RouteAware);

      expect(observer.debugObservingRoute(pageRoute), false);
      expect(observer.debugObservingRoute(nextPageRoute), false);
    });
  });

  testWidgets('Can autofocus a TextField nested in a Focus in a route.', (WidgetTester tester) async {
    final TextEditingController controller = TextEditingController();
    addTearDown(controller.dispose);

    final FocusNode focusNode = FocusNode(debugLabel: 'Test Node');
    addTearDown(focusNode.dispose);

    await tester.pumpWidget(
      Material(
        child: MaterialApp(
          onGenerateRoute: (RouteSettings settings) {
            return PageRouteBuilder<void>(
              settings: settings,
              pageBuilder: (BuildContext context, Animation<double> input, Animation<double> out) {
                return Focus(
                  child: TextField(
                    autofocus: true,
                    focusNode: focusNode,
                    controller: controller,
                  ),
                );
              },
            );
          },
        ),
      ),
    );
    await tester.pump();

    expect(focusNode.hasPrimaryFocus, isTrue);
  });

  group('PageRouteBuilder', () {
    testWidgets('reverseTransitionDuration defaults to 300ms', (WidgetTester tester) async {
      // Default PageRouteBuilder reverse transition duration should be 300ms.
      await tester.pumpWidget(
        MaterialApp(
          onGenerateRoute: (RouteSettings settings) {
            return MaterialPageRoute<dynamic>(
              builder: (BuildContext context) {
                return ElevatedButton(
                  onPressed: () {
                    Navigator.of(context).push<void>(
                      PageRouteBuilder<void>(
                        settings: settings,
                        pageBuilder: (BuildContext context, Animation<double> input, Animation<double> out) {
                          return const Text('Page Two');
                        },
                      ),
                    );
                  },
                  child: const Text('Open page'),
                );
              },
            );
          },
        ),
      );

      // Open the new route.
      await tester.tap(find.byType(ElevatedButton));
      await tester.pumpAndSettle();
      expect(find.text('Open page'), findsNothing);
      expect(find.text('Page Two'), findsOneWidget);

      // Pop the new route.
      tester.state<NavigatorState>(find.byType(Navigator)).pop();
      await tester.pump();
      expect(find.text('Page Two'), findsOneWidget);

      // Text('Page Two') should be present halfway through the reverse transition.
      await tester.pump(const Duration(milliseconds: 150));
      expect(find.text('Page Two'), findsOneWidget);

      // Text('Page Two') should be present at the very end of the reverse transition.
      await tester.pump(const Duration(milliseconds: 150));
      expect(find.text('Page Two'), findsOneWidget);

      // Text('Page Two') have transitioned out after 300ms.
      await tester.pump(const Duration(milliseconds: 1));
      expect(find.text('Page Two'), findsNothing);
      expect(find.text('Open page'), findsOneWidget);
    });

    testWidgets('reverseTransitionDuration can be customized', (WidgetTester tester) async {
      await tester.pumpWidget(MaterialApp(
        onGenerateRoute: (RouteSettings settings) {
          return MaterialPageRoute<dynamic>(
            builder: (BuildContext context) {
              return ElevatedButton(
                onPressed: () {
                  Navigator.of(context).push<void>(
                    PageRouteBuilder<void>(
                      settings: settings,
                      pageBuilder: (BuildContext context, Animation<double> input, Animation<double> out) {
                        return const Text('Page Two');
                      },
                      // modified value, default PageRouteBuilder reverse transition duration should be 300ms.
                      reverseTransitionDuration: const Duration(milliseconds: 150),
                    ),
                  );
                },
                child: const Text('Open page'),
              );
            },
          );
        },
      ));

      // Open the new route.
      await tester.tap(find.byType(ElevatedButton));
      await tester.pumpAndSettle();
      expect(find.text('Open page'), findsNothing);
      expect(find.text('Page Two'), findsOneWidget);

      // Pop the new route.
      tester.state<NavigatorState>(find.byType(Navigator)).pop();
      await tester.pump();
      expect(find.text('Page Two'), findsOneWidget);

      // Text('Page Two') should be present halfway through the reverse transition.
      await tester.pump(const Duration(milliseconds: 75));
      expect(find.text('Page Two'), findsOneWidget);

      // Text('Page Two') should be present at the very end of the reverse transition.
      await tester.pump(const Duration(milliseconds: 75));
      expect(find.text('Page Two'), findsOneWidget);

      // Text('Page Two') have transitioned out after 500ms.
      await tester.pump(const Duration(milliseconds: 1));
      expect(find.text('Page Two'), findsNothing);
      expect(find.text('Open page'), findsOneWidget);
    });
  });

  group('TransitionRoute', () {
    testWidgets('secondary animation is kDismissed when next route finishes pop', (WidgetTester tester) async {
      final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
      await tester.pumpWidget(
        MaterialApp(
          navigatorKey: navigator,
          home: const Text('home'),
        ),
      );

      // Push page one, its secondary animation is kAlwaysDismissedAnimation.
      late ProxyAnimation secondaryAnimationProxyPageOne;
      late ProxyAnimation animationPageOne;
      navigator.currentState!.push(
        PageRouteBuilder<void>(
          pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
            secondaryAnimationProxyPageOne = secondaryAnimation as ProxyAnimation;
            animationPageOne = animation as ProxyAnimation;
            return const Text('Page One');
          },
        ),
      );
      await tester.pump();
      await tester.pumpAndSettle();
      final ProxyAnimation secondaryAnimationPageOne = secondaryAnimationProxyPageOne.parent! as ProxyAnimation;
      expect(animationPageOne.value, 1.0);
      expect(secondaryAnimationPageOne.parent, kAlwaysDismissedAnimation);

      // Push page two, the secondary animation of page one is the primary
      // animation of page two.
      late ProxyAnimation secondaryAnimationProxyPageTwo;
      late ProxyAnimation animationPageTwo;
      navigator.currentState!.push(
        PageRouteBuilder<void>(
          pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
            secondaryAnimationProxyPageTwo = secondaryAnimation as ProxyAnimation;
            animationPageTwo = animation as ProxyAnimation;
            return const Text('Page Two');
          },
        ),
      );
      await tester.pump();
      await tester.pumpAndSettle();
      final ProxyAnimation secondaryAnimationPageTwo = secondaryAnimationProxyPageTwo.parent! as ProxyAnimation;
      expect(animationPageTwo.value, 1.0);
      expect(secondaryAnimationPageTwo.parent, kAlwaysDismissedAnimation);
      expect(secondaryAnimationPageOne.parent, animationPageTwo.parent);

      // Pop page two, the secondary animation of page one becomes
      // kAlwaysDismissedAnimation.
      navigator.currentState!.pop();
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 100));
      expect(secondaryAnimationPageOne.parent, animationPageTwo.parent);
      await tester.pumpAndSettle();
      expect(animationPageTwo.value, 0.0);
      expect(secondaryAnimationPageOne.parent, kAlwaysDismissedAnimation);
    });

    testWidgets('secondary animation is kDismissed when next route is removed', (WidgetTester tester) async {
      final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
      await tester.pumpWidget(
        MaterialApp(
          navigatorKey: navigator,
          home: const Text('home'),
        ),
      );

      // Push page one, its secondary animation is kAlwaysDismissedAnimation.
      late ProxyAnimation secondaryAnimationProxyPageOne;
      late ProxyAnimation animationPageOne;
      navigator.currentState!.push(
        PageRouteBuilder<void>(
          pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
            secondaryAnimationProxyPageOne = secondaryAnimation as ProxyAnimation;
            animationPageOne = animation as ProxyAnimation;
            return const Text('Page One');
          },
        ),
      );
      await tester.pump();
      await tester.pumpAndSettle();
      final ProxyAnimation secondaryAnimationPageOne = secondaryAnimationProxyPageOne.parent! as ProxyAnimation;
      expect(animationPageOne.value, 1.0);
      expect(secondaryAnimationPageOne.parent, kAlwaysDismissedAnimation);

      // Push page two, the secondary animation of page one is the primary
      // animation of page two.
      late ProxyAnimation secondaryAnimationProxyPageTwo;
      late ProxyAnimation animationPageTwo;
      Route<void> secondRoute;
      navigator.currentState!.push(
        secondRoute = PageRouteBuilder<void>(
          pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
            secondaryAnimationProxyPageTwo = secondaryAnimation as ProxyAnimation;
            animationPageTwo = animation as ProxyAnimation;
            return const Text('Page Two');
          },
        ),
      );
      await tester.pump();
      await tester.pumpAndSettle();
      final ProxyAnimation secondaryAnimationPageTwo = secondaryAnimationProxyPageTwo.parent! as ProxyAnimation;
      expect(animationPageTwo.value, 1.0);
      expect(secondaryAnimationPageTwo.parent, kAlwaysDismissedAnimation);
      expect(secondaryAnimationPageOne.parent, animationPageTwo.parent);

      // Remove the second route, the secondary animation of page one is
      // kAlwaysDismissedAnimation again.
      navigator.currentState!.removeRoute(secondRoute);
      await tester.pump();
      expect(secondaryAnimationPageOne.parent, kAlwaysDismissedAnimation);
    });

    testWidgets('secondary animation is kDismissed after train hopping finishes and pop', (WidgetTester tester) async {
      final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
      await tester.pumpWidget(
        MaterialApp(
          navigatorKey: navigator,
          home: const Text('home'),
        ),
      );

      // Push page one, its secondary animation is kAlwaysDismissedAnimation.
      late ProxyAnimation secondaryAnimationProxyPageOne;
      late ProxyAnimation animationPageOne;
      navigator.currentState!.push(
        PageRouteBuilder<void>(
          pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
            secondaryAnimationProxyPageOne = secondaryAnimation as ProxyAnimation;
            animationPageOne = animation as ProxyAnimation;
            return const Text('Page One');
          },
        ),
      );
      await tester.pump();
      await tester.pumpAndSettle();
      final ProxyAnimation secondaryAnimationPageOne = secondaryAnimationProxyPageOne.parent! as ProxyAnimation;
      expect(animationPageOne.value, 1.0);
      expect(secondaryAnimationPageOne.parent, kAlwaysDismissedAnimation);

      // Push page two, the secondary animation of page one is the primary
      // animation of page two.
      late ProxyAnimation animationPageTwo;
      navigator.currentState!.push(
        PageRouteBuilder<void>(
          pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
            animationPageTwo = animation as ProxyAnimation;
            return const Text('Page Two');
          },
        ),
      );
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 100));
      expect(secondaryAnimationPageOne.parent, animationPageTwo.parent);

      // Replace with a different route while push is ongoing to trigger
      // TrainHopping.
      late ProxyAnimation animationPageThree;
      navigator.currentState!.pushReplacement(
        TestPageRouteBuilder(
          pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
            animationPageThree = animation as ProxyAnimation;
            return const Text('Page Three');
          },
        ),
      );
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 1));
      expect(secondaryAnimationPageOne.parent, isA<TrainHoppingAnimation>());
      final TrainHoppingAnimation trainHopper = secondaryAnimationPageOne.parent! as TrainHoppingAnimation;
      expect(trainHopper.currentTrain, animationPageTwo.parent);
      await tester.pump(const Duration(milliseconds: 100));
      expect(secondaryAnimationPageOne.parent, isNot(isA<TrainHoppingAnimation>()));
      expect(secondaryAnimationPageOne.parent, animationPageThree.parent);
      expect(trainHopper.currentTrain, isNull); // Has been disposed.
      await tester.pumpAndSettle();
      expect(secondaryAnimationPageOne.parent, animationPageThree.parent);

      // Pop page three.
      navigator.currentState!.pop();
      await tester.pump();
      await tester.pumpAndSettle();
      expect(secondaryAnimationPageOne.parent, kAlwaysDismissedAnimation);
    });

    testWidgets('secondary animation is kDismissed when train hopping is interrupted', (WidgetTester tester) async {
      final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
      await tester.pumpWidget(
        MaterialApp(
          navigatorKey: navigator,
          home: const Text('home'),
        ),
      );

      // Push page one, its secondary animation is kAlwaysDismissedAnimation.
      late ProxyAnimation secondaryAnimationProxyPageOne;
      late ProxyAnimation animationPageOne;
      navigator.currentState!.push(
        PageRouteBuilder<void>(
          pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
            secondaryAnimationProxyPageOne = secondaryAnimation as ProxyAnimation;
            animationPageOne = animation as ProxyAnimation;
            return const Text('Page One');
          },
        ),
      );
      await tester.pump();
      await tester.pumpAndSettle();
      final ProxyAnimation secondaryAnimationPageOne = secondaryAnimationProxyPageOne.parent! as ProxyAnimation;
      expect(animationPageOne.value, 1.0);
      expect(secondaryAnimationPageOne.parent, kAlwaysDismissedAnimation);

      // Push page two, the secondary animation of page one is the primary
      // animation of page two.
      late ProxyAnimation animationPageTwo;
      navigator.currentState!.push(
        PageRouteBuilder<void>(
          pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
            animationPageTwo = animation as ProxyAnimation;
            return const Text('Page Two');
          },
        ),
      );
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 100));
      expect(secondaryAnimationPageOne.parent, animationPageTwo.parent);

      // Replace with a different route while push is ongoing to trigger
      // TrainHopping.
      navigator.currentState!.pushReplacement(
        TestPageRouteBuilder(
          pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
            return const Text('Page Three');
          },
        ),
      );
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 10));
      expect(secondaryAnimationPageOne.parent, isA<TrainHoppingAnimation>());
      final TrainHoppingAnimation trainHopper = secondaryAnimationPageOne.parent! as TrainHoppingAnimation;
      expect(trainHopper.currentTrain, animationPageTwo.parent);

      // Pop page three while replacement push is ongoing.
      navigator.currentState!.pop();
      await tester.pump();
      expect(secondaryAnimationPageOne.parent, isA<TrainHoppingAnimation>());
      final TrainHoppingAnimation trainHopper2 = secondaryAnimationPageOne.parent! as TrainHoppingAnimation;
      expect(trainHopper2.currentTrain, animationPageTwo.parent);
      expect(trainHopper.currentTrain, isNull); // Has been disposed.
      await tester.pumpAndSettle();
      expect(secondaryAnimationPageOne.parent, kAlwaysDismissedAnimation);
      expect(trainHopper2.currentTrain, isNull); // Has been disposed.
    });

    testWidgets('secondary animation is triggered when pop initial route', (WidgetTester tester) async {
      final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
      late Animation<double> secondaryAnimationOfRouteOne;
      late Animation<double> primaryAnimationOfRouteTwo;
      await tester.pumpWidget(
        MaterialApp(
          navigatorKey: navigator,
          onGenerateRoute: (RouteSettings settings) {
            return PageRouteBuilder<void>(
              settings: settings,
              pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
                if (settings.name == '/') {
                  secondaryAnimationOfRouteOne = secondaryAnimation;
                } else {
                  primaryAnimationOfRouteTwo = animation;
                }
                return const Text('Page');
              },
            );
          },
          initialRoute: '/a',
        ),
      );
      // The secondary animation of the bottom route should be chained with the
      // primary animation of top most route.
      expect(secondaryAnimationOfRouteOne.value, 1.0);
      expect(secondaryAnimationOfRouteOne.value, primaryAnimationOfRouteTwo.value);
      // Pops the top most route and verifies two routes are still chained.
      navigator.currentState!.pop();
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 30));
      expect(secondaryAnimationOfRouteOne.value, 0.9);
      expect(secondaryAnimationOfRouteOne.value, primaryAnimationOfRouteTwo.value);
      await tester.pumpAndSettle();
      expect(secondaryAnimationOfRouteOne.value, 0.0);
      expect(secondaryAnimationOfRouteOne.value, primaryAnimationOfRouteTwo.value);
    });

    testWidgets('showGeneralDialog handles transparent barrier color',
    // TODO(polina-c): remove when fixed https://github.com/flutter/flutter/issues/145600 [leak-tracking-opt-in]
    experimentalLeakTesting: LeakTesting.settings.withTracked(classes: <String>['CurvedAnimation']),
    (WidgetTester tester) async {
      await tester.pumpWidget(MaterialApp(
        home: Builder(
          builder: (BuildContext context) {
            return ElevatedButton(
              onPressed: () {
                showGeneralDialog<void>(
                  context: context,
                  barrierDismissible: true,
                  barrierLabel: 'barrier_label',
                  barrierColor: const Color(0x00000000),
                  transitionDuration: Duration.zero,
                  pageBuilder: (BuildContext innerContext, _, __) {
                    return const SizedBox();
                  },
                );
              },
              child: const Text('Show Dialog'),
            );
          },
        ),
      ));

      // Open the dialog.
      await tester.tap(find.byType(ElevatedButton));
      await tester.pump();
      expect(find.byType(ModalBarrier), findsNWidgets(2));

      // Close the dialog.
      await tester.tapAt(Offset.zero);
      await tester.pump();
      expect(find.byType(ModalBarrier), findsNWidgets(1));
    });

    testWidgets('showGeneralDialog adds non-dismissible barrier when barrierDismissible is false', (WidgetTester tester) async {
      await tester.pumpWidget(MaterialApp(
        home: Builder(
          builder: (BuildContext context) {
            return ElevatedButton(
              onPressed: () {
                showGeneralDialog<void>(
                  context: context,
                  transitionDuration: Duration.zero,
                  pageBuilder: (BuildContext innerContext, _, __) {
                    return const SizedBox();
                  },
                );
              },
              child: const Text('Show Dialog'),
            );
          },
        ),
      ));

      // Open the dialog.
      await tester.tap(find.byType(ElevatedButton));
      await tester.pump();
      expect(find.byType(ModalBarrier), findsNWidgets(2));
      final ModalBarrier barrier = find.byType(ModalBarrier).evaluate().last.widget as ModalBarrier;
      expect(barrier.dismissible, isFalse);

      // Close the dialog.
      final StatefulElement navigatorElement = find.byType(Navigator).evaluate().last as StatefulElement;
      final NavigatorState navigatorState = navigatorElement.state as NavigatorState;
      navigatorState.pop();
      await tester.pumpAndSettle();
      expect(find.byType(ModalBarrier), findsNWidgets(1));
    });

    testWidgets('showGeneralDialog uses null as a barrierLabel by default', (WidgetTester tester) async {
      await tester.pumpWidget(MaterialApp(
        home: Builder(
          builder: (BuildContext context) {
            return ElevatedButton(
              onPressed: () {
                showGeneralDialog<void>(
                  context: context,
                  transitionDuration: Duration.zero,
                  pageBuilder: (BuildContext innerContext, _, __) {
                    return const SizedBox();
                  },
                );
              },
              child: const Text('Show Dialog'),
            );
          },
        ),
      ));

      // Open the dialog.
      await tester.tap(find.byType(ElevatedButton));
      await tester.pump();
      expect(find.byType(ModalBarrier), findsNWidgets(2));
      final ModalBarrier barrier = find.byType(ModalBarrier).evaluate().last.widget as ModalBarrier;
      expect(barrier.semanticsLabel, same(null));

      // Close the dialog.
      final StatefulElement navigatorElement = find.byType(Navigator).evaluate().last as StatefulElement;
      final NavigatorState navigatorState = navigatorElement.state as NavigatorState;
      navigatorState.pop();
      await tester.pumpAndSettle();
      expect(find.byType(ModalBarrier), findsNWidgets(1));
    });

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

      await tester.pumpWidget(MaterialApp(
        navigatorObservers: <NavigatorObserver>[rootObserver],
        home: Navigator(
          observers: <NavigatorObserver>[nestedObserver],
          onGenerateRoute: (RouteSettings settings) {
            return MaterialPageRoute<dynamic>(
              builder: (BuildContext context) {
                return ElevatedButton(
                  onPressed: () {
                    showGeneralDialog<void>(
                      context: context,
                      transitionDuration: Duration.zero,
                      pageBuilder: (BuildContext innerContext, _, __) {
                        return const SizedBox();
                      },
                    );
                  },
                  child: const Text('Show Dialog'),
                );
              },
            );
          },
        ),
      ));

      // Open the dialog.
      await tester.tap(find.byType(ElevatedButton));

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

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

      await tester.pumpWidget(MaterialApp(
        navigatorObservers: <NavigatorObserver>[rootObserver],
        home: Navigator(
          observers: <NavigatorObserver>[nestedObserver],
          onGenerateRoute: (RouteSettings settings) {
            return MaterialPageRoute<dynamic>(
              builder: (BuildContext context) {
                return ElevatedButton(
                  onPressed: () {
                    showGeneralDialog<void>(
                      useRootNavigator: false,
                      context: context,
                      transitionDuration: Duration.zero,
                      pageBuilder: (BuildContext innerContext, _, __) {
                        return const SizedBox();
                      },
                    );
                  },
                  child: const Text('Show Dialog'),
                );
              },
            );
          },
        ),
      ));

      // Open the dialog.
      await tester.tap(find.byType(ElevatedButton));

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

    testWidgets('showGeneralDialog default argument values', (WidgetTester tester) async {
      final DialogObserver rootObserver = DialogObserver();

      await tester.pumpWidget(MaterialApp(
        navigatorObservers: <NavigatorObserver>[rootObserver],
        home: Navigator(
          onGenerateRoute: (RouteSettings settings) {
            return MaterialPageRoute<dynamic>(
              builder: (BuildContext context) {
                return ElevatedButton(
                  onPressed: () {
                    showGeneralDialog<void>(
                      context: context,
                      pageBuilder: (BuildContext innerContext, _, __) {
                        return const SizedBox();
                      },
                    );
                  },
                  child: const Text('Show Dialog'),
                );
              },
            );
          },
        ),
      ));

      // Open the dialog.
      await tester.tap(find.byType(ElevatedButton));
      expect(rootObserver.dialogRoutes.length, equals(1));
      final ModalRoute<dynamic> route = rootObserver.dialogRoutes.last;
      expect(route.barrierDismissible, isNotNull);
      expect(route.barrierColor, isNotNull);
      expect(route.transitionDuration, isNotNull);
    });

    group('showGeneralDialog avoids overlapping display features', () {
      testWidgets('positioning with anchorPoint', (WidgetTester tester) async {
        await tester.pumpWidget(
          MaterialApp(
            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'));

        showGeneralDialog<void>(
          context: context,
          pageBuilder: (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(
          MaterialApp(
            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'));

        showGeneralDialog<void>(
          context: context,
          pageBuilder: (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(
          MaterialApp(
            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'));

        showGeneralDialog<void>(
          context: context,
          pageBuilder: (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));
      });
    });

    testWidgets('reverseTransitionDuration defaults to transitionDuration', (WidgetTester tester) async {
      final GlobalKey containerKey = GlobalKey();

      // Default MaterialPageRoute transition duration should be 300ms.
      await tester.pumpWidget(MaterialApp(
        onGenerateRoute: (RouteSettings settings) {
          return MaterialPageRoute<dynamic>(
            builder: (BuildContext context) {
              return ElevatedButton(
                onPressed: () {
                  Navigator.of(context).push<void>(
                    MaterialPageRoute<void>(
                      builder: (BuildContext innerContext) {
                        return Container(
                          key: containerKey,
                          color: Colors.green,
                        );
                      },
                    ),
                  );
                },
                child: const Text('Open page'),
              );
            },
          );
        },
      ));

      // Open the new route.
      await tester.tap(find.byType(ElevatedButton));
      await tester.pumpAndSettle();
      expect(find.text('Open page'), findsNothing);
      expect(find.byKey(containerKey), findsOneWidget);

      // Pop the new route.
      tester.state<NavigatorState>(find.byType(Navigator)).pop();
      await tester.pump();
      expect(find.byKey(containerKey), findsOneWidget);

      // Container should be present halfway through the transition.
      await tester.pump(const Duration(milliseconds: 150));
      expect(find.byKey(containerKey), findsOneWidget);

      // Container should be present at the very end of the transition.
      await tester.pump(const Duration(milliseconds: 150));
      expect(find.byKey(containerKey), findsOneWidget);

      // Container have transitioned out after 300ms.
      await tester.pump(const Duration(milliseconds: 1));
      expect(find.byKey(containerKey), findsNothing);
    });

    testWidgets('reverseTransitionDuration can be customized', (WidgetTester tester) async {
      final GlobalKey containerKey = GlobalKey();
      await tester.pumpWidget(MaterialApp(
        onGenerateRoute: (RouteSettings settings) {
          return MaterialPageRoute<dynamic>(
            builder: (BuildContext context) {
              return ElevatedButton(
                onPressed: () {
                  Navigator.of(context).push<void>(
                    ModifiedReverseTransitionDurationRoute<void>(
                      builder: (BuildContext innerContext) {
                        return Container(
                          key: containerKey,
                          color: Colors.green,
                        );
                      },
                      // modified value, default MaterialPageRoute transition duration should be 300ms.
                      reverseTransitionDuration: const Duration(milliseconds: 150),
                    ),
                  );
                },
                child: const Text('Open page'),
              );
            },
          );
        },
      ));

      // Open the new route.
      await tester.tap(find.byType(ElevatedButton));
      await tester.pumpAndSettle();
      expect(find.text('Open page'), findsNothing);
      expect(find.byKey(containerKey), findsOneWidget);

      // Pop the new route.
      tester.state<NavigatorState>(find.byType(Navigator)).pop();
      await tester.pump();
      expect(find.byKey(containerKey), findsOneWidget);

      // Container should be present halfway through the transition.
      await tester.pump(const Duration(milliseconds: 75));
      expect(find.byKey(containerKey), findsOneWidget);

      // Container should be present at the very end of the transition.
      await tester.pump(const Duration(milliseconds: 75));
      expect(find.byKey(containerKey), findsOneWidget);

      // Container have transitioned out after 150ms.
      await tester.pump(const Duration(milliseconds: 1));
      expect(find.byKey(containerKey), findsNothing);
    });

    testWidgets('custom reverseTransitionDuration does not result in interrupted animations', (WidgetTester tester) async {
      final GlobalKey containerKey = GlobalKey();
      await tester.pumpWidget(MaterialApp(
        theme: ThemeData(
          pageTransitionsTheme: const PageTransitionsTheme(
            builders: <TargetPlatform, PageTransitionsBuilder>{
              TargetPlatform.android: FadeUpwardsPageTransitionsBuilder(), // use a fade transition
            },
          ),
        ),
        onGenerateRoute: (RouteSettings settings) {
          return MaterialPageRoute<dynamic>(
            builder: (BuildContext context) {
              return ElevatedButton(
                onPressed: () {
                  Navigator.of(context).push<void>(
                    ModifiedReverseTransitionDurationRoute<void>(
                      builder: (BuildContext innerContext) {
                        return Container(
                          key: containerKey,
                          color: Colors.green,
                        );
                      },
                      // modified value, default MaterialPageRoute transition duration should be 300ms.
                      reverseTransitionDuration: const Duration(milliseconds: 150),
                    ),
                  );
                },
                child: const Text('Open page'),
              );
            },
          );
        },
      ));

      // Open the new route.
      await tester.tap(find.byType(ElevatedButton));
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 200)); // jump partway through the forward transition
      expect(find.byKey(containerKey), findsOneWidget);

      // Gets the opacity of the fade transition while animating forwards.
      final double topFadeTransitionOpacity = _getOpacity(containerKey, tester);

      // Pop the new route mid-transition.
      tester.state<NavigatorState>(find.byType(Navigator)).pop();
      await tester.pump();

      // Transition should not jump. In other words, the fade transition
      // opacity before and after animation changes directions should remain
      // the same.
      expect(_getOpacity(containerKey, tester), topFadeTransitionOpacity);

      // Reverse transition duration should be:
      // Forward transition elapsed time: 200ms / 300ms = 2 / 3
      // Reverse transition remaining time: 150ms * 2 / 3 = 100ms

      // Container should be present at the very end of the transition.
      await tester.pump(const Duration(milliseconds: 100));
      expect(find.byKey(containerKey), findsOneWidget);

      // Container have transitioned out after 100ms.
      await tester.pump(const Duration(milliseconds: 1));
      expect(find.byKey(containerKey), findsNothing);
    });
  });

  group('ModalRoute', () {
    testWidgets('default barrierCurve', (WidgetTester tester) async {
      await tester.pumpWidget(MaterialApp(
        home: Material(
          child: Builder(
            builder: (BuildContext context) {
              return Center(
                child: ElevatedButton(
                  child: const Text('X'),
                  onPressed: () {
                    Navigator.of(context).push<void>(
                      _TestDialogRouteWithCustomBarrierCurve<void>(
                        child: const Text('Hello World'),
                      ),
                    );
                  },
                ),
              );
            },
          ),
        ),
      ));

      final CurveTween defaultBarrierTween = CurveTween(curve: Curves.ease);
      int getExpectedBarrierTweenAlphaValue(double t) {
        return Color.getAlphaFromOpacity(defaultBarrierTween.transform(t));
      }

      await tester.tap(find.text('X'));
      await tester.pump();
      final Finder animatedModalBarrier = find.byType(AnimatedModalBarrier);
      expect(animatedModalBarrier, findsOneWidget);

      Animation<Color?> modalBarrierAnimation;
      modalBarrierAnimation = tester.widget<AnimatedModalBarrier>(animatedModalBarrier).color;
      expect(modalBarrierAnimation.value, Colors.transparent);

      await tester.pump(const Duration(milliseconds: 25));
      modalBarrierAnimation = tester.widget<AnimatedModalBarrier>(animatedModalBarrier).color;
      expect(
        modalBarrierAnimation.value!.alpha,
        closeTo(getExpectedBarrierTweenAlphaValue(0.25), 1),
      );

      await tester.pump(const Duration(milliseconds: 25));
      modalBarrierAnimation = tester.widget<AnimatedModalBarrier>(animatedModalBarrier).color;
      expect(
        modalBarrierAnimation.value!.alpha,
        closeTo(getExpectedBarrierTweenAlphaValue(0.50), 1),
      );

      await tester.pump(const Duration(milliseconds: 25));
      modalBarrierAnimation = tester.widget<AnimatedModalBarrier>(animatedModalBarrier).color;
      expect(
        modalBarrierAnimation.value!.alpha,
        closeTo(getExpectedBarrierTweenAlphaValue(0.75), 1),
      );

      await tester.pumpAndSettle();
      modalBarrierAnimation = tester.widget<AnimatedModalBarrier>(animatedModalBarrier).color;
      expect(modalBarrierAnimation.value, Colors.black);
    });

    testWidgets('custom barrierCurve', (WidgetTester tester) async {
      await tester.pumpWidget(MaterialApp(
        home: Material(
          child: Builder(
            builder: (BuildContext context) {
              return Center(
                child: ElevatedButton(
                  child: const Text('X'),
                  onPressed: () {
                    Navigator.of(context).push<void>(
                      _TestDialogRouteWithCustomBarrierCurve<void>(
                        child: const Text('Hello World'),
                        barrierCurve: Curves.linear,
                      ),
                    );
                  },
                ),
              );
            },
          ),
        ),
      ));

      final CurveTween customBarrierTween = CurveTween(curve: Curves.linear);
      int getExpectedBarrierTweenAlphaValue(double t) {
        return Color.getAlphaFromOpacity(customBarrierTween.transform(t));
      }

      await tester.tap(find.text('X'));
      await tester.pump();
      final Finder animatedModalBarrier = find.byType(AnimatedModalBarrier);
      expect(animatedModalBarrier, findsOneWidget);

      Animation<Color?> modalBarrierAnimation;
      modalBarrierAnimation = tester.widget<AnimatedModalBarrier>(animatedModalBarrier).color;
      expect(modalBarrierAnimation.value, Colors.transparent);

      await tester.pump(const Duration(milliseconds: 25));
      modalBarrierAnimation = tester.widget<AnimatedModalBarrier>(animatedModalBarrier).color;
      expect(
        modalBarrierAnimation.value!.alpha,
        closeTo(getExpectedBarrierTweenAlphaValue(0.25), 1),
      );

      await tester.pump(const Duration(milliseconds: 25));
      modalBarrierAnimation = tester.widget<AnimatedModalBarrier>(animatedModalBarrier).color;
      expect(
        modalBarrierAnimation.value!.alpha,
        closeTo(getExpectedBarrierTweenAlphaValue(0.50), 1),
      );

      await tester.pump(const Duration(milliseconds: 25));
      modalBarrierAnimation = tester.widget<AnimatedModalBarrier>(animatedModalBarrier).color;
      expect(
        modalBarrierAnimation.value!.alpha,
        closeTo(getExpectedBarrierTweenAlphaValue(0.75), 1),
      );

      await tester.pumpAndSettle();
      modalBarrierAnimation = tester.widget<AnimatedModalBarrier>(animatedModalBarrier).color;
      expect(modalBarrierAnimation.value, Colors.black);
    });

    testWidgets('white barrierColor', (WidgetTester tester) async {
      await tester.pumpWidget(MaterialApp(
        home: Material(
          child: Builder(
            builder: (BuildContext context) {
              return Center(
                child: ElevatedButton(
                  child: const Text('X'),
                  onPressed: () {
                    Navigator.of(context).push<void>(
                      _TestDialogRouteWithCustomBarrierCurve<void>(
                        child: const Text('Hello World'),
                        barrierColor: Colors.white,
                      ),
                    );
                  },
                ),
              );
            },
          ),
        ),
      ));

      final CurveTween defaultBarrierTween = CurveTween(curve: Curves.ease);
      int getExpectedBarrierTweenAlphaValue(double t) {
        return Color.getAlphaFromOpacity(defaultBarrierTween.transform(t));
      }

      await tester.tap(find.text('X'));
      await tester.pump();
      final Finder animatedModalBarrier = find.byType(AnimatedModalBarrier);
      expect(animatedModalBarrier, findsOneWidget);

      Animation<Color?> modalBarrierAnimation;
      modalBarrierAnimation = tester.widget<AnimatedModalBarrier>(animatedModalBarrier).color;
      expect(modalBarrierAnimation.value, Colors.white.withOpacity(0));

      await tester.pump(const Duration(milliseconds: 25));
      modalBarrierAnimation = tester.widget<AnimatedModalBarrier>(animatedModalBarrier).color;
      expect(
        modalBarrierAnimation.value!.alpha,
        closeTo(getExpectedBarrierTweenAlphaValue(0.25), 1),
      );

      await tester.pump(const Duration(milliseconds: 25));
      modalBarrierAnimation = tester.widget<AnimatedModalBarrier>(animatedModalBarrier).color;
      expect(
        modalBarrierAnimation.value!.alpha,
        closeTo(getExpectedBarrierTweenAlphaValue(0.50), 1),
      );

      await tester.pump(const Duration(milliseconds: 25));
      modalBarrierAnimation = tester.widget<AnimatedModalBarrier>(animatedModalBarrier).color;
      expect(
        modalBarrierAnimation.value!.alpha,
        closeTo(getExpectedBarrierTweenAlphaValue(0.75), 1),
      );

      await tester.pumpAndSettle();
      modalBarrierAnimation = tester.widget<AnimatedModalBarrier>(animatedModalBarrier).color;
      expect(modalBarrierAnimation.value, Colors.white);
    });

    testWidgets('modal route semantics order', (WidgetTester tester) async {
      // Regression test for https://github.com/flutter/flutter/issues/46625.
      final SemanticsTester semantics = SemanticsTester(tester);
      await tester.pumpWidget(MaterialApp(
        home: Material(
          child: Builder(
            builder: (BuildContext context) {
              return Center(
                child: ElevatedButton(
                  child: const Text('X'),
                  onPressed: () {
                    Navigator.of(context).push<void>(
                      _TestDialogRouteWithCustomBarrierCurve<void>(
                        child: const Text('Hello World'),
                        barrierLabel: 'test label',
                        barrierCurve: Curves.linear,
                      ),
                    );
                  },
                ),
              );
            },
          ),
        ),
      ));

      await tester.tap(find.text('X'));
      await tester.pumpAndSettle();
      expect(find.text('Hello World'), findsOneWidget);

      final TestSemantics expectedSemantics = TestSemantics.root(
        children: <TestSemantics>[
          TestSemantics.rootChild(
            id: 1,
            rect: TestSemantics.fullScreen,
            children: <TestSemantics>[
              TestSemantics(
                id: 6,
                rect: TestSemantics.fullScreen,
                children: <TestSemantics>[
                  TestSemantics(
                    id: 7,
                    rect: TestSemantics.fullScreen,
                    flags: <SemanticsFlag>[SemanticsFlag.scopesRoute],
                    children: <TestSemantics>[
                      TestSemantics(
                        id: 8,
                        label: 'Hello World',
                        rect: TestSemantics.fullScreen,
                        textDirection: TextDirection.ltr,
                      ),
                    ],
                  ),
                ],
              ),
              // Modal barrier is put after modal scope
              TestSemantics(
                id: 5,
                rect: TestSemantics.fullScreen,
                actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.dismiss],
                label: 'test label',
                textDirection: TextDirection.ltr,
              ),
            ],
          ),
        ],
      )
      ;

      expect(semantics, hasSemantics(expectedSemantics));
      semantics.dispose();
    }, variant: const TargetPlatformVariant(<TargetPlatform>{TargetPlatform.iOS}));

    testWidgets('focus traversal is correct when popping multiple pages simultaneously', (WidgetTester tester) async {
      // Regression test: https://github.com/flutter/flutter/issues/48903
      final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
      await tester.pumpWidget(MaterialApp(
        navigatorKey: navigatorKey,
        home: const Text('dummy1'),
      ));
      final Element textOnPageOne = tester.element(find.text('dummy1'));
      final FocusScopeNode focusNodeOnPageOne = FocusScope.of(textOnPageOne);
      expect(focusNodeOnPageOne.hasFocus, isTrue);

      // Pushes one page.
      navigatorKey.currentState!.push<void>(
        MaterialPageRoute<void>(
          builder: (BuildContext context) => const Text('dummy2'),
        ),
      );
      await tester.pumpAndSettle();

      final Element textOnPageTwo = tester.element(find.text('dummy2'));
      final FocusScopeNode focusNodeOnPageTwo = FocusScope.of(textOnPageTwo);
      // The focus should be on second page.
      expect(focusNodeOnPageOne.hasFocus, isFalse);
      expect(focusNodeOnPageTwo.hasFocus, isTrue);

      // Pushes another page.
      navigatorKey.currentState!.push<void>(
        MaterialPageRoute<void>(
          builder: (BuildContext context) => const Text('dummy3'),
        ),
      );
      await tester.pumpAndSettle();
      final Element textOnPageThree = tester.element(find.text('dummy3'));
      final FocusScopeNode focusNodeOnPageThree = FocusScope.of(textOnPageThree);
      // The focus should be on third page.
      expect(focusNodeOnPageOne.hasFocus, isFalse);
      expect(focusNodeOnPageTwo.hasFocus, isFalse);
      expect(focusNodeOnPageThree.hasFocus, isTrue);

      // Pops two pages simultaneously.
      navigatorKey.currentState!.popUntil((Route<void> route) => route.isFirst);
      await tester.pumpAndSettle();
      // It should refocus page one after pops.
      expect(focusNodeOnPageOne.hasFocus, isTrue);
    });

    testWidgets('focus traversal is correct when popping multiple pages simultaneously - with focused children', (WidgetTester tester) async {
      // Regression test: https://github.com/flutter/flutter/issues/48903
      final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
      await tester.pumpWidget(MaterialApp(
        navigatorKey: navigatorKey,
        home: const Text('dummy1'),
      ));
      final Element textOnPageOne = tester.element(find.text('dummy1'));
      final FocusScopeNode focusNodeOnPageOne = FocusScope.of(textOnPageOne);
      expect(focusNodeOnPageOne.hasFocus, isTrue);

      // Pushes one page.
      navigatorKey.currentState!.push<void>(
        MaterialPageRoute<void>(
          builder: (BuildContext context) => const Material(child: TextField()),
        ),
      );
      await tester.pumpAndSettle();

      final Element textOnPageTwo = tester.element(find.byType(TextField));
      final FocusScopeNode focusNodeOnPageTwo = FocusScope.of(textOnPageTwo);
      // The focus should be on second page.
      expect(focusNodeOnPageOne.hasFocus, isFalse);
      expect(focusNodeOnPageTwo.hasFocus, isTrue);

      // Move the focus to another node.
      focusNodeOnPageTwo.nextFocus();
      await tester.pumpAndSettle();
      expect(focusNodeOnPageTwo.hasFocus, isTrue);
      expect(focusNodeOnPageTwo.hasPrimaryFocus, isFalse);

      // Pushes another page.
      navigatorKey.currentState!.push<void>(
        MaterialPageRoute<void>(
          builder: (BuildContext context) => const Text('dummy3'),
        ),
      );
      await tester.pumpAndSettle();
      final Element textOnPageThree = tester.element(find.text('dummy3'));
      final FocusScopeNode focusNodeOnPageThree = FocusScope.of(textOnPageThree);
      // The focus should be on third page.
      expect(focusNodeOnPageOne.hasFocus, isFalse);
      expect(focusNodeOnPageTwo.hasFocus, isFalse);
      expect(focusNodeOnPageThree.hasFocus, isTrue);

      // Pops two pages simultaneously.
      navigatorKey.currentState!.popUntil((Route<void> route) => route.isFirst);
      await tester.pumpAndSettle();
      // It should refocus page one after pops.
      expect(focusNodeOnPageOne.hasFocus, isTrue);
    });

    testWidgets('child with local history can be disposed', (WidgetTester tester) async {
      // Regression test: https://github.com/flutter/flutter/issues/52478
      await tester.pumpWidget(const MaterialApp(
        home: WidgetWithLocalHistory(),
      ));

      final WidgetWithLocalHistoryState state = tester.state(find.byType(WidgetWithLocalHistory));
      state.addLocalHistory();
      // Waits for modal route to update its internal state;
      await tester.pump();
      // Pumps a new widget to dispose WidgetWithLocalHistory. This should cause
      // it to remove the local history entry from modal route during
      // finalizeTree.
      await tester.pumpWidget(const MaterialApp(
        home: Text('dummy'),
      ));
      // Waits for modal route to update its internal state;
      await tester.pump();
      expect(tester.takeException(), null);
    });

    testWidgets('child with no local history can be disposed', (WidgetTester tester) async {
      await tester.pumpWidget(const MaterialApp(
        home: WidgetWithNoLocalHistory(),
      ));

      final WidgetWithNoLocalHistoryState state = tester.state(find.byType(WidgetWithNoLocalHistory));
      state.addLocalHistory();
      // Waits for modal route to update its internal state;
      await tester.pump();
      // Pumps a new widget to dispose WidgetWithNoLocalHistory. This should cause
      // it to remove the local history entry from modal route during
      // finalizeTree.
      await tester.pumpWidget(const MaterialApp(
        home: Text('dummy'),
      ));
      await tester.pump();
      expect(tester.takeException(), null);
    });
  });

  testWidgets('can be dismissed with escape keyboard shortcut', (WidgetTester tester) async {
    final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
    await tester.pumpWidget(MaterialApp(
      navigatorKey: navigatorKey,
      home: const Text('dummy1'),
    ));
    final Element textOnPageOne = tester.element(find.text('dummy1'));

    // Show a simple dialog
    showDialog<void>(
      context: textOnPageOne,
      builder: (BuildContext context) => const Text('dialog1'),
    );
    await tester.pumpAndSettle();
    expect(find.text('dialog1'), findsOneWidget);

    // Try to dismiss the dialog with the shortcut key
    await tester.sendKeyEvent(LogicalKeyboardKey.escape);
    await tester.pumpAndSettle();
    expect(find.text('dialog1'), findsNothing);
  });

  testWidgets('can not be dismissed with escape keyboard shortcut if barrier not dismissible', (WidgetTester tester) async {
    final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
    await tester.pumpWidget(MaterialApp(
      navigatorKey: navigatorKey,
      home: const Text('dummy1'),
    ));
    final Element textOnPageOne = tester.element(find.text('dummy1'));

    // Show a simple dialog
    showDialog<void>(
      context: textOnPageOne,
      barrierDismissible: false,
      builder: (BuildContext context) => const Text('dialog1'),
    );
    await tester.pumpAndSettle();
    expect(find.text('dialog1'), findsOneWidget);

    // Try to dismiss the dialog with the shortcut key
    await tester.sendKeyEvent(LogicalKeyboardKey.escape);
    await tester.pumpAndSettle();
    expect(find.text('dialog1'), findsOneWidget);
  });

  testWidgets('ModalRoute.of works for void routes', (WidgetTester tester) async {
    final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
    await tester.pumpWidget(MaterialApp(
      navigatorKey: navigatorKey,
      home: const Text('home'),
    ));
    expect(find.text('page2'), findsNothing);

    navigatorKey.currentState!.push<void>(MaterialPageRoute<void>(
      builder: (BuildContext context) {
        return const Text('page2');
      },
    ));

    await tester.pumpAndSettle();
    expect(find.text('page2'), findsOneWidget);

    final ModalRoute<void>? parentRoute = ModalRoute.of<void>(tester.element(find.text('page2')));
    expect(parentRoute, isNotNull);
    expect(parentRoute, isA<MaterialPageRoute<void>>());
  });

  testWidgets('RawDialogRoute is state restorable', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        restorationScopeId: 'app',
        home: _RestorableDialogTestWidget(),
      ),
    );

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

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

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

    await tester.restartAndRestore();

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

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

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

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

double _getOpacity(GlobalKey key, WidgetTester tester) {
  final Finder finder = find.ancestor(
    of: find.byKey(key),
    matching: find.byType(FadeTransition),
  );
  return tester.widgetList(finder).fold<double>(1.0, (double a, Widget widget) {
    final FadeTransition transition = widget as FadeTransition;
    return a * transition.opacity.value;
  });
}

class ModifiedReverseTransitionDurationRoute<T> extends MaterialPageRoute<T> {
  ModifiedReverseTransitionDurationRoute({
    required super.builder,
    super.settings,
    required this.reverseTransitionDuration,
    super.fullscreenDialog,
  });

  @override
  final Duration reverseTransitionDuration;
}

class MockPageRoute extends Fake implements PageRoute<dynamic> { }

class MockRoute extends Fake implements Route<dynamic> { }

class MockRouteAware extends Fake implements RouteAware {
  int didPushCount = 0;
  int didPushNextCount = 0;
  int didPopCount = 0;
  int didPopNextCount = 0;

  @override
  void didPush() {
    didPushCount += 1;
  }

  @override
  void didPushNext() {
    didPushNextCount += 1;
  }

  @override
  void didPop() {
    didPopCount += 1;
  }

  @override
  void didPopNext() {
    didPopNextCount += 1;
  }
}

class TestPageRouteBuilder extends PageRouteBuilder<void> {
  TestPageRouteBuilder({required super.pageBuilder});

  @override
  Animation<double> createAnimation() {
    return CurvedAnimation(parent: super.createAnimation(), curve: Curves.easeOutExpo);
  }
}

class DialogObserver extends NavigatorObserver {
  final List<ModalRoute<dynamic>> dialogRoutes = <ModalRoute<dynamic>>[];
  int dialogCount = 0;

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

  @override
  void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
    if (route is RawDialogRoute) {
      dialogRoutes.removeLast();
      dialogCount--;
    }
    super.didPop(route, previousRoute);
  }
}

class _TestDialogRouteWithCustomBarrierCurve<T> extends PopupRoute<T> {
  _TestDialogRouteWithCustomBarrierCurve({
    required Widget child,
    this.barrierLabel,
    this.barrierColor = Colors.black,
    Curve? barrierCurve,
  }) : _barrierCurve = barrierCurve,
       _child = child;

  final Widget _child;

  @override
  bool get barrierDismissible => true;

  @override
  final String? barrierLabel;

  @override
  final Color? barrierColor;

  @override
  Curve get barrierCurve => _barrierCurve ?? super.barrierCurve;

  final Curve? _barrierCurve;

  @override
  Duration get transitionDuration => const Duration(milliseconds: 100); // easier value to test against

  @override
  Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
    return Semantics(
      scopesRoute: true,
      explicitChildNodes: true,
      child: _child,
    );
  }
}

class WidgetWithLocalHistory extends StatefulWidget {
  const WidgetWithLocalHistory({super.key});

  @override
  WidgetWithLocalHistoryState createState() => WidgetWithLocalHistoryState();
}

class WidgetWithLocalHistoryState extends State<WidgetWithLocalHistory> {
  late LocalHistoryEntry _localHistory;

  void addLocalHistory() {
    final ModalRoute<dynamic> route = ModalRoute.of(context)!;
    _localHistory = LocalHistoryEntry();
    route.addLocalHistoryEntry(_localHistory);
  }

  @override
  void dispose() {
    super.dispose();
    _localHistory.remove();
  }

  @override
  Widget build(BuildContext context) {
    return const Text('dummy');
  }
}

class WidgetWithNoLocalHistory extends StatefulWidget {
  const WidgetWithNoLocalHistory({super.key});

  @override
  WidgetWithNoLocalHistoryState createState() => WidgetWithNoLocalHistoryState();
}

class WidgetWithNoLocalHistoryState extends State<WidgetWithNoLocalHistory> {
  late LocalHistoryEntry _localHistory;

  void addLocalHistory() {
    _localHistory = LocalHistoryEntry();
    // Not calling `route.addLocalHistoryEntry` here.
  }

  @override
  void dispose() {
    super.dispose();
    _localHistory.remove();
  }

  @override
  Widget build(BuildContext context) {
    return const Text('dummy');
  }
}

class _RestorableDialogTestWidget extends StatelessWidget {
  const _RestorableDialogTestWidget();

  @pragma('vm:entry-point')
  static Route<Object?> _dialogBuilder(BuildContext context, Object? arguments) {
    return RawDialogRoute<void>(
      pageBuilder: (
        BuildContext context,
        Animation<double> animation,
        Animation<double> secondaryAnimation,
      ) {
        return const AlertDialog(title: Text('Alert!'));
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: OutlinedButton(
          onPressed: () {
            Navigator.of(context).restorablePush(_dialogBuilder);
          },
          child: const Text('X'),
        ),
      ),
    );
  }
}
