[go_router] Fixes RouteInformationParser that does not restore full RouteMatchList if the optionURLReflectsImperativeAPIs is set (#4713)
fixes https://github.com/flutter/flutter/issues/131457
diff --git a/packages/go_router/CHANGELOG.md b/packages/go_router/CHANGELOG.md
index 0380e7b..31a7b52 100644
--- a/packages/go_router/CHANGELOG.md
+++ b/packages/go_router/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 10.1.4
+
+- Fixes RouteInformationParser that does not restore full RouteMatchList if
+ the optionURLReflectsImperativeAPIs is set.
+
## 10.1.3
- Fixes an issue in the documentation that was using `state.queryParameters` instead of `state.uri.queryParameters`.
diff --git a/packages/go_router/lib/src/parser.dart b/packages/go_router/lib/src/parser.dart
index df4d551..cc5ca70 100644
--- a/packages/go_router/lib/src/parser.dart
+++ b/packages/go_router/lib/src/parser.dart
@@ -129,16 +129,21 @@
if (configuration.isEmpty) {
return null;
}
+ final String location;
if (GoRouter.optionURLReflectsImperativeAPIs &&
configuration.matches.last is ImperativeRouteMatch) {
- configuration =
- (configuration.matches.last as ImperativeRouteMatch).matches;
+ location = (configuration.matches.last as ImperativeRouteMatch)
+ .matches
+ .uri
+ .toString();
+ } else {
+ location = configuration.uri.toString();
}
return RouteInformation(
// TODO(chunhtai): remove this ignore and migrate the code
// https://github.com/flutter/flutter/issues/124045.
// ignore: deprecated_member_use
- location: configuration.uri.toString(),
+ location: location,
state: _routeMatchListCodec.encode(configuration),
);
}
diff --git a/packages/go_router/pubspec.yaml b/packages/go_router/pubspec.yaml
index 0e4bb0f..83bf119 100644
--- a/packages/go_router/pubspec.yaml
+++ b/packages/go_router/pubspec.yaml
@@ -1,7 +1,7 @@
name: go_router
description: A declarative router for Flutter based on Navigation 2 supporting
deep linking, data-driven routes and more
-version: 10.1.3
+version: 10.1.4
repository: https://github.com/flutter/packages/tree/main/packages/go_router
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+go_router%22
diff --git a/packages/go_router/test/go_router_test.dart b/packages/go_router/test/go_router_test.dart
index 755b3e3..2d67029 100644
--- a/packages/go_router/test/go_router_test.dart
+++ b/packages/go_router/test/go_router_test.dart
@@ -1046,11 +1046,10 @@
final RouteMatchListCodec codec =
RouteMatchListCodec(router.configuration);
await tester.pumpAndSettle();
- final ImperativeRouteMatch match = router
- .routerDelegate.currentConfiguration.last as ImperativeRouteMatch;
expect(log, <Object>[
isMethodCall('selectMultiEntryHistory', arguments: null),
- IsRouteUpdateCall('/settings', false, codec.encode(match.matches)),
+ IsRouteUpdateCall('/settings', false,
+ codec.encode(router.routerDelegate.currentConfiguration)),
]);
GoRouter.optionURLReflectsImperativeAPIs = false;
});
diff --git a/packages/go_router/test/parser_test.dart b/packages/go_router/test/parser_test.dart
index 67d17c2..8e5463b 100644
--- a/packages/go_router/test/parser_test.dart
+++ b/packages/go_router/test/parser_test.dart
@@ -6,6 +6,8 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:go_router/go_router.dart';
+import 'test_helpers.dart';
+
RouteInformation createRouteInformation(String location, [Object? extra]) {
return RouteInformation(
// TODO(chunhtai): remove this ignore and migrate the code
@@ -81,6 +83,53 @@
expect(matches[1].route, routes[0].routes[0]);
});
+ testWidgets(
+ 'GoRouteInformationParser can restore full route matches if optionURLReflectsImperativeAPIs is true',
+ (WidgetTester tester) async {
+ final GlobalKey<NavigatorState> navKey = GlobalKey<NavigatorState>();
+ final List<GoRoute> routes = <GoRoute>[
+ GoRoute(
+ path: '/',
+ builder: (_, __) => const Placeholder(),
+ routes: <GoRoute>[
+ GoRoute(
+ path: 'abc',
+ builder: (_, __) => const Placeholder(),
+ ),
+ ],
+ ),
+ ];
+ GoRouter.optionURLReflectsImperativeAPIs = true;
+ final GoRouter router =
+ await createRouter(routes, tester, navigatorKey: navKey);
+
+ // Generate RouteMatchList with imperative route match
+ router.go('/abc');
+ await tester.pumpAndSettle();
+ router.push('/');
+ await tester.pumpAndSettle();
+ final RouteMatchList matchList = router.routerDelegate.currentConfiguration;
+ expect(matchList.uri.toString(), '/abc');
+ expect(matchList.matches.length, 3);
+
+ final RouteInformation restoredRouteInformation =
+ router.routeInformationParser.restoreRouteInformation(matchList)!;
+ // URL reflects the latest push.
+ // TODO(chunhtai): remove this ignore and migrate the code
+ // https://github.com/flutter/flutter/issues/124045.
+ // ignore: deprecated_member_use
+ expect(restoredRouteInformation.location, '/');
+
+ // Can restore back to original RouteMatchList.
+ final RouteMatchList parsedRouteMatch = await router.routeInformationParser
+ .parseRouteInformationWithDependencies(
+ restoredRouteInformation, navKey.currentContext!);
+ expect(parsedRouteMatch.uri.toString(), '/abc');
+ expect(parsedRouteMatch.matches.length, 3);
+
+ GoRouter.optionURLReflectsImperativeAPIs = false;
+ });
+
test('GoRouteInformationParser can retrieve route by name', () async {
final List<GoRoute> routes = <GoRoute>[
GoRoute(