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

void main() {
  testWidgets('Simple router basic functionality - synchronized', (WidgetTester tester) async {
    final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
    provider.value = const RouteInformation(
      location: 'initial',
    );
    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        routeInformationProvider: provider,
        routeInformationParser: SimpleRouteInformationParser(),
        routerDelegate: SimpleRouterDelegate(
          builder: (BuildContext context, RouteInformation? information) {
            return Text(information!.location!);
          },
        ),
      ),
    ));
    expect(find.text('initial'), findsOneWidget);

    provider.value = const RouteInformation(
      location: '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();
    provider.value = const RouteInformation(
      location: 'initial',
    );
    final SimpleAsyncRouteInformationParser parser = SimpleAsyncRouteInformationParser();
    final SimpleAsyncRouterDelegate delegate = SimpleAsyncRouterDelegate(
      builder: (BuildContext context, RouteInformation? information) {
        if (information == null) {
          return const Text('waiting');
        }
        return Text(information.location!);
      },
    );
    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 = const RouteInformation(
        location: '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();
    provider.value = const RouteInformation(
      location: 'initial',
    );
    final CompleterRouteInformationParser parser = CompleterRouteInformationParser();
    final SimpleAsyncRouterDelegate delegate = SimpleAsyncRouterDelegate(
      builder: (BuildContext context, RouteInformation? information) {
        if (information == null) {
          return const Text('waiting');
        }
        return Text(information.location!);
      },
    );
    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 = const RouteInformation(
        location: '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();
    provider.value = const RouteInformation(
      location: 'initial',
    );
    final BackButtonDispatcher dispatcher = RootBackButtonDispatcher();

    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        routeInformationProvider: provider,
        routeInformationParser: SimpleRouteInformationParser(),
        routerDelegate: SimpleRouterDelegate(
          builder: (BuildContext context, RouteInformation? information) {
            return Text(information!.location!);
          },
          onPopRoute: () {
            provider.value = const RouteInformation(
              location: 'popped',
            );
            return SynchronousFuture<bool>(true);
          },
        ),
        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();
    provider.value = const RouteInformation(
      location: 'initial',
    );
    expect(
      () {
        Router<RouteInformation>(
          routeInformationProvider: provider,
          routerDelegate: SimpleRouterDelegate(
            builder: (BuildContext context, RouteInformation? information) {
              return Text(information!.location!);
            },
          ),
        );
      },
      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();
    provider.value = const RouteInformation(
      location: 'initial',
    );
    final BackButtonDispatcher dispatcher = RootBackButtonDispatcher();
    final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate(
      builder: (BuildContext context, RouteInformation? information) {
        return Text(information!.location!);
      },
      onPopPage: (Route<void> route, void result) {
        provider.value = const RouteInformation(
          location: 'popped',
        );
        return route.didPop(result);
      },
    );
    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();
    provider.value = const RouteInformation(
      location: 'initial',
    );
    final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        backButtonDispatcher: outerDispatcher,
        routeInformationProvider: provider,
        routeInformationParser: SimpleRouteInformationParser(),
        routerDelegate: SimpleRouterDelegate(
          builder: (BuildContext context, RouteInformation? information) {
            final BackButtonDispatcher innerDispatcher = ChildBackButtonDispatcher(outerDispatcher);
            innerDispatcher.takePriority();
            // Creates the sub-router.
            return Router<RouteInformation>(
              backButtonDispatcher: innerDispatcher,
              routerDelegate: SimpleRouterDelegate(
                builder: (BuildContext context, RouteInformation? innerInformation) {
                  return Text(information!.location!);
                },
                onPopRoute: () {
                  provider.value = const RouteInformation(
                    location: 'popped inner',
                  );
                  return SynchronousFuture<bool>(true);
                },
              ),
            );
          },
          onPopRoute: () {
            provider.value = const RouteInformation(
              location: 'popped outer',
            );
            return SynchronousFuture<bool>(true);
          },
        ),
      ),
    ));
    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();
    provider.value = const RouteInformation(
      location: 'initial',
    );
    final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
    final BackButtonDispatcher innerDispatcher1 = ChildBackButtonDispatcher(outerDispatcher);
    final BackButtonDispatcher innerDispatcher2 = ChildBackButtonDispatcher(outerDispatcher);
    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        backButtonDispatcher: outerDispatcher,
        routeInformationProvider: provider,
        routeInformationParser: SimpleRouteInformationParser(),
        routerDelegate: SimpleRouterDelegate(
          builder: (BuildContext context, RouteInformation? information) {
            // Creates the sub-router.
            return Column(
              children: <Widget>[
                Text(information!.location!),
                Router<RouteInformation>(
                  backButtonDispatcher: innerDispatcher1,
                  routerDelegate: SimpleRouterDelegate(
                    builder: (BuildContext context, RouteInformation? innerInformation) {
                      return Container();
                    },
                    onPopRoute: () {
                      provider.value = const RouteInformation(
                        location: 'popped inner1',
                      );
                      return SynchronousFuture<bool>(true);
                    },
                  ),
                ),
                Router<RouteInformation>(
                  backButtonDispatcher: innerDispatcher2,
                  routerDelegate: SimpleRouterDelegate(
                    builder: (BuildContext context, RouteInformation? innerInformation) {
                      return Container();
                    },
                    onPopRoute: () {
                      provider.value = const RouteInformation(
                        location: 'popped inner2',
                      );
                      return SynchronousFuture<bool>(true);
                    },
                  ),
                ),
              ],
            );
          },
          onPopRoute: () {
            provider.value = const RouteInformation(
              location: 'popped outer',
            );
            return SynchronousFuture<bool>(true);
          },
        ),
      ),
    ));
    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);
    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        backButtonDispatcher: outerDispatcher,
        routerDelegate: SimpleRouterDelegate(
          builder: (BuildContext context, RouteInformation? information) {
            // Creates the sub-router.
            return Column(
              children: <Widget>[
                const Text('initial'),
                Router<RouteInformation>(
                  backButtonDispatcher: innerDispatcher,
                  routerDelegate: SimpleRouterDelegate(
                    builder: (BuildContext context, RouteInformation? innerInformation) {
                      return Container();
                    },
                  ),
                ),
              ],
            );
          },
        ),
      ),
    ));

    // Creates a new child back button dispatcher and rebuild, this will cause
    // the old one to be replaced and discarded.
    innerDispatcher = ChildBackButtonDispatcher(outerDispatcher);
    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        backButtonDispatcher: outerDispatcher,
        routerDelegate: SimpleRouterDelegate(
          builder: (BuildContext context, RouteInformation? information) {
            // Creates the sub-router.
            return Column(
              children: <Widget>[
                const Text('initial'),
                Router<RouteInformation>(
                  backButtonDispatcher: innerDispatcher,
                  routerDelegate: SimpleRouterDelegate(
                    builder: (BuildContext context, RouteInformation? innerInformation) {
                      return Container();
                    },
                  ),
                ),
              ],
            );
          },
        ),
      ),
    ));

    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);
    bool isPopped = false;
    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        backButtonDispatcher: outerDispatcher,
        routerDelegate: SimpleRouterDelegate(
          builder: (BuildContext context, RouteInformation? information) {
            // Creates the sub-router.
            return Router<RouteInformation>(
              backButtonDispatcher: innerDispatcher1,
              routerDelegate: SimpleRouterDelegate(
                builder: (BuildContext context, RouteInformation? innerInformation) {
                  return Router<RouteInformation>(
                    backButtonDispatcher: innerDispatcher2,
                    routerDelegate: SimpleRouterDelegate(
                      builder: (BuildContext context, RouteInformation? innerInformation) {
                        return Router<RouteInformation>(
                          backButtonDispatcher: innerDispatcher3,
                          routerDelegate: 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;
      },
    );
    final SimpleRouterDelegate delegate = SimpleRouterDelegate(
      reportConfiguration: true,
      builder: (BuildContext context, RouteInformation? information) {
        return Text(information!.location!);
      },
    );
    delegate.onPopRoute = () {
      delegate.routeInformation = const RouteInformation(
        location: 'popped',
      );
      return SynchronousFuture<bool>(true);
    };
    final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();

    provider.value = const RouteInformation(
      location: 'initial',
    );

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

    // The router should report as non navigation event if only state changes.
    reportedRouteInformation = null;
    reportedType = null;
    delegate.routeInformation = const RouteInformation(
      location: 'update',
      state: 'another state',
    );
    await tester.pump();
    expect(find.text('update'), findsOneWidget);
    expect(reportedRouteInformation!.location, '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!.location, '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;
      },
    );
    provider.value = const RouteInformation(
      location: 'initial',
    );
    final SimpleRouterDelegate delegate = SimpleRouterDelegate(reportConfiguration: true);
    delegate.builder = (BuildContext context, RouteInformation? information) {
      return ElevatedButton(
        child: Text(information!.location!),
        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!.location, 'initial');
    expect(reportedType, RouteInformationReportingType.none);
    reportedType = null;
    reportedRouteInformation = null;

    nextRouteInformation = const RouteInformation(
      location: '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!.location, '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!.location, '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;
      },
    );
    provider.value = const RouteInformation(
      location: 'initial',
    );
    final SimpleRouterDelegate delegate = SimpleRouterDelegate(reportConfiguration: true);
    delegate.builder = (BuildContext context, RouteInformation? information) {
      return ElevatedButton(
        child: Text(information!.location!),
        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!.location, 'initial');
    expect(reportingType, RouteInformationReportingType.none);
    updatedRouteInformation = null;
    reportingType = null;

    nextRouteInformation = const RouteInformation(
      location: 'update',
    );
    await tester.tap(find.byType(ElevatedButton));
    await tester.pump();
    expect(find.text('initial'), findsNothing);
    expect(find.text('update'), findsOneWidget);
    expect(updatedRouteInformation!.location, '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;
      },
    );
    provider.value = const RouteInformation(
      location: 'initial',
      state: 'state1',
    );
    final SimpleRouterDelegate delegate = SimpleRouterDelegate(reportConfiguration: true);
    delegate.builder = (BuildContext context, RouteInformation? information) {
      return ElevatedButton(
        child: Text(information!.location!),
        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!.location, 'initial');
    expect(reportingType, RouteInformationReportingType.none);
    updatedRouteInformation = null;
    reportingType = null;

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

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

    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 ServicesBinding.instance.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 ServicesBinding.instance.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 RouteInformationProvider provider = PlatformRouteInformationProvider(
      initialRouteInformation: const RouteInformation(
        location: 'initial',
      ),
    );

    log.clear();
    provider.routerReportsNewRouteInformation(const RouteInformation(location: '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>{ 'location': 'a', 'state': true, 'replace': false }),
    ]);
    log.clear();
    provider.routerReportsNewRouteInformation(const RouteInformation(location: '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>{ 'location': 'a', 'state': false, 'replace': true }),
    ]);

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

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

  testWidgets('RootBackButtonDispatcher works', (WidgetTester tester) async {
    final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
    final RouteInformationProvider provider = PlatformRouteInformationProvider(
      initialRouteInformation: const RouteInformation(
        location: 'initial',
      ),
    );
    final SimpleRouterDelegate delegate = SimpleRouterDelegate(
      reportConfiguration: true,
      builder: (BuildContext context, RouteInformation? information) {
        return Text(information!.location!);
      },
    );
    delegate.onPopRoute = () {
      delegate.routeInformation = const RouteInformation(
        location: '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 ServicesBinding.instance.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();
    provider.value = const RouteInformation(
      location: 'initial',
    );
    final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        backButtonDispatcher: outerDispatcher,
        routeInformationProvider: provider,
        routeInformationParser: SimpleRouteInformationParser(),
        routerDelegate: SimpleRouterDelegate(
          builder: (BuildContext context, RouteInformation? information) {
            // Creates the sub-router.
            return Column(
              children: <Widget>[
                Text(information!.location!),
                BackButtonListener(
                  child: Container(),
                  onBackButtonPressed: () {
                      provider.value = const RouteInformation(
                        location: 'popped inner1',
                      );
                      return SynchronousFuture<bool>(true);
                    },
                ),
              ],
            );
          },
          onPopRoute: () {
            provider.value = const RouteInformation(
              location: 'popped outer',
            );
            return SynchronousFuture<bool>(true);
          },
        ),
      ),
    ));
    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();
    provider.value = const RouteInformation(
      location: 'initial',
    );
    final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
    final SimpleRouterDelegate routerDelegate = SimpleRouterDelegate()
      ..builder = (BuildContext context, RouteInformation? information) {
            // Creates the sub-router.
            return Column(
              children: <Widget>[
                Text(information!.location!),
                BackButtonListener(
                  child: Container(),
                  onBackButtonPressed: () {
                      provider.value = const RouteInformation(
                        location: 'first callback',
                      );
                      return SynchronousFuture<bool>(true);
                    },
                ),
              ],
            );
          }
        ..onPopRoute = () {
            provider.value = const RouteInformation(
              location: 'popped outer',
            );
            return SynchronousFuture<bool>(true);
          };

    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(information!.location!),
            BackButtonListener(
              child: Container(),
              onBackButtonPressed: () {
                  provider.value = const RouteInformation(
                    location: 'second callback',
                  );
                  return SynchronousFuture<bool>(true);
                },
            ),
          ],
        );
      }
      ..onPopRoute = () {
        provider.value = const RouteInformation(
          location: '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();
    provider.value = const RouteInformation(
      location: 'initial',
    );
    final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
    final SimpleRouterDelegate routerDelegate = SimpleRouterDelegate()
      ..builder = (BuildContext context, RouteInformation? information) {
            // Creates the sub-router.
            return Column(
              children: <Widget>[
                Text(information!.location!),
                BackButtonListener(
                  child: Container(),
                  onBackButtonPressed: () {
                      provider.value = const RouteInformation(
                        location: 'first callback',
                      );
                      return SynchronousFuture<bool>(true);
                    },
                ),
              ],
            );
          }
        ..onPopRoute = () {
            provider.value = const RouteInformation(
              location: 'popped outer',
            );
            return SynchronousFuture<bool>(true);
          };

    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(information!.location!),
          ],
        );
      }
      ..onPopRoute = () {
        provider.value = const RouteInformation(
          location: '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();
    provider.value = const RouteInformation(
      location: 'initial',
    );
    final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        backButtonDispatcher: outerDispatcher,
        routeInformationProvider: provider,
        routeInformationParser: SimpleRouteInformationParser(),
        routerDelegate: SimpleRouterDelegate(
          builder: (BuildContext context, RouteInformation? information) {
            // Creates the sub-router.
            return Column(
              children: <Widget>[
                Text(information!.location!),
                BackButtonListener(
                  child: BackButtonListener(
                    child: Container(),
                    onBackButtonPressed: () {
                      provider.value = const RouteInformation(
                        location: 'popped inner2',
                      );
                      return SynchronousFuture<bool>(true);
                    },
                  ),
                  onBackButtonPressed: () {
                      provider.value = const RouteInformation(
                        location: 'popped inner1',
                      );
                      return SynchronousFuture<bool>(true);
                    },
                ),
              ],
            );
          },
          onPopRoute: () {
            provider.value = const RouteInformation(
              location: 'popped outer',
            );
            return SynchronousFuture<bool>(true);
          },
        ),
      ),
    ));
    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();
    provider.value = const RouteInformation(
      location: 'initial',
    );
    final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        backButtonDispatcher: outerDispatcher,
        routeInformationProvider: provider,
        routeInformationParser: SimpleRouteInformationParser(),
        routerDelegate: SimpleRouterDelegate(
          builder: (BuildContext context, RouteInformation? information) {
            // Creates the sub-router.
            return Column(
              children: <Widget>[
                Text(information!.location!),
                BackButtonListener(
                  child: BackButtonListener(
                    child: Container(),
                    onBackButtonPressed: () {
                      provider.value = const RouteInformation(
                        location: 'popped inner2',
                      );
                      return SynchronousFuture<bool>(false);
                    },
                  ),
                  onBackButtonPressed: () {
                      provider.value = const RouteInformation(
                        location: 'popped inner1',
                      );
                      return SynchronousFuture<bool>(true);
                    },
                ),
              ],
            );
          },
          onPopRoute: () {
            provider.value = const RouteInformation(
              location: 'popped outer',
            );
            return SynchronousFuture<bool>(true);
          },
        ),
      ),
    ));
    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();
    provider.value = const RouteInformation(
      location: '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(information!.location!),
            StatefulBuilder(
              builder: (BuildContext context, StateSetter setter) {
                setState = setter;
                return BackButtonListener(
                  child: Container(),
                  onBackButtonPressed: () {
                    provider.value = RouteInformation(
                      location: location,
                    );
                    return SynchronousFuture<bool>(true);
                  },
                );
              },
            ),
          ],
        );
      }
      ..onPopRoute = () {
        provider.value = const RouteInformation(
          location: 'popped outer',
        );
        return SynchronousFuture<bool>(true);
      };

    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 = const RouteInformation(location: '/home');

    await tester.pumpWidget(buildBoilerPlate(
      Router<RouteInformation>(
        routeInformationProvider: provider,
        routeInformationParser: RedirectingInformationParser(<String, RouteInformation>{
          '/doesNotExist' : const RouteInformation(location: '/404'),
        }),
        routerDelegate: SimpleRouterDelegate(
          builder: (BuildContext _, RouteInformation? info) => Text('Current route: ${info?.location}'),
          reportConfiguration: true,
        ),
      ),
    ));

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

    provider.value = const RouteInformation(location: '/doesNotExist');
    await tester.pump();

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

  testWidgets('RouterInformationParser can look up dependencies and reparse', (WidgetTester tester) async {
    final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
    provider.value = const RouteInformation(
      location: 'initial',
    );
    final BackButtonDispatcher dispatcher = RootBackButtonDispatcher();
    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(location: '${style.maxLines}');
      }),
      routerDelegate: SimpleRouterDelegate(
        builder: (BuildContext context, RouteInformation? information) {
          return Text(information!.location!);
        },
        onPopRoute: () {
          provider.value = const RouteInformation(
            location: 'popped',
          );
          return SynchronousFuture<bool>(true);
        },
      ),
      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();
    provider.value = const RouteInformation(
      location: 'initial',
    );
    final BackButtonDispatcher dispatcher = RootBackButtonDispatcher();
    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.getElementForInheritedWidgetOfExactType<DefaultTextStyle>()!.widget as DefaultTextStyle;
        return RouteInformation(location: '${style.maxLines}');
      }),
      routerDelegate: SimpleRouterDelegate(
        builder: (BuildContext context, RouteInformation? information) {
          return Text(information!.location!);
        },
        onPopRoute: () {
          provider.value = const RouteInformation(
            location: 'popped',
          );
          return SynchronousFuture<bool>(true);
        },
      ),
      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();
    provider.value = const RouteInformation(
      location: 'initial',
    );
    final BackButtonDispatcher dispatcher = RootBackButtonDispatcher();
    int expectedMaxLines = 1;
    bool parserCalled = false;
    final Widget router = Router<RouteInformation>(
      routeInformationProvider: provider,
      routeInformationParser: CustomRouteInformationParser((RouteInformation information, BuildContext context) {
        parserCalled = true;
        return information;
      }),
      routerDelegate: SimpleRouterDelegate(
        builder: (BuildContext context, RouteInformation? information) {
          final DefaultTextStyle style = DefaultTextStyle.of(context);
          return Text('${style.maxLines}');
        },
        onPopRoute: () {
          provider.value = const RouteInformation(
            location: 'popped',
          );
          return SynchronousFuture<bool>(true);
        },
      ),
      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 RouterConfig<RouteInformation> config = RouterConfig<RouteInformation>(
      routeInformationProvider: SimpleRouteInformationProvider()..value = const RouteInformation(location: '/'),
      routeInformationParser: SimpleRouteInformationParser(),
      routerDelegate: SimpleRouterDelegate(
        builder: (_, __) => const Text(expected),
      ),
      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);
  });
}

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

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

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,
  });

  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;
  set routeInformation(RouteInformation newValue) {
    _routeInformation = newValue;
    notifyListeners();
  }

  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.location!),
          child: builder(context, routeInformation),
        ),
      ],
    );
  }
}

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

  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,
  });

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

  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.location] ?? information);
  }

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