Unverified Commit 2c3db435 authored by Kostia Sokolovskyi's avatar Kostia Sokolovskyi Committed by GitHub

_RouterState should dispose created _RestorableRouteInformation. (#136556)

### Description
- Fixes https://github.com/flutter/flutter/issues/134205.

### Tests
- Removes ignoring the `_RestorableRouteInformation` leak from `cupertino/app_test.dart`;
- Removes ignoring the `_RestorableRouteInformation` leak from `material/app_test.dart`;
- Removes ignoring the `_RestorableRouteInformation` leak from `widgets/app_test.dart`;
- Removes ignoring the `_RestorableRouteInformation` leak from `widgets/route_notification_messages_test.dart`;
- Removes ignoring the `_RestorableRouteInformation` leak from `widgets/router_restoration_test.dart`;
- Updates `widgets/router_test.dart` to use `testWidgetsWithLeakTracking`.
parent 5b7e9d60
...@@ -632,6 +632,10 @@ class _RouterState<T> extends State<Router<T>> with RestorationMixin { ...@@ -632,6 +632,10 @@ class _RouterState<T> extends State<Router<T>> with RestorationMixin {
} }
void _reportRouteInformation(Duration timestamp) { void _reportRouteInformation(Duration timestamp) {
if (!mounted) {
return;
}
assert(_routeInformationReportingTaskScheduled); assert(_routeInformationReportingTaskScheduled);
_routeInformationReportingTaskScheduled = false; _routeInformationReportingTaskScheduled = false;
...@@ -726,6 +730,7 @@ class _RouterState<T> extends State<Router<T>> with RestorationMixin { ...@@ -726,6 +730,7 @@ class _RouterState<T> extends State<Router<T>> with RestorationMixin {
@override @override
void dispose() { void dispose() {
_routeInformation.dispose();
widget.routeInformationProvider?.removeListener(_handleRouteInformationProviderNotification); widget.routeInformationProvider?.removeListener(_handleRouteInformationProviderNotification);
widget.backButtonDispatcher?.removeCallback(_handleBackButtonDispatcherNotification); widget.backButtonDispatcher?.removeCallback(_handleBackButtonDispatcherNotification);
widget.routerDelegate.removeListener(_handleRouterDelegateNotification); widget.routerDelegate.removeListener(_handleRouterDelegateNotification);
......
...@@ -178,12 +178,7 @@ void main() { ...@@ -178,12 +178,7 @@ void main() {
await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { });
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(find.text('popped'), findsOneWidget); expect(find.text('popped'), findsOneWidget);
}, });
// TODO(polina-c): remove after fixing
// https://github.com/flutter/flutter/issues/134205
leakTrackingTestConfig: const LeakTrackingTestConfig(
allowAllNotDisposed: true,
));
testWidgetsWithLeakTracking('CupertinoApp.router route information parser is optional', (WidgetTester tester) async { testWidgetsWithLeakTracking('CupertinoApp.router route information parser is optional', (WidgetTester tester) async {
final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate( final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate(
...@@ -209,12 +204,7 @@ void main() { ...@@ -209,12 +204,7 @@ void main() {
await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { });
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(find.text('popped'), findsOneWidget); expect(find.text('popped'), findsOneWidget);
}, });
// TODO(polina-c): remove after fixing
// https://github.com/flutter/flutter/issues/134205
leakTrackingTestConfig: const LeakTrackingTestConfig(
allowAllNotDisposed: true,
));
testWidgetsWithLeakTracking('CupertinoApp.router throw if route information provider is provided but no route information parser', (WidgetTester tester) async { testWidgetsWithLeakTracking('CupertinoApp.router throw if route information provider is provided but no route information parser', (WidgetTester tester) async {
final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate( final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate(
...@@ -300,12 +290,7 @@ void main() { ...@@ -300,12 +290,7 @@ void main() {
await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { });
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(find.text('popped'), findsOneWidget); expect(find.text('popped'), findsOneWidget);
}, });
// TODO(polina-c): remove after fixing
// https://github.com/flutter/flutter/issues/134205
leakTrackingTestConfig: const LeakTrackingTestConfig(
allowAllNotDisposed: true,
));
testWidgetsWithLeakTracking('CupertinoApp has correct default ScrollBehavior', (WidgetTester tester) async { testWidgetsWithLeakTracking('CupertinoApp has correct default ScrollBehavior', (WidgetTester tester) async {
late BuildContext capturedContext; late BuildContext capturedContext;
......
...@@ -1114,12 +1114,7 @@ void main() { ...@@ -1114,12 +1114,7 @@ void main() {
await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { });
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(find.text('popped'), findsOneWidget); expect(find.text('popped'), findsOneWidget);
}, });
// TODO(polina-c): remove after fixing
// https://github.com/flutter/flutter/issues/134205
leakTrackingTestConfig: const LeakTrackingTestConfig(
allowAllNotDisposed: true,
));
testWidgetsWithLeakTracking('MaterialApp.router route information parser is optional', (WidgetTester tester) async { testWidgetsWithLeakTracking('MaterialApp.router route information parser is optional', (WidgetTester tester) async {
final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate( final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate(
...@@ -1145,12 +1140,7 @@ void main() { ...@@ -1145,12 +1140,7 @@ void main() {
await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { });
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(find.text('popped'), findsOneWidget); expect(find.text('popped'), findsOneWidget);
}, });
// TODO(polina-c): remove after fixing
// https://github.com/flutter/flutter/issues/134205
leakTrackingTestConfig: const LeakTrackingTestConfig(
allowAllNotDisposed: true,
));
testWidgetsWithLeakTracking('MaterialApp.router throw if route information provider is provided but no route information parser', (WidgetTester tester) async { testWidgetsWithLeakTracking('MaterialApp.router throw if route information provider is provided but no route information parser', (WidgetTester tester) async {
final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate( final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate(
...@@ -1236,12 +1226,7 @@ void main() { ...@@ -1236,12 +1226,7 @@ void main() {
await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { });
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(find.text('popped'), findsOneWidget); expect(find.text('popped'), findsOneWidget);
}, });
// TODO(polina-c): remove after fixing
// https://github.com/flutter/flutter/issues/134205
leakTrackingTestConfig: const LeakTrackingTestConfig(
allowAllNotDisposed: true,
));
testWidgetsWithLeakTracking('MaterialApp.builder can build app without a Navigator', (WidgetTester tester) async { testWidgetsWithLeakTracking('MaterialApp.builder can build app without a Navigator', (WidgetTester tester) async {
Widget? builderChild; Widget? builderChild;
......
...@@ -304,12 +304,7 @@ void main() { ...@@ -304,12 +304,7 @@ void main() {
await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { });
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(find.text('popped'), findsOneWidget); expect(find.text('popped'), findsOneWidget);
}, });
leakTrackingTestConfig: const LeakTrackingTestConfig(
// TODO(ksokolovskyi): remove after fixing
// https://github.com/flutter/flutter/issues/134205
notDisposedAllowList: <String, int?> {'_RestorableRouteInformation': 1},
));
testWidgetsWithLeakTracking('WidgetsApp.router route information parser is optional', (WidgetTester tester) async { testWidgetsWithLeakTracking('WidgetsApp.router route information parser is optional', (WidgetTester tester) async {
final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate( final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate(
...@@ -336,12 +331,7 @@ void main() { ...@@ -336,12 +331,7 @@ void main() {
await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { });
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(find.text('popped'), findsOneWidget); expect(find.text('popped'), findsOneWidget);
}, });
leakTrackingTestConfig: const LeakTrackingTestConfig(
// TODO(ksokolovskyi): remove after fixing
// https://github.com/flutter/flutter/issues/134205
notDisposedAllowList: <String, int?> {'_RestorableRouteInformation': 1},
));
testWidgetsWithLeakTracking('WidgetsApp.router throw if route information provider is provided but no route information parser', (WidgetTester tester) async { testWidgetsWithLeakTracking('WidgetsApp.router throw if route information provider is provided but no route information parser', (WidgetTester tester) async {
final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate( final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate(
...@@ -432,12 +422,7 @@ void main() { ...@@ -432,12 +422,7 @@ void main() {
await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { }); await tester.binding.defaultBinaryMessenger.handlePlatformMessage('flutter/navigation', message, (_) { });
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(find.text('popped'), findsOneWidget); expect(find.text('popped'), findsOneWidget);
}, });
leakTrackingTestConfig: const LeakTrackingTestConfig(
// TODO(ksokolovskyi): remove after fixing
// https://github.com/flutter/flutter/issues/134205
notDisposedAllowList: <String, int?> {'_RestorableRouteInformation': 1},
));
testWidgetsWithLeakTracking('WidgetsApp.router has correct default', (WidgetTester tester) async { testWidgetsWithLeakTracking('WidgetsApp.router has correct default', (WidgetTester tester) async {
final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate( final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate(
...@@ -453,12 +438,7 @@ void main() { ...@@ -453,12 +438,7 @@ void main() {
color: const Color(0xFF123456), color: const Color(0xFF123456),
)); ));
expect(find.text('/'), findsOneWidget); expect(find.text('/'), findsOneWidget);
}, });
leakTrackingTestConfig: const LeakTrackingTestConfig(
// TODO(ksokolovskyi): remove after fixing
// https://github.com/flutter/flutter/issues/134205
notDisposedAllowList: <String, int?> {'_RestorableRouteInformation': 1},
));
testWidgetsWithLeakTracking('WidgetsApp has correct default ScrollBehavior', (WidgetTester tester) async { testWidgetsWithLeakTracking('WidgetsApp has correct default ScrollBehavior', (WidgetTester tester) async {
late BuildContext capturedContext; late BuildContext capturedContext;
......
...@@ -316,12 +316,7 @@ void main() { ...@@ -316,12 +316,7 @@ void main() {
'replace': false, 'replace': false,
}), }),
]); ]);
}, });
leakTrackingTestConfig: const LeakTrackingTestConfig(
// TODO(ksokolovskyi): remove after fixing
// https://github.com/flutter/flutter/issues/134205
notDisposedAllowList: <String, int?> {'_RestorableRouteInformation': 1},
));
} }
typedef SimpleRouterDelegateBuilder = Widget Function(BuildContext, RouteInformation); typedef SimpleRouterDelegateBuilder = Widget Function(BuildContext, RouteInformation);
......
...@@ -40,12 +40,7 @@ void main() { ...@@ -40,12 +40,7 @@ void main() {
expect(find.text('Current config: /foo'), findsOneWidget); expect(find.text('Current config: /foo'), findsOneWidget);
expect(delegate().newRoutePaths, isEmpty); expect(delegate().newRoutePaths, isEmpty);
expect(delegate().restoredRoutePaths, <String>['/foo', '/foo']); expect(delegate().restoredRoutePaths, <String>['/foo', '/foo']);
}, });
leakTrackingTestConfig: const LeakTrackingTestConfig(
// TODO(ksokolovskyi): remove after fixing
// https://github.com/flutter/flutter/issues/134205
notDisposedAllowList: <String, int?> {'_RestorableRouteInformation': 2},
));
testWidgets('Router state restoration with RouteInformationProvider', (WidgetTester tester) async { testWidgets('Router state restoration with RouteInformationProvider', (WidgetTester tester) async {
final UniqueKey router = UniqueKey(); final UniqueKey router = UniqueKey();
......
...@@ -11,20 +11,24 @@ import 'package:flutter_test/flutter_test.dart'; ...@@ -11,20 +11,24 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() { void main() {
testWidgets('Simple router basic functionality - synchronized', (WidgetTester tester) async { testWidgetsWithLeakTracking('Simple router basic functionality - synchronized', (WidgetTester tester) async {
final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(); final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
addTearDown(provider.dispose);
provider.value = RouteInformation( provider.value = RouteInformation(
uri: Uri.parse('initial'), uri: Uri.parse('initial'),
); );
final SimpleRouterDelegate delegate = SimpleRouterDelegate(
builder: (BuildContext context, RouteInformation? information) {
return Text(Uri.decodeComponent(information!.uri.toString()));
},
);
addTearDown(delegate.dispose);
await tester.pumpWidget(buildBoilerPlate( await tester.pumpWidget(buildBoilerPlate(
Router<RouteInformation>( Router<RouteInformation>(
routeInformationProvider: provider, routeInformationProvider: provider,
routeInformationParser: SimpleRouteInformationParser(), routeInformationParser: SimpleRouteInformationParser(),
routerDelegate: SimpleRouterDelegate( routerDelegate: delegate,
builder: (BuildContext context, RouteInformation? information) {
return Text(Uri.decodeComponent(information!.uri.toString()));
},
),
), ),
)); ));
expect(find.text('initial'), findsOneWidget); expect(find.text('initial'), findsOneWidget);
...@@ -37,8 +41,9 @@ void main() { ...@@ -37,8 +41,9 @@ void main() {
expect(find.text('update'), findsOneWidget); expect(find.text('update'), findsOneWidget);
}); });
testWidgets('Simple router basic functionality - asynchronized', (WidgetTester tester) async { testWidgetsWithLeakTracking('Simple router basic functionality - asynchronized', (WidgetTester tester) async {
final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(); final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
addTearDown(provider.dispose);
provider.value = RouteInformation( provider.value = RouteInformation(
uri: Uri.parse('initial'), uri: Uri.parse('initial'),
); );
...@@ -51,6 +56,8 @@ void main() { ...@@ -51,6 +56,8 @@ void main() {
return Text(information.uri.toString()); return Text(information.uri.toString());
}, },
); );
addTearDown(delegate.dispose);
await tester.runAsync(() async { await tester.runAsync(() async {
await tester.pumpWidget(buildBoilerPlate( await tester.pumpWidget(buildBoilerPlate(
Router<RouteInformation>( Router<RouteInformation>(
...@@ -81,8 +88,9 @@ void main() { ...@@ -81,8 +88,9 @@ void main() {
}); });
}); });
testWidgets('Interrupts route parsing should not crash', (WidgetTester tester) async { testWidgetsWithLeakTracking('Interrupts route parsing should not crash', (WidgetTester tester) async {
final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(); final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
addTearDown(provider.dispose);
provider.value = RouteInformation( provider.value = RouteInformation(
uri: Uri.parse('initial'), uri: Uri.parse('initial'),
); );
...@@ -95,6 +103,8 @@ void main() { ...@@ -95,6 +103,8 @@ void main() {
return Text(information.uri.toString()); return Text(information.uri.toString());
}, },
); );
addTearDown(delegate.dispose);
await tester.runAsync(() async { await tester.runAsync(() async {
await tester.pumpWidget(buildBoilerPlate( await tester.pumpWidget(buildBoilerPlate(
Router<RouteInformation>( Router<RouteInformation>(
...@@ -130,7 +140,7 @@ void main() { ...@@ -130,7 +140,7 @@ void main() {
}); });
}); });
testWidgets('Router.maybeOf can be null', (WidgetTester tester) async { testWidgetsWithLeakTracking('Router.maybeOf can be null', (WidgetTester tester) async {
final GlobalKey key = GlobalKey(); final GlobalKey key = GlobalKey();
await tester.pumpWidget(buildBoilerPlate( await tester.pumpWidget(buildBoilerPlate(
Text('dummy', key: key), Text('dummy', key: key),
...@@ -147,18 +157,14 @@ void main() { ...@@ -147,18 +157,14 @@ void main() {
); );
}); });
testWidgets('Simple router can handle pop route', (WidgetTester tester) async { testWidgetsWithLeakTracking('Simple router can handle pop route', (WidgetTester tester) async {
final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(); final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
addTearDown(provider.dispose);
provider.value = RouteInformation( provider.value = RouteInformation(
uri: Uri.parse('initial'), uri: Uri.parse('initial'),
); );
final BackButtonDispatcher dispatcher = RootBackButtonDispatcher(); final BackButtonDispatcher dispatcher = RootBackButtonDispatcher();
final SimpleRouterDelegate delegate = SimpleRouterDelegate(
await tester.pumpWidget(buildBoilerPlate(
Router<RouteInformation>(
routeInformationProvider: provider,
routeInformationParser: SimpleRouteInformationParser(),
routerDelegate: SimpleRouterDelegate(
builder: (BuildContext context, RouteInformation? information) { builder: (BuildContext context, RouteInformation? information) {
return Text(Uri.decodeComponent(information!.uri.toString())); return Text(Uri.decodeComponent(information!.uri.toString()));
}, },
...@@ -168,7 +174,14 @@ void main() { ...@@ -168,7 +174,14 @@ void main() {
); );
return SynchronousFuture<bool>(true); return SynchronousFuture<bool>(true);
}, },
), );
addTearDown(delegate.dispose);
await tester.pumpWidget(buildBoilerPlate(
Router<RouteInformation>(
routeInformationProvider: provider,
routeInformationParser: SimpleRouteInformationParser(),
routerDelegate: delegate,
backButtonDispatcher: dispatcher, backButtonDispatcher: dispatcher,
), ),
)); ));
...@@ -186,20 +199,24 @@ void main() { ...@@ -186,20 +199,24 @@ void main() {
expect(find.text('popped'), findsOneWidget); expect(find.text('popped'), findsOneWidget);
}); });
testWidgets('Router throw when passing routeInformationProvider without routeInformationParser', (WidgetTester tester) async { testWidgetsWithLeakTracking('Router throw when passing routeInformationProvider without routeInformationParser', (WidgetTester tester) async {
final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(); final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
addTearDown(provider.dispose);
provider.value = RouteInformation( provider.value = RouteInformation(
uri: Uri.parse('initial'), uri: Uri.parse('initial'),
); );
final SimpleRouterDelegate delegate = SimpleRouterDelegate(
builder: (BuildContext context, RouteInformation? information) {
return Text(Uri.decodeComponent(information!.uri.toString()));
},
);
addTearDown(delegate.dispose);
expect( expect(
() { () {
Router<RouteInformation>( Router<RouteInformation>(
routeInformationProvider: provider, routeInformationProvider: provider,
routerDelegate: SimpleRouterDelegate( routerDelegate: delegate,
builder: (BuildContext context, RouteInformation? information) {
return Text(Uri.decodeComponent(information!.uri.toString()));
},
),
); );
}, },
throwsA(isAssertionError.having( throwsA(isAssertionError.having(
...@@ -210,8 +227,9 @@ void main() { ...@@ -210,8 +227,9 @@ void main() {
); );
}); });
testWidgets('PopNavigatorRouterDelegateMixin works', (WidgetTester tester) async { testWidgetsWithLeakTracking('PopNavigatorRouterDelegateMixin works', (WidgetTester tester) async {
final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(); final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
addTearDown(provider.dispose);
provider.value = RouteInformation( provider.value = RouteInformation(
uri: Uri.parse('initial'), uri: Uri.parse('initial'),
); );
...@@ -227,6 +245,8 @@ void main() { ...@@ -227,6 +245,8 @@ void main() {
return route.didPop(result); return route.didPop(result);
}, },
); );
addTearDown(delegate.dispose);
await tester.pumpWidget(buildBoilerPlate( await tester.pumpWidget(buildBoilerPlate(
Router<RouteInformation>( Router<RouteInformation>(
routeInformationProvider: provider, routeInformationProvider: provider,
...@@ -263,25 +283,18 @@ void main() { ...@@ -263,25 +283,18 @@ void main() {
expect(find.text('popped'), findsOneWidget); expect(find.text('popped'), findsOneWidget);
}); });
testWidgets('Nested routers back button dispatcher works', (WidgetTester tester) async { testWidgetsWithLeakTracking('Nested routers back button dispatcher works', (WidgetTester tester) async {
final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(); final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
addTearDown(provider.dispose);
provider.value = RouteInformation( provider.value = RouteInformation(
uri: Uri.parse('initial'), uri: Uri.parse('initial'),
); );
final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher(); final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
await tester.pumpWidget(buildBoilerPlate( final SimpleRouterDelegate outerDelegate = SimpleRouterDelegate(
Router<RouteInformation>(
backButtonDispatcher: outerDispatcher,
routeInformationProvider: provider,
routeInformationParser: SimpleRouteInformationParser(),
routerDelegate: SimpleRouterDelegate(
builder: (BuildContext context, RouteInformation? information) { builder: (BuildContext context, RouteInformation? information) {
final BackButtonDispatcher innerDispatcher = ChildBackButtonDispatcher(outerDispatcher); final BackButtonDispatcher innerDispatcher = ChildBackButtonDispatcher(outerDispatcher);
innerDispatcher.takePriority(); innerDispatcher.takePriority();
// Creates the sub-router. final SimpleRouterDelegate innerDelegate = SimpleRouterDelegate(
return Router<RouteInformation>(
backButtonDispatcher: innerDispatcher,
routerDelegate: SimpleRouterDelegate(
builder: (BuildContext context, RouteInformation? innerInformation) { builder: (BuildContext context, RouteInformation? innerInformation) {
return Text(Uri.decodeComponent(information!.uri.toString())); return Text(Uri.decodeComponent(information!.uri.toString()));
}, },
...@@ -291,7 +304,12 @@ void main() { ...@@ -291,7 +304,12 @@ void main() {
); );
return SynchronousFuture<bool>(true); return SynchronousFuture<bool>(true);
}, },
), );
addTearDown(innerDelegate.dispose);
// Creates the sub-router.
return Router<RouteInformation>(
backButtonDispatcher: innerDispatcher,
routerDelegate: innerDelegate,
); );
}, },
onPopRoute: () { onPopRoute: () {
...@@ -300,7 +318,15 @@ void main() { ...@@ -300,7 +318,15 @@ void main() {
); );
return SynchronousFuture<bool>(true); return SynchronousFuture<bool>(true);
}, },
), );
addTearDown(outerDelegate.dispose);
await tester.pumpWidget(buildBoilerPlate(
Router<RouteInformation>(
backButtonDispatcher: outerDispatcher,
routeInformationProvider: provider,
routeInformationParser: SimpleRouteInformationParser(),
routerDelegate: outerDelegate,
), ),
)); ));
expect(find.text('initial'), findsOneWidget); expect(find.text('initial'), findsOneWidget);
...@@ -313,28 +339,29 @@ void main() { ...@@ -313,28 +339,29 @@ void main() {
expect(find.text('popped inner'), findsOneWidget); expect(find.text('popped inner'), findsOneWidget);
}); });
testWidgets('Nested router back button dispatcher works for multiple children', (WidgetTester tester) async { testWidgetsWithLeakTracking('Nested router back button dispatcher works for multiple children', (WidgetTester tester) async {
final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(); final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
addTearDown(provider.dispose);
provider.value = RouteInformation( provider.value = RouteInformation(
uri: Uri.parse('initial'), uri: Uri.parse('initial'),
); );
final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher(); final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
final BackButtonDispatcher innerDispatcher1 = ChildBackButtonDispatcher(outerDispatcher); final BackButtonDispatcher innerDispatcher1 = ChildBackButtonDispatcher(outerDispatcher);
final BackButtonDispatcher innerDispatcher2 = ChildBackButtonDispatcher(outerDispatcher); final BackButtonDispatcher innerDispatcher2 = ChildBackButtonDispatcher(outerDispatcher);
await tester.pumpWidget(buildBoilerPlate( final SimpleRouterDelegate outerDelegate = SimpleRouterDelegate(
Router<RouteInformation>(
backButtonDispatcher: outerDispatcher,
routeInformationProvider: provider,
routeInformationParser: SimpleRouteInformationParser(),
routerDelegate: SimpleRouterDelegate(
builder: (BuildContext context, RouteInformation? information) { builder: (BuildContext context, RouteInformation? information) {
late final SimpleRouterDelegate innerDelegate1;
addTearDown(() => innerDelegate1.dispose());
late final SimpleRouterDelegate innerDelegate2;
addTearDown(() => innerDelegate2.dispose());
// Creates the sub-router. // Creates the sub-router.
return Column( return Column(
children: <Widget>[ children: <Widget>[
Text(Uri.decodeComponent(information!.uri.toString())), Text(Uri.decodeComponent(information!.uri.toString())),
Router<RouteInformation>( Router<RouteInformation>(
backButtonDispatcher: innerDispatcher1, backButtonDispatcher: innerDispatcher1,
routerDelegate: SimpleRouterDelegate( routerDelegate: innerDelegate1 = SimpleRouterDelegate(
builder: (BuildContext context, RouteInformation? innerInformation) { builder: (BuildContext context, RouteInformation? innerInformation) {
return Container(); return Container();
}, },
...@@ -348,7 +375,7 @@ void main() { ...@@ -348,7 +375,7 @@ void main() {
), ),
Router<RouteInformation>( Router<RouteInformation>(
backButtonDispatcher: innerDispatcher2, backButtonDispatcher: innerDispatcher2,
routerDelegate: SimpleRouterDelegate( routerDelegate: innerDelegate2 = SimpleRouterDelegate(
builder: (BuildContext context, RouteInformation? innerInformation) { builder: (BuildContext context, RouteInformation? innerInformation) {
return Container(); return Container();
}, },
...@@ -369,7 +396,15 @@ void main() { ...@@ -369,7 +396,15 @@ void main() {
); );
return SynchronousFuture<bool>(true); return SynchronousFuture<bool>(true);
}, },
), );
addTearDown(outerDelegate.dispose);
await tester.pumpWidget(buildBoilerPlate(
Router<RouteInformation>(
backButtonDispatcher: outerDispatcher,
routeInformationProvider: provider,
routeInformationParser: SimpleRouteInformationParser(),
routerDelegate: outerDelegate,
), ),
)); ));
expect(find.text('initial'), findsOneWidget); expect(find.text('initial'), findsOneWidget);
...@@ -398,88 +433,107 @@ void main() { ...@@ -398,88 +433,107 @@ void main() {
expect(find.text('popped inner2'), findsOneWidget); expect(find.text('popped inner2'), findsOneWidget);
}); });
testWidgets('ChildBackButtonDispatcher can be replaced without calling the takePriority', (WidgetTester tester) async { testWidgetsWithLeakTracking('ChildBackButtonDispatcher can be replaced without calling the takePriority', (WidgetTester tester) async {
final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher(); final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
BackButtonDispatcher innerDispatcher = ChildBackButtonDispatcher(outerDispatcher); BackButtonDispatcher innerDispatcher = ChildBackButtonDispatcher(outerDispatcher);
await tester.pumpWidget(buildBoilerPlate( final SimpleRouterDelegate outerDelegate1 = SimpleRouterDelegate(
Router<RouteInformation>(
backButtonDispatcher: outerDispatcher,
routerDelegate: SimpleRouterDelegate(
builder: (BuildContext context, RouteInformation? information) { builder: (BuildContext context, RouteInformation? information) {
final SimpleRouterDelegate innerDelegate1 = SimpleRouterDelegate(
builder: (BuildContext context, RouteInformation? innerInformation) {
return Container();
},
);
addTearDown(innerDelegate1.dispose);
// Creates the sub-router. // Creates the sub-router.
return Column( return Column(
children: <Widget>[ children: <Widget>[
const Text('initial'), const Text('initial'),
Router<RouteInformation>( Router<RouteInformation>(
backButtonDispatcher: innerDispatcher, backButtonDispatcher: innerDispatcher,
routerDelegate: SimpleRouterDelegate( routerDelegate: innerDelegate1,
builder: (BuildContext context, RouteInformation? innerInformation) {
return Container();
},
),
), ),
], ],
); );
}, },
), );
addTearDown(outerDelegate1.dispose);
await tester.pumpWidget(buildBoilerPlate(
Router<RouteInformation>(
backButtonDispatcher: outerDispatcher,
routerDelegate: outerDelegate1,
), ),
)); ));
// Creates a new child back button dispatcher and rebuild, this will cause // Creates a new child back button dispatcher and rebuild, this will cause
// the old one to be replaced and discarded. // the old one to be replaced and discarded.
innerDispatcher = ChildBackButtonDispatcher(outerDispatcher); innerDispatcher = ChildBackButtonDispatcher(outerDispatcher);
await tester.pumpWidget(buildBoilerPlate( final SimpleRouterDelegate outerDelegate2 = SimpleRouterDelegate(
Router<RouteInformation>(
backButtonDispatcher: outerDispatcher,
routerDelegate: SimpleRouterDelegate(
builder: (BuildContext context, RouteInformation? information) { builder: (BuildContext context, RouteInformation? information) {
final SimpleRouterDelegate innerDelegate2 = SimpleRouterDelegate(
builder: (BuildContext context, RouteInformation? innerInformation) {
return Container();
},
);
addTearDown(innerDelegate2.dispose);
// Creates the sub-router. // Creates the sub-router.
return Column( return Column(
children: <Widget>[ children: <Widget>[
const Text('initial'), const Text('initial'),
Router<RouteInformation>( Router<RouteInformation>(
backButtonDispatcher: innerDispatcher, backButtonDispatcher: innerDispatcher,
routerDelegate: SimpleRouterDelegate( routerDelegate: innerDelegate2,
builder: (BuildContext context, RouteInformation? innerInformation) {
return Container();
},
),
), ),
], ],
); );
}, },
), );
addTearDown(outerDelegate2.dispose);
await tester.pumpWidget(buildBoilerPlate(
Router<RouteInformation>(
backButtonDispatcher: outerDispatcher,
routerDelegate: outerDelegate2,
), ),
)); ));
expect(tester.takeException(), isNull); expect(tester.takeException(), isNull);
}); });
testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester tester) async { testWidgetsWithLeakTracking('ChildBackButtonDispatcher take priority recursively', (WidgetTester tester) async {
final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher(); final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
final BackButtonDispatcher innerDispatcher1 = ChildBackButtonDispatcher(outerDispatcher); final BackButtonDispatcher innerDispatcher1 = ChildBackButtonDispatcher(outerDispatcher);
final BackButtonDispatcher innerDispatcher2 = ChildBackButtonDispatcher(innerDispatcher1); final BackButtonDispatcher innerDispatcher2 = ChildBackButtonDispatcher(innerDispatcher1);
final BackButtonDispatcher innerDispatcher3 = ChildBackButtonDispatcher(innerDispatcher2); final BackButtonDispatcher innerDispatcher3 = ChildBackButtonDispatcher(innerDispatcher2);
late final SimpleRouterDelegate outerDelegate;
addTearDown(() => outerDelegate.dispose());
late final SimpleRouterDelegate innerDelegate1;
addTearDown(() => innerDelegate1.dispose());
late final SimpleRouterDelegate innerDelegate2;
addTearDown(() => innerDelegate2.dispose());
late final SimpleRouterDelegate innerDelegate3;
addTearDown(() => innerDelegate3.dispose());
bool isPopped = false; bool isPopped = false;
await tester.pumpWidget(buildBoilerPlate( await tester.pumpWidget(buildBoilerPlate(
Router<RouteInformation>( Router<RouteInformation>(
backButtonDispatcher: outerDispatcher, backButtonDispatcher: outerDispatcher,
routerDelegate: SimpleRouterDelegate( routerDelegate: outerDelegate = SimpleRouterDelegate(
builder: (BuildContext context, RouteInformation? information) { builder: (BuildContext context, RouteInformation? information) {
// Creates the sub-router. // Creates the sub-router.
return Router<RouteInformation>( return Router<RouteInformation>(
backButtonDispatcher: innerDispatcher1, backButtonDispatcher: innerDispatcher1,
routerDelegate: SimpleRouterDelegate( routerDelegate: innerDelegate1 = SimpleRouterDelegate(
builder: (BuildContext context, RouteInformation? innerInformation) { builder: (BuildContext context, RouteInformation? innerInformation) {
return Router<RouteInformation>( return Router<RouteInformation>(
backButtonDispatcher: innerDispatcher2, backButtonDispatcher: innerDispatcher2,
routerDelegate: SimpleRouterDelegate( routerDelegate: innerDelegate2 = SimpleRouterDelegate(
builder: (BuildContext context, RouteInformation? innerInformation) { builder: (BuildContext context, RouteInformation? innerInformation) {
return Router<RouteInformation>( return Router<RouteInformation>(
backButtonDispatcher: innerDispatcher3, backButtonDispatcher: innerDispatcher3,
routerDelegate: SimpleRouterDelegate( routerDelegate: innerDelegate3 = SimpleRouterDelegate(
onPopRoute: () { onPopRoute: () {
isPopped = true; isPopped = true;
return SynchronousFuture<bool>(true); return SynchronousFuture<bool>(true);
...@@ -508,7 +562,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -508,7 +562,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
expect(isPopped, isTrue); expect(isPopped, isTrue);
}); });
testWidgets('router does report URL change correctly', (WidgetTester tester) async { testWidgetsWithLeakTracking('router does report URL change correctly', (WidgetTester tester) async {
RouteInformation? reportedRouteInformation; RouteInformation? reportedRouteInformation;
RouteInformationReportingType? reportedType; RouteInformationReportingType? reportedType;
final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider( final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(
...@@ -520,6 +574,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -520,6 +574,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
reportedType = type; reportedType = type;
}, },
); );
addTearDown(provider.dispose);
final SimpleRouterDelegate delegate = SimpleRouterDelegate( final SimpleRouterDelegate delegate = SimpleRouterDelegate(
reportConfiguration: true, reportConfiguration: true,
builder: (BuildContext context, RouteInformation? information) { builder: (BuildContext context, RouteInformation? information) {
...@@ -532,6 +587,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -532,6 +587,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
); );
return SynchronousFuture<bool>(true); return SynchronousFuture<bool>(true);
}; };
addTearDown(delegate.dispose);
final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher(); final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
provider.value = RouteInformation( provider.value = RouteInformation(
...@@ -584,7 +640,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -584,7 +640,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
expect(reportedType, RouteInformationReportingType.none); expect(reportedType, RouteInformationReportingType.none);
}); });
testWidgets('router can be forced to recognize or ignore navigating events', (WidgetTester tester) async { testWidgetsWithLeakTracking('router can be forced to recognize or ignore navigating events', (WidgetTester tester) async {
RouteInformation? reportedRouteInformation; RouteInformation? reportedRouteInformation;
RouteInformationReportingType? reportedType; RouteInformationReportingType? reportedType;
bool isNavigating = false; bool isNavigating = false;
...@@ -598,10 +654,12 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -598,10 +654,12 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
reportedType = type; reportedType = type;
}, },
); );
addTearDown(provider.dispose);
provider.value = RouteInformation( provider.value = RouteInformation(
uri: Uri.parse('initial'), uri: Uri.parse('initial'),
); );
final SimpleRouterDelegate delegate = SimpleRouterDelegate(reportConfiguration: true); final SimpleRouterDelegate delegate = SimpleRouterDelegate(reportConfiguration: true);
addTearDown(delegate.dispose);
delegate.builder = (BuildContext context, RouteInformation? information) { delegate.builder = (BuildContext context, RouteInformation? information) {
return ElevatedButton( return ElevatedButton(
child: Text(Uri.decodeComponent(information!.uri.toString())), child: Text(Uri.decodeComponent(information!.uri.toString())),
...@@ -662,7 +720,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -662,7 +720,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
reportedRouteInformation = null; reportedRouteInformation = null;
}); });
testWidgets('router ignore navigating events updates RouteInformationProvider', (WidgetTester tester) async { testWidgetsWithLeakTracking('router ignore navigating events updates RouteInformationProvider', (WidgetTester tester) async {
RouteInformation? updatedRouteInformation; RouteInformation? updatedRouteInformation;
late RouteInformation nextRouteInformation; late RouteInformation nextRouteInformation;
RouteInformationReportingType? reportingType; RouteInformationReportingType? reportingType;
...@@ -674,10 +732,12 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -674,10 +732,12 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
reportingType = type; reportingType = type;
}, },
); );
addTearDown(provider.dispose);
provider.value = RouteInformation( provider.value = RouteInformation(
uri: Uri.parse('initial'), uri: Uri.parse('initial'),
); );
final SimpleRouterDelegate delegate = SimpleRouterDelegate(reportConfiguration: true); final SimpleRouterDelegate delegate = SimpleRouterDelegate(reportConfiguration: true);
addTearDown(delegate.dispose);
delegate.builder = (BuildContext context, RouteInformation? information) { delegate.builder = (BuildContext context, RouteInformation? information) {
return ElevatedButton( return ElevatedButton(
child: Text(Uri.decodeComponent(information!.uri.toString())), child: Text(Uri.decodeComponent(information!.uri.toString())),
...@@ -717,7 +777,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -717,7 +777,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
expect(reportingType, RouteInformationReportingType.neglect); expect(reportingType, RouteInformationReportingType.neglect);
}); });
testWidgets('state change without location changes updates RouteInformationProvider', (WidgetTester tester) async { testWidgetsWithLeakTracking('state change without location changes updates RouteInformationProvider', (WidgetTester tester) async {
RouteInformation? updatedRouteInformation; RouteInformation? updatedRouteInformation;
late RouteInformation nextRouteInformation; late RouteInformation nextRouteInformation;
RouteInformationReportingType? reportingType; RouteInformationReportingType? reportingType;
...@@ -730,11 +790,13 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -730,11 +790,13 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
reportingType = type; reportingType = type;
}, },
); );
addTearDown(provider.dispose);
provider.value = RouteInformation( provider.value = RouteInformation(
uri: Uri.parse('initial'), uri: Uri.parse('initial'),
state: 'state1', state: 'state1',
); );
final SimpleRouterDelegate delegate = SimpleRouterDelegate(reportConfiguration: true); final SimpleRouterDelegate delegate = SimpleRouterDelegate(reportConfiguration: true);
addTearDown(delegate.dispose);
delegate.builder = (BuildContext context, RouteInformation? information) { delegate.builder = (BuildContext context, RouteInformation? information) {
return ElevatedButton( return ElevatedButton(
child: Text(Uri.decodeComponent(information!.uri.toString())), child: Text(Uri.decodeComponent(information!.uri.toString())),
...@@ -770,12 +832,13 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -770,12 +832,13 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
expect(reportingType, RouteInformationReportingType.none); expect(reportingType, RouteInformationReportingType.none);
}); });
testWidgets('PlatformRouteInformationProvider works', (WidgetTester tester) async { testWidgetsWithLeakTracking('PlatformRouteInformationProvider works', (WidgetTester tester) async {
final RouteInformationProvider provider = PlatformRouteInformationProvider( final PlatformRouteInformationProvider provider = PlatformRouteInformationProvider(
initialRouteInformation: RouteInformation( initialRouteInformation: RouteInformation(
uri: Uri.parse('initial'), uri: Uri.parse('initial'),
), ),
); );
addTearDown(provider.dispose);
final SimpleRouterDelegate delegate = SimpleRouterDelegate( final SimpleRouterDelegate delegate = SimpleRouterDelegate(
builder: (BuildContext context, RouteInformation? information) { builder: (BuildContext context, RouteInformation? information) {
final List<Widget> children = <Widget>[]; final List<Widget> children = <Widget>[];
...@@ -790,6 +853,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -790,6 +853,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
); );
}, },
); );
addTearDown(delegate.dispose);
await tester.pumpWidget(MaterialApp.router( await tester.pumpWidget(MaterialApp.router(
routeInformationProvider: provider, routeInformationProvider: provider,
...@@ -821,7 +885,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -821,7 +885,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
expect(find.text('newTestRouteName'), findsOneWidget); expect(find.text('newTestRouteName'), findsOneWidget);
}); });
testWidgets('PlatformRouteInformationProvider updates route information', (WidgetTester tester) async { testWidgetsWithLeakTracking('PlatformRouteInformationProvider updates route information', (WidgetTester tester) async {
final List<MethodCall> log = <MethodCall>[]; final List<MethodCall> log = <MethodCall>[];
TestDefaultBinaryMessengerBinding TestDefaultBinaryMessengerBinding
.instance.defaultBinaryMessenger .instance.defaultBinaryMessenger
...@@ -832,11 +896,12 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -832,11 +896,12 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
return null; return null;
} }
); );
final RouteInformationProvider provider = PlatformRouteInformationProvider( final PlatformRouteInformationProvider provider = PlatformRouteInformationProvider(
initialRouteInformation: RouteInformation( initialRouteInformation: RouteInformation(
uri: Uri.parse('initial'), uri: Uri.parse('initial'),
), ),
); );
addTearDown(provider.dispose);
log.clear(); log.clear();
provider.routerReportsNewRouteInformation(RouteInformation(uri: Uri.parse('a'), state: true)); provider.routerReportsNewRouteInformation(RouteInformation(uri: Uri.parse('a'), state: true));
...@@ -868,7 +933,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -868,7 +933,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
]); ]);
}); });
testWidgets('PlatformRouteInformationProvider does not push new entry if query parameters are semantically the same', (WidgetTester tester) async { testWidgetsWithLeakTracking('PlatformRouteInformationProvider does not push new entry if query parameters are semantically the same', (WidgetTester tester) async {
final List<MethodCall> log = <MethodCall>[]; final List<MethodCall> log = <MethodCall>[];
TestDefaultBinaryMessengerBinding TestDefaultBinaryMessengerBinding
.instance.defaultBinaryMessenger .instance.defaultBinaryMessenger
...@@ -882,9 +947,10 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -882,9 +947,10 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
final RouteInformation initial = RouteInformation( final RouteInformation initial = RouteInformation(
uri: Uri.parse('initial?a=ws/abcd'), uri: Uri.parse('initial?a=ws/abcd'),
); );
final RouteInformationProvider provider = PlatformRouteInformationProvider( final PlatformRouteInformationProvider provider = PlatformRouteInformationProvider(
initialRouteInformation: initial initialRouteInformation: initial
); );
addTearDown(provider.dispose);
// Make sure engine is updated with initial route // Make sure engine is updated with initial route
provider.routerReportsNewRouteInformation(initial); provider.routerReportsNewRouteInformation(initial);
log.clear(); log.clear();
...@@ -938,19 +1004,21 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -938,19 +1004,21 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
log.clear(); log.clear();
}); });
testWidgets('RootBackButtonDispatcher works', (WidgetTester tester) async { testWidgetsWithLeakTracking('RootBackButtonDispatcher works', (WidgetTester tester) async {
final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher(); final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
final RouteInformationProvider provider = PlatformRouteInformationProvider( final PlatformRouteInformationProvider provider = PlatformRouteInformationProvider(
initialRouteInformation: RouteInformation( initialRouteInformation: RouteInformation(
uri: Uri.parse('initial'), uri: Uri.parse('initial'),
), ),
); );
addTearDown(provider.dispose);
final SimpleRouterDelegate delegate = SimpleRouterDelegate( final SimpleRouterDelegate delegate = SimpleRouterDelegate(
reportConfiguration: true, reportConfiguration: true,
builder: (BuildContext context, RouteInformation? information) { builder: (BuildContext context, RouteInformation? information) {
return Text(Uri.decodeComponent(information!.uri.toString())); return Text(Uri.decodeComponent(information!.uri.toString()));
}, },
); );
addTearDown(delegate.dispose);
delegate.onPopRoute = () { delegate.onPopRoute = () {
delegate.routeInformation = RouteInformation( delegate.routeInformation = RouteInformation(
uri: Uri.parse('popped'), uri: Uri.parse('popped'),
...@@ -973,18 +1041,14 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -973,18 +1041,14 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
expect(find.text('popped'), findsOneWidget); expect(find.text('popped'), findsOneWidget);
}); });
testWidgets('BackButtonListener takes priority over root back dispatcher', (WidgetTester tester) async { testWidgetsWithLeakTracking('BackButtonListener takes priority over root back dispatcher', (WidgetTester tester) async {
final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(); final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
addTearDown(provider.dispose);
provider.value = RouteInformation( provider.value = RouteInformation(
uri: Uri.parse('initial'), uri: Uri.parse('initial'),
); );
final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher(); final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
await tester.pumpWidget(buildBoilerPlate( final SimpleRouterDelegate delegate = SimpleRouterDelegate(
Router<RouteInformation>(
backButtonDispatcher: outerDispatcher,
routeInformationProvider: provider,
routeInformationParser: SimpleRouteInformationParser(),
routerDelegate: SimpleRouterDelegate(
builder: (BuildContext context, RouteInformation? information) { builder: (BuildContext context, RouteInformation? information) {
// Creates the sub-router. // Creates the sub-router.
return Column( return Column(
...@@ -1008,7 +1072,15 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -1008,7 +1072,15 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
); );
return SynchronousFuture<bool>(true); return SynchronousFuture<bool>(true);
}, },
), );
addTearDown(delegate.dispose);
await tester.pumpWidget(buildBoilerPlate(
Router<RouteInformation>(
backButtonDispatcher: outerDispatcher,
routeInformationProvider: provider,
routeInformationParser: SimpleRouteInformationParser(),
routerDelegate: delegate,
), ),
)); ));
expect(find.text('initial'), findsOneWidget); expect(find.text('initial'), findsOneWidget);
...@@ -1020,8 +1092,9 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -1020,8 +1092,9 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
expect(find.text('popped inner1'), findsOneWidget); expect(find.text('popped inner1'), findsOneWidget);
}); });
testWidgets('BackButtonListener updates callback if it has been changed', (WidgetTester tester) async { testWidgetsWithLeakTracking('BackButtonListener updates callback if it has been changed', (WidgetTester tester) async {
final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(); final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
addTearDown(provider.dispose);
provider.value = RouteInformation( provider.value = RouteInformation(
uri: Uri.parse('initial'), uri: Uri.parse('initial'),
); );
...@@ -1050,6 +1123,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -1050,6 +1123,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
); );
return SynchronousFuture<bool>(true); return SynchronousFuture<bool>(true);
}; };
addTearDown(routerDelegate.dispose);
await tester.pumpWidget(buildBoilerPlate( await tester.pumpWidget(buildBoilerPlate(
Router<RouteInformation>( Router<RouteInformation>(
...@@ -1099,8 +1173,9 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -1099,8 +1173,9 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
expect(find.text('second callback'), findsOneWidget); expect(find.text('second callback'), findsOneWidget);
}); });
testWidgets('BackButtonListener clears callback if it is disposed', (WidgetTester tester) async { testWidgetsWithLeakTracking('BackButtonListener clears callback if it is disposed', (WidgetTester tester) async {
final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(); final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
addTearDown(provider.dispose);
provider.value = RouteInformation( provider.value = RouteInformation(
uri: Uri.parse('initial'), uri: Uri.parse('initial'),
); );
...@@ -1129,6 +1204,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -1129,6 +1204,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
); );
return SynchronousFuture<bool>(true); return SynchronousFuture<bool>(true);
}; };
addTearDown(routerDelegate.dispose);
await tester.pumpWidget(buildBoilerPlate( await tester.pumpWidget(buildBoilerPlate(
Router<RouteInformation>( Router<RouteInformation>(
...@@ -1169,18 +1245,13 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -1169,18 +1245,13 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
expect(find.text('popped outer'), findsOneWidget); expect(find.text('popped outer'), findsOneWidget);
}); });
testWidgets('Nested backButtonListener should take priority', (WidgetTester tester) async { testWidgetsWithLeakTracking('Nested backButtonListener should take priority', (WidgetTester tester) async {
final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(); final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
addTearDown(provider.dispose);
provider.value = RouteInformation( provider.value = RouteInformation(
uri: Uri.parse('initial'), uri: Uri.parse('initial'),
); );
final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher(); final SimpleRouterDelegate delegate = SimpleRouterDelegate(
await tester.pumpWidget(buildBoilerPlate(
Router<RouteInformation>(
backButtonDispatcher: outerDispatcher,
routeInformationProvider: provider,
routeInformationParser: SimpleRouteInformationParser(),
routerDelegate: SimpleRouterDelegate(
builder: (BuildContext context, RouteInformation? information) { builder: (BuildContext context, RouteInformation? information) {
// Creates the sub-router. // Creates the sub-router.
return Column( return Column(
...@@ -1212,7 +1283,16 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -1212,7 +1283,16 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
); );
return SynchronousFuture<bool>(true); return SynchronousFuture<bool>(true);
}, },
), );
addTearDown(delegate.dispose);
final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
await tester.pumpWidget(buildBoilerPlate(
Router<RouteInformation>(
backButtonDispatcher: outerDispatcher,
routeInformationProvider: provider,
routeInformationParser: SimpleRouteInformationParser(),
routerDelegate: delegate,
), ),
)); ));
expect(find.text('initial'), findsOneWidget); expect(find.text('initial'), findsOneWidget);
...@@ -1224,18 +1304,13 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -1224,18 +1304,13 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
expect(find.text('popped inner2'), findsOneWidget); expect(find.text('popped inner2'), findsOneWidget);
}); });
testWidgets('Nested backButtonListener that returns false should call next on the line', (WidgetTester tester) async { testWidgetsWithLeakTracking('Nested backButtonListener that returns false should call next on the line', (WidgetTester tester) async {
final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(); final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
addTearDown(provider.dispose);
provider.value = RouteInformation( provider.value = RouteInformation(
uri: Uri.parse('initial'), uri: Uri.parse('initial'),
); );
final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher(); final SimpleRouterDelegate delegate = SimpleRouterDelegate(
await tester.pumpWidget(buildBoilerPlate(
Router<RouteInformation>(
backButtonDispatcher: outerDispatcher,
routeInformationProvider: provider,
routeInformationParser: SimpleRouteInformationParser(),
routerDelegate: SimpleRouterDelegate(
builder: (BuildContext context, RouteInformation? information) { builder: (BuildContext context, RouteInformation? information) {
// Creates the sub-router. // Creates the sub-router.
return Column( return Column(
...@@ -1267,7 +1342,16 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -1267,7 +1342,16 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
); );
return SynchronousFuture<bool>(true); return SynchronousFuture<bool>(true);
}, },
), );
addTearDown(delegate.dispose);
final BackButtonDispatcher outerDispatcher = RootBackButtonDispatcher();
await tester.pumpWidget(buildBoilerPlate(
Router<RouteInformation>(
backButtonDispatcher: outerDispatcher,
routeInformationProvider: provider,
routeInformationParser: SimpleRouteInformationParser(),
routerDelegate: delegate,
), ),
)); ));
expect(find.text('initial'), findsOneWidget); expect(find.text('initial'), findsOneWidget);
...@@ -1279,8 +1363,9 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -1279,8 +1363,9 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
expect(find.text('popped inner1'), findsOneWidget); expect(find.text('popped inner1'), findsOneWidget);
}); });
testWidgets('`didUpdateWidget` test', (WidgetTester tester) async { testWidgetsWithLeakTracking('`didUpdateWidget` test', (WidgetTester tester) async {
final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(); final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
addTearDown(provider.dispose);
provider.value = RouteInformation( provider.value = RouteInformation(
uri: Uri.parse('initial'), uri: Uri.parse('initial'),
); );
...@@ -1316,6 +1401,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -1316,6 +1401,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
); );
return SynchronousFuture<bool>(true); return SynchronousFuture<bool>(true);
}; };
addTearDown(routerDelegate.dispose);
await tester.pumpWidget(buildBoilerPlate( await tester.pumpWidget(buildBoilerPlate(
Router<RouteInformation>( Router<RouteInformation>(
...@@ -1337,11 +1423,17 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -1337,11 +1423,17 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
expect(find.text('second callback'), findsOneWidget); expect(find.text('second callback'), findsOneWidget);
}); });
testWidgets('Router reports location if it is different from location given by OS', (WidgetTester tester) async { testWidgetsWithLeakTracking('Router reports location if it is different from location given by OS', (WidgetTester tester) async {
final List<RouteInformation> reportedRouteInformation = <RouteInformation>[]; final List<RouteInformation> reportedRouteInformation = <RouteInformation>[];
final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider( final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(
onRouterReport: (RouteInformation info, RouteInformationReportingType type) => reportedRouteInformation.add(info), onRouterReport: (RouteInformation info, RouteInformationReportingType type) => reportedRouteInformation.add(info),
)..value = RouteInformation(uri: Uri.parse('/home')); )..value = RouteInformation(uri: Uri.parse('/home'));
addTearDown(provider.dispose);
final SimpleRouterDelegate delegate = SimpleRouterDelegate(
builder: (BuildContext _, RouteInformation? info) => Text('Current route: ${info?.uri}'),
reportConfiguration: true,
);
addTearDown(delegate.dispose);
await tester.pumpWidget(buildBoilerPlate( await tester.pumpWidget(buildBoilerPlate(
Router<RouteInformation>( Router<RouteInformation>(
...@@ -1349,10 +1441,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -1349,10 +1441,7 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
routeInformationParser: RedirectingInformationParser(<String, RouteInformation>{ routeInformationParser: RedirectingInformationParser(<String, RouteInformation>{
'/doesNotExist' : RouteInformation(uri: Uri.parse('/404')), '/doesNotExist' : RouteInformation(uri: Uri.parse('/404')),
}), }),
routerDelegate: SimpleRouterDelegate( routerDelegate: delegate,
builder: (BuildContext _, RouteInformation? info) => Text('Current route: ${info?.uri}'),
reportConfiguration: true,
),
), ),
)); ));
...@@ -1366,22 +1455,14 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -1366,22 +1455,14 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
expect(reportedRouteInformation[1].uri.toString(), '/404'); expect(reportedRouteInformation[1].uri.toString(), '/404');
}); });
testWidgets('RouterInformationParser can look up dependencies and reparse', (WidgetTester tester) async { testWidgetsWithLeakTracking('RouterInformationParser can look up dependencies and reparse', (WidgetTester tester) async {
final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(); final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
addTearDown(provider.dispose);
provider.value = RouteInformation( provider.value = RouteInformation(
uri: Uri.parse('initial'), uri: Uri.parse('initial'),
); );
final BackButtonDispatcher dispatcher = RootBackButtonDispatcher(); final BackButtonDispatcher dispatcher = RootBackButtonDispatcher();
int expectedMaxLines = 1; final SimpleRouterDelegate delegate = SimpleRouterDelegate(
bool parserCalled = false;
final Widget router = Router<RouteInformation>(
routeInformationProvider: provider,
routeInformationParser: CustomRouteInformationParser((RouteInformation information, BuildContext context) {
parserCalled = true;
final DefaultTextStyle style = DefaultTextStyle.of(context);
return RouteInformation(uri: Uri.parse('${style.maxLines}'));
}),
routerDelegate: SimpleRouterDelegate(
builder: (BuildContext context, RouteInformation? information) { builder: (BuildContext context, RouteInformation? information) {
return Text(Uri.decodeComponent(information!.uri.toString())); return Text(Uri.decodeComponent(information!.uri.toString()));
}, },
...@@ -1391,7 +1472,18 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -1391,7 +1472,18 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
); );
return SynchronousFuture<bool>(true); return SynchronousFuture<bool>(true);
}, },
), );
addTearDown(delegate.dispose);
int expectedMaxLines = 1;
bool parserCalled = false;
final Widget router = Router<RouteInformation>(
routeInformationProvider: provider,
routeInformationParser: CustomRouteInformationParser((RouteInformation information, BuildContext context) {
parserCalled = true;
final DefaultTextStyle style = DefaultTextStyle.of(context);
return RouteInformation(uri: Uri.parse('${style.maxLines}'));
}),
routerDelegate: delegate,
backButtonDispatcher: dispatcher, backButtonDispatcher: dispatcher,
); );
await tester.pumpWidget(buildBoilerPlate( await tester.pumpWidget(buildBoilerPlate(
...@@ -1419,22 +1511,14 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -1419,22 +1511,14 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
expect(parserCalled, isTrue); expect(parserCalled, isTrue);
}); });
testWidgets('RouterInformationParser can look up dependencies without reparsing', (WidgetTester tester) async { testWidgetsWithLeakTracking('RouterInformationParser can look up dependencies without reparsing', (WidgetTester tester) async {
final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(); final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
addTearDown(provider.dispose);
provider.value = RouteInformation( provider.value = RouteInformation(
uri: Uri.parse('initial'), uri: Uri.parse('initial'),
); );
final BackButtonDispatcher dispatcher = RootBackButtonDispatcher(); final BackButtonDispatcher dispatcher = RootBackButtonDispatcher();
const int expectedMaxLines = 1; final SimpleRouterDelegate delegate = SimpleRouterDelegate(
bool parserCalled = false;
final Widget router = Router<RouteInformation>(
routeInformationProvider: provider,
routeInformationParser: CustomRouteInformationParser((RouteInformation information, BuildContext context) {
parserCalled = true;
final DefaultTextStyle style = context.getInheritedWidgetOfExactType<DefaultTextStyle>()!;
return RouteInformation(uri: Uri.parse('${style.maxLines}'));
}),
routerDelegate: SimpleRouterDelegate(
builder: (BuildContext context, RouteInformation? information) { builder: (BuildContext context, RouteInformation? information) {
return Text(Uri.decodeComponent(information!.uri.toString())); return Text(Uri.decodeComponent(information!.uri.toString()));
}, },
...@@ -1444,7 +1528,18 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -1444,7 +1528,18 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
); );
return SynchronousFuture<bool>(true); return SynchronousFuture<bool>(true);
}, },
), );
addTearDown(delegate.dispose);
const int expectedMaxLines = 1;
bool parserCalled = false;
final Widget router = Router<RouteInformation>(
routeInformationProvider: provider,
routeInformationParser: CustomRouteInformationParser((RouteInformation information, BuildContext context) {
parserCalled = true;
final DefaultTextStyle style = context.getInheritedWidgetOfExactType<DefaultTextStyle>()!;
return RouteInformation(uri: Uri.parse('${style.maxLines}'));
}),
routerDelegate: delegate,
backButtonDispatcher: dispatcher, backButtonDispatcher: dispatcher,
); );
await tester.pumpWidget(buildBoilerPlate( await tester.pumpWidget(buildBoilerPlate(
...@@ -1474,21 +1569,14 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -1474,21 +1569,14 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
expect(parserCalled, isFalse); expect(parserCalled, isFalse);
}); });
testWidgets('Looks up dependencies in RouterDelegate does not trigger re-parsing', (WidgetTester tester) async { testWidgetsWithLeakTracking('Looks up dependencies in RouterDelegate does not trigger re-parsing', (WidgetTester tester) async {
final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider(); final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
addTearDown(provider.dispose);
provider.value = RouteInformation( provider.value = RouteInformation(
uri: Uri.parse('initial'), uri: Uri.parse('initial'),
); );
final BackButtonDispatcher dispatcher = RootBackButtonDispatcher(); final BackButtonDispatcher dispatcher = RootBackButtonDispatcher();
int expectedMaxLines = 1; final SimpleRouterDelegate delegate = SimpleRouterDelegate(
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) { builder: (BuildContext context, RouteInformation? information) {
final DefaultTextStyle style = DefaultTextStyle.of(context); final DefaultTextStyle style = DefaultTextStyle.of(context);
return Text('${style.maxLines}'); return Text('${style.maxLines}');
...@@ -1499,7 +1587,17 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -1499,7 +1587,17 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
); );
return SynchronousFuture<bool>(true); return SynchronousFuture<bool>(true);
}, },
), );
addTearDown(delegate.dispose);
int expectedMaxLines = 1;
bool parserCalled = false;
final Widget router = Router<RouteInformation>(
routeInformationProvider: provider,
routeInformationParser: CustomRouteInformationParser((RouteInformation information, BuildContext context) {
parserCalled = true;
return information;
}),
routerDelegate: delegate,
backButtonDispatcher: dispatcher, backButtonDispatcher: dispatcher,
); );
await tester.pumpWidget(buildBoilerPlate( await tester.pumpWidget(buildBoilerPlate(
...@@ -1528,14 +1626,19 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester ...@@ -1528,14 +1626,19 @@ testWidgets('ChildBackButtonDispatcher take priority recursively', (WidgetTester
expect(parserCalled, isFalse); expect(parserCalled, isFalse);
}); });
testWidgets('Router can initialize with RouterConfig', (WidgetTester tester) async { testWidgetsWithLeakTracking('Router can initialize with RouterConfig', (WidgetTester tester) async {
const String expected = 'text'; const String expected = 'text';
final SimpleRouteInformationProvider provider = SimpleRouteInformationProvider();
addTearDown(provider.dispose);
provider.value = RouteInformation(uri: Uri.parse('/'));
final SimpleRouterDelegate delegate = SimpleRouterDelegate(
builder: (_, __) => const Text(expected),
);
addTearDown(delegate.dispose);
final RouterConfig<RouteInformation> config = RouterConfig<RouteInformation>( final RouterConfig<RouteInformation> config = RouterConfig<RouteInformation>(
routeInformationProvider: SimpleRouteInformationProvider()..value = RouteInformation(uri: Uri.parse('/')), routeInformationProvider: provider,
routeInformationParser: SimpleRouteInformationParser(), routeInformationParser: SimpleRouteInformationParser(),
routerDelegate: SimpleRouterDelegate( routerDelegate: delegate,
builder: (_, __) => const Text(expected),
),
backButtonDispatcher: RootBackButtonDispatcher(), backButtonDispatcher: RootBackButtonDispatcher(),
); );
final Router<RouteInformation> router = Router<RouteInformation>.withConfig(config: config); final Router<RouteInformation> router = Router<RouteInformation>.withConfig(config: config);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment