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