// 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:async';

import 'package:flutter/foundation.dart';
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';

void main() {
  testWidgets('Simple router basic functionality - synchronized', (WidgetTester tester) async {
    final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
    addTearDown(provider.dispose);
    provider.value = RouteInformation(
      uri: Uri.parse('initial'),
    );
    final SimpleRouterDelegate delegate = SimpleRouterDelegate(
      builder: (BuildContext context, RouteInformation? information) {
        return Text(Uri.decodeComponent(information!.uri.toString()));
      },
    );
    addTearDown(delegate.dispose);

    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        routeInformationProvider: provider,
        routeInformationParser: SimpleRouteInformationParser(),
        routerDelegate: delegate,
      ),
    ));
    expect(find.text('initial'), findsOneWidget);

    provider.value = RouteInformation(
      uri: Uri.parse('update'),
    );
    await tester.pump();
    expect(find.text('initial'), findsNothing);
    expect(find.text('update'), findsOneWidget);
  });

  testWidgets('Simple router basic functionality - asynchronized', (WidgetTester tester) async {
    final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
    addTearDown(provider.dispose);
    provider.value = RouteInformation(
      uri: Uri.parse('initial'),
    );
    final SimpleAsyncRouteInformationParser parser = SimpleAsyncRouteInformationParser();
    final SimpleAsyncRouterDelegate delegate = SimpleAsyncRouterDelegate(
      builder: (BuildContext context, RouteInformation? information) {
        return Text(information?.uri.toString() ?? 'waiting');
      },
    );
    addTearDown(delegate.dispose);

    await tester.runAsync(() async {
      await tester.pumpWidget(buildBoilerPlate(
        Router<RouteInformation>(
          routeInformationProvider: provider,
          routeInformationParser: parser,
          routerDelegate: delegate,
        ),
      ));
      // Future has not yet completed.
      expect(find.text('waiting'), findsOneWidget);

      await parser.parsingFuture;
      await delegate.setNewRouteFuture;
      await tester.pump();
      expect(find.text('initial'), findsOneWidget);

      provider.value = RouteInformation(
        uri: Uri.parse('update'),
      );
      await tester.pump();
      // Future has not yet completed.
      expect(find.text('initial'), findsOneWidget);

      await parser.parsingFuture;
      await delegate.setNewRouteFuture;
      await tester.pump();
      expect(find.text('update'), findsOneWidget);
    });
  });

  testWidgets('Interrupts route parsing should not crash', (WidgetTester tester) async {
    final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
    addTearDown(provider.dispose);
    provider.value = RouteInformation(
      uri: Uri.parse('initial'),
    );
    final CompleterRouteInformationParser parser = CompleterRouteInformationParser();
    final SimpleAsyncRouterDelegate delegate = SimpleAsyncRouterDelegate(
      builder: (BuildContext context, RouteInformation? information) {
        return Text(information?.uri.toString() ?? 'waiting');
      },
    );
    addTearDown(delegate.dispose);

    await tester.runAsync(() async {
      await tester.pumpWidget(buildBoilerPlate(
        Router<RouteInformation>(
          routeInformationProvider: provider,
          routeInformationParser: parser,
          routerDelegate: delegate,
        ),
      ));
      // Future has not yet completed.
      expect(find.text('waiting'), findsOneWidget);

      final Completer<void> firstTransactionCompleter = parser.completer;

      // Start a new parsing transaction before the previous one complete.
      provider.value = RouteInformation(
        uri: Uri.parse('update'),
      );
      await tester.pump();
      expect(find.text('waiting'), findsOneWidget);
      // Completing the previous transaction does not cause an update.
      firstTransactionCompleter.complete();
      await firstTransactionCompleter.future;
      await tester.pump();
      expect(find.text('waiting'), findsOneWidget);
      expect(tester.takeException(), isNull);

      // Make sure the new transaction can complete and update correctly.
      parser.completer.complete();
      await parser.completer.future;
      await delegate.setNewRouteFuture;
      await tester.pump();
      expect(find.text('update'), findsOneWidget);
    });
  });

  testWidgets('Router.maybeOf can be null', (WidgetTester tester) async {
    final GlobalKey key = GlobalKey();
    await tester.pumpWidget(buildBoilerPlate(
      Text('dummy', key: key),
    ));
    final BuildContext textContext = key.currentContext!;

    // This should not throw error.
    final Router<dynamic>? router = Router.maybeOf(textContext);
    expect(router, isNull);

    expect(
      () => Router.of(textContext),
      throwsA(isFlutterError.having((FlutterError e) => e.message, 'message', startsWith('Router')))
    );
  });

  testWidgets('Simple router can handle pop route', (WidgetTester tester) async {
    final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
    addTearDown(provider.dispose);
    provider.value = RouteInformation(
      uri: Uri.parse('initial'),
    );
    final BackButtonDispatcher dispatcher = RootBackButtonDispatcher();
    final SimpleRouterDelegate delegate = SimpleRouterDelegate(
      builder: (BuildContext context, RouteInformation? information) {
        return Text(Uri.decodeComponent(information!.uri.toString()));
      },
      onPopRoute: () {
        provider.value = RouteInformation(
          uri: Uri.parse('popped'),
        );
        return SynchronousFuture<bool>(true);
      },
    );
    addTearDown(delegate.dispose);

    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        routeInformationProvider: provider,
        routeInformationParser: SimpleRouteInformationParser(),
        routerDelegate: delegate,
        backButtonDispatcher: dispatcher,
      ),
    ));
    expect(find.text('initial'), findsOneWidget);

    bool result = false;
    // SynchronousFuture should complete immediately.
    dispatcher.invokeCallback(SynchronousFuture<bool>(false))
      .then((bool data) {
        result = data;
      });
    expect(result, isTrue);

    await tester.pump();
    expect(find.text('popped'), findsOneWidget);
  });

  testWidgets('Router throw when passing routeInformationProvider without routeInformationParser', (WidgetTester tester) async {
    final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
    addTearDown(provider.dispose);
    provider.value = RouteInformation(
      uri: Uri.parse('initial'),
    );
    final SimpleRouterDelegate delegate = SimpleRouterDelegate(
      builder: (BuildContext context, RouteInformation? information) {
        return Text(Uri.decodeComponent(information!.uri.toString()));
      },
    );
    addTearDown(delegate.dispose);

    expect(
      () {
        Router<RouteInformation>(
          routeInformationProvider: provider,
          routerDelegate: delegate,
        );
      },
      throwsA(isAssertionError.having(
        (AssertionError e) => e.message,
        'message',
        'A routeInformationParser must be provided when a routeInformationProvider is specified.',
      )),
    );
  });

  testWidgets('PopNavigatorRouterDelegateMixin works', (WidgetTester tester) async {
    final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
    addTearDown(provider.dispose);
    provider.value = RouteInformation(
      uri: Uri.parse('initial'),
    );
    final BackButtonDispatcher dispatcher = RootBackButtonDispatcher();
    final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate(
      builder: (BuildContext context, RouteInformation? information) {
        return Text(Uri.decodeComponent(information!.uri.toString()));
      },
      onPopPage: (Route<void> route, void result) {
        provider.value = RouteInformation(
          uri: Uri.parse('popped'),
        );
        return route.didPop(result);
      },
    );
    addTearDown(delegate.dispose);

    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        routeInformationProvider: provider,
        routeInformationParser: SimpleRouteInformationParser(),
        routerDelegate: delegate,
        backButtonDispatcher: dispatcher,
      ),
    ));
    expect(find.text('initial'), findsOneWidget);

    // Pushes a nameless route.
    showDialog<void>(
      useRootNavigator: false,
      context: delegate.navigatorKey.currentContext!,
      builder: (BuildContext context) => const Text('dialog'),
    );
    await tester.pumpAndSettle();
    expect(find.text('dialog'), findsOneWidget);

    // Pops the nameless route and makes sure the initial page is shown.
    bool result = false;
    result = await dispatcher.invokeCallback(SynchronousFuture<bool>(false));
    expect(result, isTrue);

    await tester.pumpAndSettle();
    expect(find.text('initial'), findsOneWidget);
    expect(find.text('dialog'), findsNothing);

    // Pops one more time.
    result = false;
    result = await dispatcher.invokeCallback(SynchronousFuture<bool>(false));
    expect(result, isTrue);
    await tester.pumpAndSettle();
    expect(find.text('popped'), findsOneWidget);
  });

  testWidgets('Nested routers back button dispatcher works', (WidgetTester tester) async {
    final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
    addTearDown(provider.dispose);
    provider.value = RouteInformation(
      uri: Uri.parse('initial'),
    );
    final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
    final SimpleRouterDelegate outerDelegate = SimpleRouterDelegate(
      builder: (BuildContext context, RouteInformation? information) {
        final BackButtonDispatcher innerDispatcher = ChildBackButtonDispatcher(outerDispatcher);
        innerDispatcher.takePriority();
        final SimpleRouterDelegate innerDelegate = SimpleRouterDelegate(
          builder: (BuildContext context, RouteInformation? innerInformation) {
            return Text(Uri.decodeComponent(information!.uri.toString()));
          },
          onPopRoute: () {
            provider.value = RouteInformation(
              uri: Uri.parse('popped inner'),
            );
            return SynchronousFuture<bool>(true);
          },
        );
        addTearDown(innerDelegate.dispose);
        // Creates the sub-router.
        return Router<RouteInformation>(
          backButtonDispatcher: innerDispatcher,
          routerDelegate: innerDelegate,
        );
      },
      onPopRoute: () {
        provider.value = RouteInformation(
          uri: Uri.parse('popped outer'),
        );
        return SynchronousFuture<bool>(true);
      },
    );
    addTearDown(outerDelegate.dispose);

    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        backButtonDispatcher: outerDispatcher,
        routeInformationProvider: provider,
        routeInformationParser: SimpleRouteInformationParser(),
        routerDelegate: outerDelegate,
      ),
    ));
    expect(find.text('initial'), findsOneWidget);

    // The outer dispatcher should trigger the pop on the inner router.
    bool result = false;
    result = await outerDispatcher.invokeCallback(SynchronousFuture<bool>(false));
    expect(result, isTrue);
    await tester.pump();
    expect(find.text('popped inner'), findsOneWidget);
  });

  testWidgets('Nested router back button dispatcher works for multiple children', (WidgetTester tester) async {
    final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
    addTearDown(provider.dispose);
    provider.value = RouteInformation(
      uri: Uri.parse('initial'),
    );
    final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
    final BackButtonDispatcher innerDispatcher1 = ChildBackButtonDispatcher(outerDispatcher);
    final BackButtonDispatcher innerDispatcher2 = ChildBackButtonDispatcher(outerDispatcher);
    final SimpleRouterDelegate outerDelegate = SimpleRouterDelegate(
      builder: (BuildContext context, RouteInformation? information) {
        late final SimpleRouterDelegate innerDelegate1;
        addTearDown(() => innerDelegate1.dispose());
        late final SimpleRouterDelegate innerDelegate2;
        addTearDown(() => innerDelegate2.dispose());

        // Creates the sub-router.
        return Column(
          children: <Widget>[
            Text(Uri.decodeComponent(information!.uri.toString())),
            Router<RouteInformation>(
              backButtonDispatcher: innerDispatcher1,
              routerDelegate: innerDelegate1 = SimpleRouterDelegate(
                builder: (BuildContext context, RouteInformation? innerInformation) {
                  return Container();
                },
                onPopRoute: () {
                  provider.value = RouteInformation(
                    uri: Uri.parse('popped inner1'),
                  );
                  return SynchronousFuture<bool>(true);
                },
              ),
            ),
            Router<RouteInformation>(
              backButtonDispatcher: innerDispatcher2,
              routerDelegate: innerDelegate2 = SimpleRouterDelegate(
                builder: (BuildContext context, RouteInformation? innerInformation) {
                  return Container();
                },
                onPopRoute: () {
                  provider.value = RouteInformation(
                    uri: Uri.parse('popped inner2'),
                  );
                  return SynchronousFuture<bool>(true);
                },
              ),
            ),
          ],
        );
      },
      onPopRoute: () {
        provider.value = RouteInformation(
          uri: Uri.parse('popped outer'),
        );
        return SynchronousFuture<bool>(true);
      },
    );
    addTearDown(outerDelegate.dispose);

    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        backButtonDispatcher: outerDispatcher,
        routeInformationProvider: provider,
        routeInformationParser: SimpleRouteInformationParser(),
        routerDelegate: outerDelegate,
      ),
    ));
    expect(find.text('initial'), findsOneWidget);

    // If none of the children have taken the priority, the root router handles
    // the pop.
    bool result = false;
    result = await outerDispatcher.invokeCallback(SynchronousFuture<bool>(false));
    expect(result, isTrue);
    await tester.pump();
    expect(find.text('popped outer'), findsOneWidget);

    innerDispatcher1.takePriority();
    result = false;
    result = await outerDispatcher.invokeCallback(SynchronousFuture<bool>(false));
    expect(result, isTrue);
    await tester.pump();
    expect(find.text('popped inner1'), findsOneWidget);

    // The last child dispatcher that took priority handles the pop.
    innerDispatcher2.takePriority();
    result = false;
    result = await outerDispatcher.invokeCallback(SynchronousFuture<bool>(false));
    expect(result, isTrue);
    await tester.pump();
    expect(find.text('popped inner2'), findsOneWidget);
  });

  testWidgets('ChildBackButtonDispatcher can be replaced without calling the takePriority', (WidgetTester tester) async {
    final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
    BackButtonDispatcher innerDispatcher = ChildBackButtonDispatcher(outerDispatcher);
    final SimpleRouterDelegate outerDelegate1 = SimpleRouterDelegate(
      builder: (BuildContext context, RouteInformation? information) {
        final SimpleRouterDelegate innerDelegate1 = SimpleRouterDelegate(
          builder: (BuildContext context, RouteInformation? innerInformation) {
            return Container();
          },
        );
        addTearDown(innerDelegate1.dispose);

        // Creates the sub-router.
        return Column(
          children: <Widget>[
            const Text('initial'),
            Router<RouteInformation>(
              backButtonDispatcher: innerDispatcher,
              routerDelegate: innerDelegate1,
            ),
          ],
        );
      },
    );
    addTearDown(outerDelegate1.dispose);

    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        backButtonDispatcher: outerDispatcher,
        routerDelegate: outerDelegate1,
      ),
    ));

    // Creates a new child back button dispatcher and rebuild, this will cause
    // the old one to be replaced and discarded.
    innerDispatcher = ChildBackButtonDispatcher(outerDispatcher);
    final SimpleRouterDelegate outerDelegate2 = SimpleRouterDelegate(
      builder: (BuildContext context, RouteInformation? information) {
        final SimpleRouterDelegate innerDelegate2 = SimpleRouterDelegate(
          builder: (BuildContext context, RouteInformation? innerInformation) {
            return Container();
          },
        );
        addTearDown(innerDelegate2.dispose);

        // Creates the sub-router.
        return Column(
          children: <Widget>[
            const Text('initial'),
            Router<RouteInformation>(
              backButtonDispatcher: innerDispatcher,
              routerDelegate: innerDelegate2,
            ),
          ],
        );
      },
    );
    addTearDown(outerDelegate2.dispose);

    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        backButtonDispatcher: outerDispatcher,
        routerDelegate: outerDelegate2,
      ),
    ));

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

testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester tester) async {
    final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
    final BackButtonDispatcher innerDispatcher1 = ChildBackButtonDispatcher(outerDispatcher);
    final BackButtonDispatcher innerDispatcher2 = ChildBackButtonDispatcher(innerDispatcher1);
    final BackButtonDispatcher innerDispatcher3 = ChildBackButtonDispatcher(innerDispatcher2);
    late final SimpleRouterDelegate outerDelegate;
    addTearDown(() => outerDelegate.dispose());
    late final SimpleRouterDelegate innerDelegate1;
    addTearDown(() => innerDelegate1.dispose());
    late final SimpleRouterDelegate innerDelegate2;
    addTearDown(() => innerDelegate2.dispose());
    late final SimpleRouterDelegate innerDelegate3;
    addTearDown(() => innerDelegate3.dispose());
    bool isPopped = false;

    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        backButtonDispatcher: outerDispatcher,
        routerDelegate: outerDelegate = SimpleRouterDelegate(
          builder: (BuildContext context, RouteInformation? information) {
            // Creates the sub-router.
            return Router<RouteInformation>(
              backButtonDispatcher: innerDispatcher1,
              routerDelegate: innerDelegate1 = SimpleRouterDelegate(
                builder: (BuildContext context, RouteInformation? innerInformation) {
                  return Router<RouteInformation>(
                    backButtonDispatcher: innerDispatcher2,
                    routerDelegate: innerDelegate2 = SimpleRouterDelegate(
                      builder: (BuildContext context, RouteInformation? innerInformation) {
                        return Router<RouteInformation>(
                          backButtonDispatcher: innerDispatcher3,
                          routerDelegate: innerDelegate3 = SimpleRouterDelegate(
                            onPopRoute: () {
                              isPopped = true;
                              return SynchronousFuture<bool>(true);
                            },
                            builder: (BuildContext context, RouteInformation? innerInformation) {
                              return Container();
                            },
                          ),
                        );
                      },
                    ),
                  );
                },
              ),
            );
          },
        ),
      ),
    ));
    // This should work without calling the takePriority on the innerDispatcher2
    // and the innerDispatcher1.
    innerDispatcher3.takePriority();
    bool result = false;
    result = await outerDispatcher.invokeCallback(SynchronousFuture<bool>(false));
    expect(result, isTrue);
    expect(isPopped, isTrue);
  });

  testWidgets('router does report URL change correctly', (WidgetTester tester) async {
    RouteInformation? reportedRouteInformation;
    RouteInformationReportingType? reportedType;
    final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(
      onRouterReport: (RouteInformation information, RouteInformationReportingType type) {
        // Makes sure we only report once after manually cleaning up.
        expect(reportedRouteInformation, isNull);
        expect(reportedType, isNull);
        reportedRouteInformation = information;
        reportedType = type;
      },
    );
    addTearDown(provider.dispose);
    final SimpleRouterDelegate delegate = SimpleRouterDelegate(
      reportConfiguration: true,
      builder: (BuildContext context, RouteInformation? information) {
        return Text(Uri.decodeComponent(information!.uri.toString()));
      },
    );
    delegate.onPopRoute = () {
      delegate.routeInformation = RouteInformation(
        uri: Uri.parse('popped'),
      );
      return SynchronousFuture<bool>(true);
    };
    addTearDown(delegate.dispose);
    final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();

    provider.value = RouteInformation(
      uri: Uri.parse('initial'),
    );

    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        backButtonDispatcher: outerDispatcher,
        routeInformationProvider: provider,
        routeInformationParser: SimpleRouteInformationParser(),
        routerDelegate: delegate,
      ),
    ));
    expect(find.text('initial'), findsOneWidget);
    expect(reportedRouteInformation!.uri.toString(), 'initial');
    expect(reportedType, RouteInformationReportingType.none);
    reportedRouteInformation = null;
    reportedType = null;
    delegate.routeInformation = RouteInformation(
      uri: Uri.parse('update'),
    );
    await tester.pump();
    expect(find.text('initial'), findsNothing);
    expect(find.text('update'), findsOneWidget);
    expect(reportedRouteInformation!.uri.toString(), 'update');
    expect(reportedType, RouteInformationReportingType.none);

    // The router should report as non navigation event if only state changes.
    reportedRouteInformation = null;
    reportedType = null;
    delegate.routeInformation = RouteInformation(
      uri: Uri.parse('update'),
      state: 'another state',
    );
    await tester.pump();
    expect(find.text('update'), findsOneWidget);
    expect(reportedRouteInformation!.uri.toString(), 'update');
    expect(reportedRouteInformation!.state, 'another state');
    expect(reportedType, RouteInformationReportingType.none);

    reportedRouteInformation = null;
    reportedType = null;
    bool result = false;
    result = await outerDispatcher.invokeCallback(SynchronousFuture<bool>(false));
    expect(result, isTrue);
    await tester.pump();
    expect(find.text('popped'), findsOneWidget);
    expect(reportedRouteInformation!.uri.toString(), 'popped');
    expect(reportedType, RouteInformationReportingType.none);
  });

  testWidgets('router can be forced to recognize or ignore navigating events', (WidgetTester tester) async {
    RouteInformation? reportedRouteInformation;
    RouteInformationReportingType? reportedType;
    bool isNavigating = false;
    late RouteInformation nextRouteInformation;
    final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(
      onRouterReport: (RouteInformation information, RouteInformationReportingType type) {
        // Makes sure we only report once after manually cleaning up.
        expect(reportedRouteInformation, isNull);
        expect(reportedType, isNull);
        reportedRouteInformation = information;
        reportedType = type;
      },
    );
    addTearDown(provider.dispose);
    provider.value = RouteInformation(
      uri: Uri.parse('initial'),
    );
    final SimpleRouterDelegate delegate = SimpleRouterDelegate(reportConfiguration: true);
    addTearDown(delegate.dispose);
    delegate.builder = (BuildContext context, RouteInformation? information) {
      return ElevatedButton(
        child: Text(Uri.decodeComponent(information!.uri.toString())),
        onPressed: () {
          if (isNavigating) {
            Router.navigate(context, () {
              if (delegate.routeInformation != nextRouteInformation) {
                delegate.routeInformation = nextRouteInformation;
              }
            });
          } else {
            Router.neglect(context, () {
              if (delegate.routeInformation != nextRouteInformation) {
                delegate.routeInformation = nextRouteInformation;
              }
            });
          }
        },
      );
    };
    final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();

    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        backButtonDispatcher: outerDispatcher,
        routeInformationProvider: provider,
        routeInformationParser: SimpleRouteInformationParser(),
        routerDelegate: delegate,
      ),
    ));
    expect(find.text('initial'), findsOneWidget);
    expect(reportedRouteInformation!.uri.toString(), 'initial');
    expect(reportedType, RouteInformationReportingType.none);
    reportedType = null;
    reportedRouteInformation = null;

    nextRouteInformation = RouteInformation(
      uri: Uri.parse('update'),
    );
    await tester.tap(find.byType(ElevatedButton));
    await tester.pump();
    expect(find.text('initial'), findsNothing);
    expect(find.text('update'), findsOneWidget);
    expect(reportedType, RouteInformationReportingType.neglect);
    expect(reportedRouteInformation!.uri.toString(), 'update');
    reportedType = null;
    reportedRouteInformation = null;

    isNavigating = true;
    // This should not trigger any real navigating event because the
    // nextRouteInformation does not change. However, the router should still
    // report a route information because isNavigating = true.
    await tester.tap(find.byType(ElevatedButton));
    await tester.pump();
    expect(reportedType, RouteInformationReportingType.navigate);
    expect(reportedRouteInformation!.uri.toString(), 'update');
    reportedType = null;
    reportedRouteInformation = null;
  });

  testWidgets('router ignore navigating events updates RouteInformationProvider', (WidgetTester tester) async {
    RouteInformation? updatedRouteInformation;
    late RouteInformation nextRouteInformation;
    RouteInformationReportingType? reportingType;
    final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(
      onRouterReport: (RouteInformation information, RouteInformationReportingType type) {
        expect(reportingType, isNull);
        expect(updatedRouteInformation, isNull);
        updatedRouteInformation = information;
        reportingType = type;
      },
    );
    addTearDown(provider.dispose);
    provider.value = RouteInformation(
      uri: Uri.parse('initial'),
    );
    final SimpleRouterDelegate delegate = SimpleRouterDelegate(reportConfiguration: true);
    addTearDown(delegate.dispose);
    delegate.builder = (BuildContext context, RouteInformation? information) {
      return ElevatedButton(
        child: Text(Uri.decodeComponent(information!.uri.toString())),
        onPressed: () {
          Router.neglect(context, () {
            if (delegate.routeInformation != nextRouteInformation) {
              delegate.routeInformation = nextRouteInformation;
            }
          });
        },
      );
    };
    final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();

    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        backButtonDispatcher: outerDispatcher,
        routeInformationProvider: provider,
        routeInformationParser: SimpleRouteInformationParser(),
        routerDelegate: delegate,
      ),
    ));
    expect(find.text('initial'), findsOneWidget);
    expect(updatedRouteInformation!.uri.toString(), 'initial');
    expect(reportingType, RouteInformationReportingType.none);
    updatedRouteInformation = null;
    reportingType = null;

    nextRouteInformation = RouteInformation(
      uri: Uri.parse('update'),
    );
    await tester.tap(find.byType(ElevatedButton));
    await tester.pump();
    expect(find.text('initial'), findsNothing);
    expect(find.text('update'), findsOneWidget);
    expect(updatedRouteInformation!.uri.toString(), 'update');
    expect(reportingType, RouteInformationReportingType.neglect);
  });

  testWidgets('state change without location changes updates RouteInformationProvider', (WidgetTester tester) async {
    RouteInformation? updatedRouteInformation;
    late RouteInformation nextRouteInformation;
    RouteInformationReportingType? reportingType;
    final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(
      onRouterReport: (RouteInformation information, RouteInformationReportingType type) {
        // This should never be a navigation event.
        expect(reportingType, isNull);
        expect(updatedRouteInformation, isNull);
        updatedRouteInformation = information;
        reportingType = type;
      },
    );
    addTearDown(provider.dispose);
    provider.value = RouteInformation(
      uri: Uri.parse('initial'),
      state: 'state1',
    );
    final SimpleRouterDelegate delegate = SimpleRouterDelegate(reportConfiguration: true);
    addTearDown(delegate.dispose);
    delegate.builder = (BuildContext context, RouteInformation? information) {
      return ElevatedButton(
        child: Text(Uri.decodeComponent(information!.uri.toString())),
        onPressed: () {
          delegate.routeInformation = nextRouteInformation;
        },
      );
    };
    final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();

    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        backButtonDispatcher: outerDispatcher,
        routeInformationProvider: provider,
        routeInformationParser: SimpleRouteInformationParser(),
        routerDelegate: delegate,
      ),
    ));
    expect(find.text('initial'), findsOneWidget);
    expect(updatedRouteInformation!.uri.toString(), 'initial');
    expect(reportingType, RouteInformationReportingType.none);
    updatedRouteInformation = null;
    reportingType = null;

    nextRouteInformation = RouteInformation(
      uri: Uri.parse('initial'),
      state: 'state2',
    );
    await tester.tap(find.byType(ElevatedButton));
    await tester.pump();
    expect(updatedRouteInformation!.uri.toString(), 'initial');
    expect(updatedRouteInformation!.state, 'state2');
    expect(reportingType, RouteInformationReportingType.none);
  });

  testWidgets('PlatformRouteInformationProvider works', (WidgetTester tester) async {
    final PlatformRouteInformationProvider provider = PlatformRouteInformationProvider(
      initialRouteInformation: RouteInformation(
        uri: Uri.parse('initial'),
      ),
    );
    addTearDown(provider.dispose);
    final SimpleRouterDelegate delegate = SimpleRouterDelegate(
      builder: (BuildContext context, RouteInformation? information) {
        final List<Widget> children = <Widget>[];
        if (information!.uri.toString().isNotEmpty) {
          children.add(Text(information.uri.toString()));
        }
        if (information.state != null) {
          children.add(Text(information.state.toString()));
        }
        return Column(
          children: children,
        );
      },
    );
    addTearDown(delegate.dispose);

    await tester.pumpWidget(MaterialApp.router(
        routeInformationProvider: provider,
        routeInformationParser: SimpleRouteInformationParser(),
        routerDelegate: delegate,
    ));
    expect(find.text('initial'), findsOneWidget);

    // Pushes through the `pushRouteInformation` in the navigation method channel.
    const Map<String, dynamic> testRouteInformation = <String, dynamic>{
      'location': 'testRouteName',
      'state': 'state',
    };
    final ByteData routerMessage = const JSONMethodCodec().encodeMethodCall(
      const MethodCall('pushRouteInformation', testRouteInformation),
    );
    await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', routerMessage, (_) { });
    await tester.pump();
    expect(find.text('testRouteName'), findsOneWidget);
    expect(find.text('state'), findsOneWidget);

    // Pushes through the `pushRoute` in the navigation method channel.
    const String testRouteName = 'newTestRouteName';
    final ByteData message = const JSONMethodCodec().encodeMethodCall(
      const MethodCall('pushRoute', testRouteName),
    );
    await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { });
    await tester.pump();
    expect(find.text('newTestRouteName'), findsOneWidget);
  });

  testWidgets('PlatformRouteInformationProvider updates route information', (WidgetTester tester) async {
    final List<MethodCall> log = <MethodCall>[];
    TestDefaultBinaryMessengerBinding
      .instance.defaultBinaryMessenger
      .setMockMethodCallHandler(
        SystemChannels.navigation,
        (MethodCall methodCall) async {
          log.add(methodCall);
	  return null;
        }
      );
    final PlatformRouteInformationProvider provider = PlatformRouteInformationProvider(
      initialRouteInformation: RouteInformation(
        uri: Uri.parse('initial'),
      ),
    );
    addTearDown(provider.dispose);

    log.clear();
    provider.routerReportsNewRouteInformation(RouteInformation(uri: Uri.parse('a'), state: true));
    // Implicit reporting pushes new history entry if the location changes.
    expect(log, <Object>[
      isMethodCall('selectMultiEntryHistory', arguments: null),
      isMethodCall('routeInformationUpdated', arguments: <String, dynamic>{ 'uri': 'a', 'state': true, 'replace': false }),
    ]);
    log.clear();
    provider.routerReportsNewRouteInformation(RouteInformation(uri: Uri.parse('a'), state: false));
    // Since the location is the same, the provider sends replaces message.
    expect(log, <Object>[
      isMethodCall('selectMultiEntryHistory', arguments: null),
      isMethodCall('routeInformationUpdated', arguments: <String, dynamic>{ 'uri': 'a', 'state': false, 'replace': true }),
    ]);

    log.clear();
    provider.routerReportsNewRouteInformation(RouteInformation(uri: Uri.parse('b'), state: false), type: RouteInformationReportingType.neglect);
    expect(log, <Object>[
      isMethodCall('selectMultiEntryHistory', arguments: null),
      isMethodCall('routeInformationUpdated', arguments: <String, dynamic>{ 'uri': 'b', 'state': false, 'replace': true }),
    ]);

    log.clear();
    provider.routerReportsNewRouteInformation(RouteInformation(uri: Uri.parse('b'), state: false), type: RouteInformationReportingType.navigate);
    expect(log, <Object>[
      isMethodCall('selectMultiEntryHistory', arguments: null),
      isMethodCall('routeInformationUpdated', arguments: <String, dynamic>{ 'uri': 'b', 'state': false, 'replace': false }),
    ]);
  });

  testWidgets('PlatformRouteInformationProvider does not push new entry if query parameters are semantically the same', (WidgetTester tester) async {
    final List<MethodCall> log = <MethodCall>[];
    TestDefaultBinaryMessengerBinding
        .instance.defaultBinaryMessenger
        .setMockMethodCallHandler(
        SystemChannels.navigation,
            (MethodCall methodCall) async {
          log.add(methodCall);
          return null;
        }
    );
    final RouteInformation initial = RouteInformation(
      uri: Uri.parse('initial?a=ws/abcd'),
    );
    final PlatformRouteInformationProvider provider = PlatformRouteInformationProvider(
      initialRouteInformation: initial
    );
    addTearDown(provider.dispose);
    // Make sure engine is updated with initial route
    provider.routerReportsNewRouteInformation(initial);
    log.clear();

    provider.routerReportsNewRouteInformation(
      RouteInformation(
        uri: Uri(
          path: 'initial',
          queryParameters: <String, String>{'a': 'ws/abcd'}, // This will be escaped.
        ),
      ),
    );
    expect(provider.value.uri.toString(), 'initial?a=ws%2Fabcd');
    // should use `replace: true`
    expect(log, <Object>[
      isMethodCall('selectMultiEntryHistory', arguments: null),
      isMethodCall('routeInformationUpdated', arguments: <String, dynamic>{ 'uri': 'initial?a=ws%2Fabcd', 'state': null, 'replace': true }),
    ]);
    log.clear();

    provider.routerReportsNewRouteInformation(
      RouteInformation(uri: Uri.parse('initial?a=1&b=2')),
    );
    log.clear();

    // Change query parameters order
    provider.routerReportsNewRouteInformation(
      RouteInformation(uri: Uri.parse('initial?b=2&a=1')),
    );
    // should use `replace: true`
    expect(log, <Object>[
      isMethodCall('selectMultiEntryHistory', arguments: null),
      isMethodCall('routeInformationUpdated', arguments: <String, dynamic>{ 'uri': 'initial?b=2&a=1', 'state': null, 'replace': true }),
    ]);
    log.clear();

    provider.routerReportsNewRouteInformation(
      RouteInformation(uri: Uri.parse('initial?a=1&a=2')),
    );
    log.clear();

    // Change query parameters order for same key
    provider.routerReportsNewRouteInformation(
      RouteInformation(uri: Uri.parse('initial?a=2&a=1')),
    );
    // should use `replace: true`
    expect(log, <Object>[
      isMethodCall('selectMultiEntryHistory', arguments: null),
      isMethodCall('routeInformationUpdated', arguments: <String, dynamic>{ 'uri': 'initial?a=2&a=1', 'state': null, 'replace': true }),
    ]);
    log.clear();
  });

  testWidgets('RootBackButtonDispatcher works', (WidgetTester tester) async {
    final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
    final PlatformRouteInformationProvider provider = PlatformRouteInformationProvider(
      initialRouteInformation: RouteInformation(
        uri: Uri.parse('initial'),
      ),
    );
    addTearDown(provider.dispose);
    final SimpleRouterDelegate delegate = SimpleRouterDelegate(
      reportConfiguration: true,
      builder: (BuildContext context, RouteInformation? information) {
        return Text(Uri.decodeComponent(information!.uri.toString()));
      },
    );
    addTearDown(delegate.dispose);
    delegate.onPopRoute = () {
      delegate.routeInformation = RouteInformation(
        uri: Uri.parse('popped'),
      );
      return SynchronousFuture<bool>(true);
    };

    await tester.pumpWidget(MaterialApp.router(
      backButtonDispatcher: outerDispatcher,
      routeInformationProvider: provider,
      routeInformationParser: SimpleRouteInformationParser(),
      routerDelegate: delegate,
    ));
    expect(find.text('initial'), findsOneWidget);

    // Pop route through the message channel.
    final ByteData message = const JSONMethodCodec().encodeMethodCall(const MethodCall('popRoute'));
    await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { });
    await tester.pump();
    expect(find.text('popped'), findsOneWidget);
  });

  testWidgets('BackButtonListener takes priority over root back dispatcher', (WidgetTester tester) async {
    final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
    addTearDown(provider.dispose);
    provider.value = RouteInformation(
      uri: Uri.parse('initial'),
    );
    final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
    final SimpleRouterDelegate delegate = SimpleRouterDelegate(
      builder: (BuildContext context, RouteInformation? information) {
        // Creates the sub-router.
        return Column(
          children: <Widget>[
            Text(Uri.decodeComponent(information!.uri.toString())),
            BackButtonListener(
              child: Container(),
              onBackButtonPressed: () {
                  provider.value = RouteInformation(
                    uri: Uri.parse('popped inner1'),
                  );
                  return SynchronousFuture<bool>(true);
                },
            ),
          ],
        );
      },
      onPopRoute: () {
        provider.value = RouteInformation(
          uri: Uri.parse('popped outer'),
        );
        return SynchronousFuture<bool>(true);
      },
    );
    addTearDown(delegate.dispose);

    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        backButtonDispatcher: outerDispatcher,
        routeInformationProvider: provider,
        routeInformationParser: SimpleRouteInformationParser(),
        routerDelegate: delegate,
      ),
    ));
    expect(find.text('initial'), findsOneWidget);

    bool result = false;
    result = await outerDispatcher.invokeCallback(SynchronousFuture<bool>(false));
    expect(result, isTrue);
    await tester.pump();
    expect(find.text('popped inner1'), findsOneWidget);
  });

  testWidgets('BackButtonListener updates callback if it has been changed', (WidgetTester tester) async {
    final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
    addTearDown(provider.dispose);
    provider.value = RouteInformation(
      uri: Uri.parse('initial'),
    );
    final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
    final SimpleRouterDelegate routerDelegate = SimpleRouterDelegate()
      ..builder = (BuildContext context, RouteInformation? information) {
            // Creates the sub-router.
            return Column(
              children: <Widget>[
                Text(Uri.decodeComponent(information!.uri.toString())),
                BackButtonListener(
                  child: Container(),
                  onBackButtonPressed: () {
                      provider.value = RouteInformation(
                        uri: Uri.parse('first callback'),
                      );
                      return SynchronousFuture<bool>(true);
                    },
                ),
              ],
            );
          }
        ..onPopRoute = () {
            provider.value = RouteInformation(
              uri: Uri.parse('popped outer'),
            );
            return SynchronousFuture<bool>(true);
          };
    addTearDown(routerDelegate.dispose);

    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        backButtonDispatcher: outerDispatcher,
        routeInformationProvider: provider,
        routeInformationParser: SimpleRouteInformationParser(),
        routerDelegate: routerDelegate,
      ),
    ));

    routerDelegate
      ..builder = (BuildContext context, RouteInformation? information) {
        // Creates the sub-router.
        return Column(
          children: <Widget>[
            Text(Uri.decodeComponent(information!.uri.toString())),
            BackButtonListener(
              child: Container(),
              onBackButtonPressed: () {
                  provider.value = RouteInformation(
                    uri: Uri.parse('second callback'),
                  );
                  return SynchronousFuture<bool>(true);
                },
            ),
          ],
        );
      }
      ..onPopRoute = () {
        provider.value = RouteInformation(
          uri: Uri.parse('popped outer'),
        );
        return SynchronousFuture<bool>(true);
      };

    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        backButtonDispatcher: outerDispatcher,
        routeInformationProvider: provider,
        routeInformationParser: SimpleRouteInformationParser(),
        routerDelegate: routerDelegate,
      ),
    ));
    await tester.pump();
    await outerDispatcher.invokeCallback(SynchronousFuture<bool>(false));
    await tester.pump();
    expect(find.text('second callback'), findsOneWidget);
  });

  testWidgets('BackButtonListener clears callback if it is disposed', (WidgetTester tester) async {
    final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
    addTearDown(provider.dispose);
    provider.value = RouteInformation(
      uri: Uri.parse('initial'),
    );
    final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
    final SimpleRouterDelegate routerDelegate = SimpleRouterDelegate()
      ..builder = (BuildContext context, RouteInformation? information) {
            // Creates the sub-router.
            return Column(
              children: <Widget>[
                Text(Uri.decodeComponent(information!.uri.toString())),
                BackButtonListener(
                  child: Container(),
                  onBackButtonPressed: () {
                      provider.value = RouteInformation(
                        uri: Uri.parse('first callback'),
                      );
                      return SynchronousFuture<bool>(true);
                    },
                ),
              ],
            );
          }
        ..onPopRoute = () {
            provider.value = RouteInformation(
              uri: Uri.parse('popped outer'),
            );
            return SynchronousFuture<bool>(true);
          };
    addTearDown(routerDelegate.dispose);

    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        backButtonDispatcher: outerDispatcher,
        routeInformationProvider: provider,
        routeInformationParser: SimpleRouteInformationParser(),
        routerDelegate: routerDelegate,
      ),
    ));

    routerDelegate
      ..builder = (BuildContext context, RouteInformation? information) {
        // Creates the sub-router.
        return Column(
          children: <Widget>[
            Text(Uri.decodeComponent(information!.uri.toString())),
          ],
        );
      }
      ..onPopRoute = () {
        provider.value = RouteInformation(
          uri: Uri.parse('popped outer'),
        );
        return SynchronousFuture<bool>(true);
      };

    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        backButtonDispatcher: outerDispatcher,
        routeInformationProvider: provider,
        routeInformationParser: SimpleRouteInformationParser(),
        routerDelegate: routerDelegate,
      ),
    ));
    await tester.pump();
    await outerDispatcher.invokeCallback(SynchronousFuture<bool>(false));
    await tester.pump();
    expect(find.text('popped outer'), findsOneWidget);
  });

  testWidgets('Nested backButtonListener should take priority', (WidgetTester tester) async {
    final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
    addTearDown(provider.dispose);
    provider.value = RouteInformation(
      uri: Uri.parse('initial'),
    );
    final SimpleRouterDelegate delegate = SimpleRouterDelegate(
      builder: (BuildContext context, RouteInformation? information) {
        // Creates the sub-router.
        return Column(
          children: <Widget>[
            Text(Uri.decodeComponent(information!.uri.toString())),
            BackButtonListener(
              child: BackButtonListener(
                child: Container(),
                onBackButtonPressed: () {
                  provider.value = RouteInformation(
                    uri: Uri.parse('popped inner2'),
                  );
                  return SynchronousFuture<bool>(true);
                },
              ),
              onBackButtonPressed: () {
                  provider.value = RouteInformation(
                    uri: Uri.parse('popped inner1'),
                  );
                  return SynchronousFuture<bool>(true);
                },
            ),
          ],
        );
      },
      onPopRoute: () {
        provider.value = RouteInformation(
          uri: Uri.parse('popped outer'),
        );
        return SynchronousFuture<bool>(true);
      },
    );
    addTearDown(delegate.dispose);
    final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();

    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        backButtonDispatcher: outerDispatcher,
        routeInformationProvider: provider,
        routeInformationParser: SimpleRouteInformationParser(),
        routerDelegate: delegate,
      ),
    ));
    expect(find.text('initial'), findsOneWidget);

    bool result = false;
    result = await outerDispatcher.invokeCallback(SynchronousFuture<bool>(false));
    expect(result, isTrue);
    await tester.pump();
    expect(find.text('popped inner2'), findsOneWidget);
  });

  testWidgets('Nested backButtonListener that returns false should call next on the line', (WidgetTester tester) async {
    final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
    addTearDown(provider.dispose);
    provider.value = RouteInformation(
      uri: Uri.parse('initial'),
    );
    final SimpleRouterDelegate delegate = SimpleRouterDelegate(
      builder: (BuildContext context, RouteInformation? information) {
        // Creates the sub-router.
        return Column(
          children: <Widget>[
            Text(Uri.decodeComponent(information!.uri.toString())),
            BackButtonListener(
              child: BackButtonListener(
                child: Container(),
                onBackButtonPressed: () {
                  provider.value = RouteInformation(
                    uri: Uri.parse('popped inner2'),
                  );
                  return SynchronousFuture<bool>(false);
                },
              ),
              onBackButtonPressed: () {
                  provider.value = RouteInformation(
                    uri: Uri.parse('popped inner1'),
                  );
                  return SynchronousFuture<bool>(true);
                },
            ),
          ],
        );
      },
      onPopRoute: () {
        provider.value = RouteInformation(
          uri: Uri.parse('popped outer'),
        );
        return SynchronousFuture<bool>(true);
      },
    );
    addTearDown(delegate.dispose);
    final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();

    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        backButtonDispatcher: outerDispatcher,
        routeInformationProvider: provider,
        routeInformationParser: SimpleRouteInformationParser(),
        routerDelegate: delegate,
      ),
    ));
    expect(find.text('initial'), findsOneWidget);

    bool result = false;
    result = await outerDispatcher.invokeCallback(SynchronousFuture<bool>(false));
    expect(result, isTrue);
    await tester.pump();
    expect(find.text('popped inner1'), findsOneWidget);
  });

  testWidgets('`didUpdateWidget` test', (WidgetTester tester) async {
    final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
    addTearDown(provider.dispose);
    provider.value = RouteInformation(
      uri: Uri.parse('initial'),
    );
    final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
    late StateSetter setState;
    String location = 'first callback';
    final SimpleRouterDelegate routerDelegate = SimpleRouterDelegate()
      ..builder = (BuildContext context, RouteInformation? information) {
        // Creates the sub-router.
        return Column(
          children: <Widget>[
            Text(Uri.decodeComponent(information!.uri.toString())),
            StatefulBuilder(
              builder: (BuildContext context, StateSetter setter) {
                setState = setter;
                return BackButtonListener(
                  child: Container(),
                  onBackButtonPressed: () {
                    provider.value = RouteInformation(
                      uri: Uri.parse(location),
                    );
                    return SynchronousFuture<bool>(true);
                  },
                );
              },
            ),
          ],
        );
      }
      ..onPopRoute = () {
        provider.value = RouteInformation(
          uri: Uri.parse('popped outer'),
        );
        return SynchronousFuture<bool>(true);
      };
    addTearDown(routerDelegate.dispose);

    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        backButtonDispatcher: outerDispatcher,
        routeInformationProvider: provider,
        routeInformationParser: SimpleRouteInformationParser(),
        routerDelegate: routerDelegate,
      ),
    ));

    // Only update BackButtonListener widget.
    setState(() {
      location = 'second callback';
    });

    await tester.pump();
    await outerDispatcher.invokeCallback(SynchronousFuture<bool>(false));
    await tester.pump();
    expect(find.text('second callback'), findsOneWidget);
  });

  testWidgets('Router reports location if it is different from location given by OS', (WidgetTester tester) async {
    final List<RouteInformation> reportedRouteInformation = <RouteInformation>[];
    final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(
      onRouterReport: (RouteInformation info, RouteInformationReportingType type) => reportedRouteInformation.add(info),
    )..value = RouteInformation(uri: Uri.parse('/home'));
    addTearDown(provider.dispose);
    final SimpleRouterDelegate delegate = SimpleRouterDelegate(
      builder: (BuildContext _, RouteInformation? info) => Text('Current route: ${info?.uri}'),
      reportConfiguration: true,
    );
    addTearDown(delegate.dispose);

    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        routeInformationProvider: provider,
        routeInformationParser: RedirectingInformationParser(<String, RouteInformation>{
          '/doesNotExist' : RouteInformation(uri: Uri.parse('/404')),
        }),
        routerDelegate: delegate,
      ),
    ));

    expect(find.text('Current route: /home'), findsOneWidget);
    expect(reportedRouteInformation.single.uri.toString(), '/home');

    provider.value = RouteInformation(uri: Uri.parse('/doesNotExist'));
    await tester.pump();

    expect(find.text('Current route: /404'), findsOneWidget);
    expect(reportedRouteInformation[1].uri.toString(), '/404');
  });

  testWidgets('RouterInformationParser can look up dependencies and reparse', (WidgetTester tester) async {
    final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
    addTearDown(provider.dispose);
    provider.value = RouteInformation(
      uri: Uri.parse('initial'),
    );
    final BackButtonDispatcher dispatcher = RootBackButtonDispatcher();
    final SimpleRouterDelegate delegate = SimpleRouterDelegate(
      builder: (BuildContext context, RouteInformation? information) {
        return Text(Uri.decodeComponent(information!.uri.toString()));
      },
      onPopRoute: () {
        provider.value = RouteInformation(
          uri: Uri.parse('popped'),
        );
        return SynchronousFuture<bool>(true);
      },
    );
    addTearDown(delegate.dispose);
    int expectedMaxLines = 1;
    bool parserCalled = false;
    final Widget router = Router<RouteInformation>(
      routeInformationProvider: provider,
      routeInformationParser: CustomRouteInformationParser((RouteInformation information, BuildContext context) {
        parserCalled = true;
        final DefaultTextStyle style = DefaultTextStyle.of(context);
        return RouteInformation(uri: Uri.parse('${style.maxLines}'));
      }),
      routerDelegate: delegate,
      backButtonDispatcher: dispatcher,
    );
    await tester.pumpWidget(buildBoilerPlate(
      DefaultTextStyle(
        style: const TextStyle(),
        maxLines: expectedMaxLines,
        child: router,
      ),
    ));

    expect(find.text('$expectedMaxLines'), findsOneWidget);
    expect(parserCalled, isTrue);

    parserCalled = false;
    expectedMaxLines = 2;
    await tester.pumpWidget(buildBoilerPlate(
      DefaultTextStyle(
        style: const TextStyle(),
        maxLines: expectedMaxLines,
        child: router,
      ),
    ));
    await tester.pump();
    expect(find.text('$expectedMaxLines'), findsOneWidget);
    expect(parserCalled, isTrue);
  });

  testWidgets('RouterInformationParser can look up dependencies without reparsing', (WidgetTester tester) async {
    final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
    addTearDown(provider.dispose);
    provider.value = RouteInformation(
      uri: Uri.parse('initial'),
    );
    final BackButtonDispatcher dispatcher = RootBackButtonDispatcher();
    final SimpleRouterDelegate delegate = SimpleRouterDelegate(
      builder: (BuildContext context, RouteInformation? information) {
        return Text(Uri.decodeComponent(information!.uri.toString()));
      },
      onPopRoute: () {
        provider.value = RouteInformation(
            uri: Uri.parse('popped'),
        );
        return SynchronousFuture<bool>(true);
      },
    );
    addTearDown(delegate.dispose);
    const int expectedMaxLines = 1;
    bool parserCalled = false;
    final Widget router = Router<RouteInformation>(
      routeInformationProvider: provider,
      routeInformationParser: CustomRouteInformationParser((RouteInformation information, BuildContext context) {
        parserCalled = true;
        final DefaultTextStyle style = context.getInheritedWidgetOfExactType<DefaultTextStyle>()!;
        return RouteInformation(uri: Uri.parse('${style.maxLines}'));
      }),
      routerDelegate: delegate,
      backButtonDispatcher: dispatcher,
    );
    await tester.pumpWidget(buildBoilerPlate(
      DefaultTextStyle(
        style: const TextStyle(),
        maxLines: expectedMaxLines,
        child: router,
      ),
    ));

    expect(find.text('$expectedMaxLines'), findsOneWidget);
    expect(parserCalled, isTrue);

    parserCalled = false;
    const int newMaxLines = 2;
    // This rebuild should not trigger re-parsing.
    await tester.pumpWidget(buildBoilerPlate(
      DefaultTextStyle(
        style: const TextStyle(),
        maxLines: newMaxLines,
        child: router,
      ),
    ));
    await tester.pump();
    expect(find.text('$newMaxLines'), findsNothing);
    expect(find.text('$expectedMaxLines'), findsOneWidget);
    expect(parserCalled, isFalse);
  });

  testWidgets('Looks up dependencies in RouterDelegate does not trigger re-parsing', (WidgetTester tester) async {
    final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
    addTearDown(provider.dispose);
    provider.value = RouteInformation(
      uri: Uri.parse('initial'),
    );
    final BackButtonDispatcher dispatcher = RootBackButtonDispatcher();
    final SimpleRouterDelegate delegate = SimpleRouterDelegate(
      builder: (BuildContext context, RouteInformation? information) {
        final DefaultTextStyle style = DefaultTextStyle.of(context);
        return Text('${style.maxLines}');
      },
      onPopRoute: () {
        provider.value = RouteInformation(
          uri: Uri.parse('popped'),
        );
        return SynchronousFuture<bool>(true);
      },
    );
    addTearDown(delegate.dispose);
    int expectedMaxLines = 1;
    bool parserCalled = false;
    final Widget router = Router<RouteInformation>(
      routeInformationProvider: provider,
      routeInformationParser: CustomRouteInformationParser((RouteInformation information, BuildContext context) {
        parserCalled = true;
        return information;
      }),
      routerDelegate: delegate,
      backButtonDispatcher: dispatcher,
    );
    await tester.pumpWidget(buildBoilerPlate(
      DefaultTextStyle(
        style: const TextStyle(),
        maxLines: expectedMaxLines,
        child: router,
      ),
    ));

    expect(find.text('$expectedMaxLines'), findsOneWidget);
    // Initial route will be parsed regardless.
    expect(parserCalled, isTrue);

    parserCalled = false;
    expectedMaxLines = 2;
    await tester.pumpWidget(buildBoilerPlate(
      DefaultTextStyle(
        style: const TextStyle(),
        maxLines: expectedMaxLines,
        child: router,
      ),
    ));
    await tester.pump();
    expect(find.text('$expectedMaxLines'), findsOneWidget);
    expect(parserCalled, isFalse);
  });

  testWidgets('Router can initialize with RouterConfig', (WidgetTester tester) async {
    const String expected = 'text';
    final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
    addTearDown(provider.dispose);
    provider.value = RouteInformation(uri: Uri.parse('/'));
    final SimpleRouterDelegate delegate = SimpleRouterDelegate(
      builder: (_, __) => const Text(expected),
    );
    addTearDown(delegate.dispose);
    final RouterConfig<RouteInformation> config = RouterConfig<RouteInformation>(
      routeInformationProvider: provider,
      routeInformationParser: SimpleRouteInformationParser(),
      routerDelegate: delegate,
      backButtonDispatcher: RootBackButtonDispatcher(),
    );
    final Router<RouteInformation> router = Router<RouteInformation>.withConfig(config: config);
    expect(router.routerDelegate, config.routerDelegate);
    expect(router.routeInformationParser, config.routeInformationParser);
    expect(router.routeInformationProvider, config.routeInformationProvider);
    expect(router.backButtonDispatcher, config.backButtonDispatcher);

    await tester.pumpWidget(buildBoilerPlate(router));

    expect(find.text(expected), findsOneWidget);
  });

  group('RouteInformation uri api', () {
    test('can produce correct uri from location', () async {
      final RouteInformation info1 = RouteInformation(uri: Uri.parse('/a?abc=def&abc=jkl#mno'));
      expect(info1.location, '/a?abc=def&abc=jkl#mno');
      final Uri uri1 = info1.uri;
      expect(uri1.scheme, '');
      expect(uri1.host, '');
      expect(uri1.path, '/a');
      expect(uri1.fragment, 'mno');
      expect(uri1.queryParametersAll.length, 1);
      expect(uri1.queryParametersAll['abc']!.length, 2);
      expect(uri1.queryParametersAll['abc']![0], 'def');
      expect(uri1.queryParametersAll['abc']![1], 'jkl');

      final RouteInformation info2 = RouteInformation(uri: Uri.parse('1'));
      expect(info2.location, '1');
      final Uri uri2 = info2.uri;
      expect(uri2.scheme, '');
      expect(uri2.host, '');
      expect(uri2.path, '1');
      expect(uri2.fragment, '');
      expect(uri2.queryParametersAll.length, 0);
    });

    test('can produce correct location from uri', () async {
      final RouteInformation info1 = RouteInformation(uri: Uri.parse('http://mydomain.com'));
      expect(info1.uri.toString(), 'http://mydomain.com');
      expect(info1.location, '/');

      final RouteInformation info2 = RouteInformation(uri: Uri.parse('http://mydomain.com/abc?def=ghi&def=jkl#mno'));
      expect(info2.uri.toString(), 'http://mydomain.com/abc?def=ghi&def=jkl#mno');
      expect(info2.location, '/abc?def=ghi&def=jkl#mno');
    });
  });

  test('$PlatformRouteInformationProvider dispatches object creation in constructor', () async {
    Future<void> createAndDispose() async {
      PlatformRouteInformationProvider(
        initialRouteInformation: RouteInformation(uri: Uri.parse('http://google.com')),
      ).dispose();
    }
    await expectLater(
      await memoryEvents(createAndDispose, PlatformRouteInformationProvider),
      areCreateAndDispose,
    );
  });
}

Widget buildBoilerPlate(Widget child) {
  return MaterialApp(
    home: Scaffold(
      body: child,
    ),
  );
}

typedef SimpleRouterDelegateBuilder = Widget Function(BuildContext context, RouteInformation? information);
typedef SimpleRouterDelegatePopRoute = Future<bool> Function();
typedef SimpleNavigatorRouterDelegatePopPage<T> = bool Function(Route<T> route, T result);
typedef RouterReportRouterInformation = void Function(RouteInformation information, RouteInformationReportingType type);
typedef CustomRouteInformationParserCallback = RouteInformation Function(RouteInformation information, BuildContext context);

class SimpleRouteInformationParser extends RouteInformationParser<RouteInformation> {
  SimpleRouteInformationParser();

  @override
  Future<RouteInformation> parseRouteInformation(RouteInformation information) {
    return SynchronousFuture<RouteInformation>(information);
  }

  @override
  RouteInformation restoreRouteInformation(RouteInformation configuration) {
    return configuration;
  }
}

class CustomRouteInformationParser extends RouteInformationParser<RouteInformation> {
  const CustomRouteInformationParser(this.callback);

  final CustomRouteInformationParserCallback callback;

  @override
  Future<RouteInformation> parseRouteInformationWithDependencies(RouteInformation information, BuildContext context) {
    return SynchronousFuture<RouteInformation>(callback(information, context));
  }

  @override
  RouteInformation restoreRouteInformation(RouteInformation configuration) {
    return configuration;
  }
}

class SimpleRouterDelegate extends RouterDelegate<RouteInformation> with ChangeNotifier {
  SimpleRouterDelegate({
    this.builder,
    this.onPopRoute,
    this.reportConfiguration = false,
  }) {
    if (kFlutterMemoryAllocationsEnabled) {
      ChangeNotifier.maybeDispatchObjectCreation(this);
    }
  }

  RouteInformation? get routeInformation => _routeInformation;
  RouteInformation? _routeInformation;
  set routeInformation(RouteInformation? newValue) {
    _routeInformation = newValue;
    notifyListeners();
  }

  SimpleRouterDelegateBuilder? builder;
  SimpleRouterDelegatePopRoute? onPopRoute;
  final bool reportConfiguration;

  @override
  RouteInformation? get currentConfiguration {
    if (reportConfiguration) {
      return routeInformation;
    }
    return null;
  }

  @override
  Future<void> setNewRoutePath(RouteInformation configuration) {
    _routeInformation = configuration;
    return SynchronousFuture<void>(null);
  }

  @override
  Future<bool> popRoute() {
    return onPopRoute?.call() ?? SynchronousFuture<bool>(true);
  }

  @override
  Widget build(BuildContext context) => builder!(context, routeInformation);
}

class SimpleNavigatorRouterDelegate extends RouterDelegate<RouteInformation> with PopNavigatorRouterDelegateMixin<RouteInformation>, ChangeNotifier {
  SimpleNavigatorRouterDelegate({
    required this.builder,
    required this.onPopPage,
  });

  @override
  GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

  RouteInformation get routeInformation => _routeInformation;
  late RouteInformation _routeInformation;

  SimpleRouterDelegateBuilder builder;
  SimpleNavigatorRouterDelegatePopPage<void> onPopPage;

  @override
  Future<void> setNewRoutePath(RouteInformation configuration) {
    _routeInformation = configuration;
    return SynchronousFuture<void>(null);
  }

  bool _handlePopPage(Route<void> route, void data) {
    return onPopPage(route, data);
  }

  @override
  Widget build(BuildContext context) {
    return Navigator(
      key: navigatorKey,
      onPopPage: _handlePopPage,
      pages: <Page<void>>[
        // We need at least two pages for the pop to propagate through.
        // Otherwise, the navigator will bubble the pop to the system navigator.
        const MaterialPage<void>(
          child: Text('base'),
        ),
        MaterialPage<void>(
          key: ValueKey<String>(routeInformation.uri.toString()),
          child: builder(context, routeInformation),
        ),
      ],
    );
  }
}

class SimpleRouteInformationProvider extends RouteInformationProvider with ChangeNotifier {
  SimpleRouteInformationProvider({
    this.onRouterReport,
  }) {
    if (kFlutterMemoryAllocationsEnabled) {
      ChangeNotifier.maybeDispatchObjectCreation(this);
    }
  }

  RouterReportRouterInformation? onRouterReport;

  @override
  RouteInformation get value => _value;
  late RouteInformation _value;
  set value(RouteInformation newValue) {
    _value = newValue;
    notifyListeners();
  }

  @override
  void routerReportsNewRouteInformation(RouteInformation routeInformation, {RouteInformationReportingType type = RouteInformationReportingType.none}) {
    _value = routeInformation;
    onRouterReport?.call(routeInformation, type);
  }
}

class SimpleAsyncRouteInformationParser extends RouteInformationParser<RouteInformation> {
  SimpleAsyncRouteInformationParser();

  late Future<RouteInformation> parsingFuture;

  @override
  Future<RouteInformation> parseRouteInformation(RouteInformation information) {
    return parsingFuture = Future<RouteInformation>.value(information);
  }

  @override
  RouteInformation restoreRouteInformation(RouteInformation configuration) {
    return configuration;
  }
}

class CompleterRouteInformationParser extends RouteInformationParser<RouteInformation> {
  CompleterRouteInformationParser();

  late Completer<void> completer;

  @override
  Future<RouteInformation> parseRouteInformation(RouteInformation information) async {
    completer = Completer<void>();
    await completer.future;
    return SynchronousFuture<RouteInformation>(information);
  }

  @override
  RouteInformation restoreRouteInformation(RouteInformation configuration) {
    return configuration;
  }
}

class SimpleAsyncRouterDelegate extends RouterDelegate<RouteInformation> with ChangeNotifier {
  SimpleAsyncRouterDelegate({
    required this.builder,
  }) {
    if (kFlutterMemoryAllocationsEnabled) {
      ChangeNotifier.maybeDispatchObjectCreation(this);
    }
  }

  RouteInformation? get routeInformation => _routeInformation;
  RouteInformation? _routeInformation;

  SimpleRouterDelegateBuilder builder;
  late Future<void> setNewRouteFuture;

  @override
  Future<void> setNewRoutePath(RouteInformation configuration) {
    _routeInformation = configuration;
    return setNewRouteFuture = Future<void>.value();
  }

  @override
  Future<bool> popRoute() {
    return Future<bool>.value(true);
  }

  @override
  Widget build(BuildContext context) => builder(context, routeInformation);
}

class RedirectingInformationParser extends RouteInformationParser<RouteInformation> {

  RedirectingInformationParser(this.redirects);

  final Map<String, RouteInformation> redirects;

  @override
  Future<RouteInformation> parseRouteInformation(RouteInformation information) {
    return SynchronousFuture<RouteInformation>(redirects[information.uri.toString()] ?? information);
  }

  @override
  RouteInformation restoreRouteInformation(RouteInformation configuration) {
    return configuration;
  }
}
