[go_router] Fix parentNavigatorKey not working with multiple nested Routes in ShellRoute (#2784)

* [go_router] Fix parentNavigatorKey with multiple nested Routes in ShellRoute (#111961)

* Update packages/go_router/CHANGELOG.md

Co-authored-by: chunhtai <47866232+chunhtai@users.noreply.github.com>

Co-authored-by: chunhtai <47866232+chunhtai@users.noreply.github.com>
This commit is contained in:
David Miguel Lozano
2022-11-14 18:55:56 +01:00
committed by GitHub
parent 1973a509a3
commit 6a03dd47ec
4 changed files with 121 additions and 68 deletions

View File

@ -1,3 +1,7 @@
## 5.1.6
- Fixes crashes when multiple `GoRoute`s use the same `parentNavigatorKey` in a route subtree.
## 5.1.5
- Adds migration guide for 5.1.2 to readme.

View File

@ -60,9 +60,9 @@ class RouteConfiguration {
checkParentNavigatorKeys(
route.routes,
<GlobalKey<NavigatorState>>[
// Once a parentNavigatorKey is used, only the navigator keys
// above it can be used.
...allowedKeys.sublist(0, allowedKeys.indexOf(parentKey)),
// Once a parentNavigatorKey is used, only that navigator key
// or keys above it can be used.
...allowedKeys.sublist(0, allowedKeys.indexOf(parentKey) + 1),
],
);
} else {

View File

@ -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: 5.1.5
version: 5.1.6
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

View File

@ -175,6 +175,55 @@ void main() {
},
);
test(
'Does not throw with multiple nested GoRoutes using parentNavigatorKey in ShellRoute',
() {
final GlobalKey<NavigatorState> root =
GlobalKey<NavigatorState>(debugLabel: 'root');
final GlobalKey<NavigatorState> shell =
GlobalKey<NavigatorState>(debugLabel: 'shell');
RouteConfiguration(
navigatorKey: root,
routes: <RouteBase>[
ShellRoute(
navigatorKey: shell,
routes: <RouteBase>[
GoRoute(
path: '/',
builder: _mockScreenBuilder,
routes: <RouteBase>[
GoRoute(
path: 'a',
builder: _mockScreenBuilder,
parentNavigatorKey: root,
routes: <RouteBase>[
GoRoute(
path: 'b',
builder: _mockScreenBuilder,
parentNavigatorKey: root,
routes: <RouteBase>[
GoRoute(
path: 'c',
builder: _mockScreenBuilder,
parentNavigatorKey: root,
),
],
),
],
),
],
),
],
),
],
redirectLimit: 10,
topRedirect: (BuildContext context, GoRouterState state) {
return null;
},
);
},
);
test(
'Throws when parentNavigatorKeys are overlapping',
() {
@ -369,78 +418,50 @@ void main() {
navigatorKey: root,
);
});
});
test(
'Does not throw with valid parentNavigatorKey configuration',
() {
final GlobalKey<NavigatorState> root =
GlobalKey<NavigatorState>(debugLabel: 'root');
final GlobalKey<NavigatorState> shell =
GlobalKey<NavigatorState>(debugLabel: 'shell');
final GlobalKey<NavigatorState> shell2 =
GlobalKey<NavigatorState>(debugLabel: 'shell2');
RouteConfiguration(
navigatorKey: root,
routes: <RouteBase>[
ShellRoute(
navigatorKey: shell,
routes: <RouteBase>[
GoRoute(
path: '/',
builder: _mockScreenBuilder,
routes: <RouteBase>[
GoRoute(
path: 'a',
builder: _mockScreenBuilder,
parentNavigatorKey: root,
routes: <RouteBase>[
ShellRoute(
navigatorKey: shell2,
routes: <RouteBase>[
GoRoute(
path: 'b',
builder: _mockScreenBuilder,
routes: <RouteBase>[
GoRoute(
path: 'b',
builder: _mockScreenBuilder,
parentNavigatorKey: shell2,
),
],
),
],
),
],
),
],
),
],
),
],
redirectLimit: 10,
topRedirect: (BuildContext context, GoRouterState state) {
return null;
},
);
},
);
test('throws when ShellRoute contains a GoRoute with a parentNavigatorKey',
() {
final GlobalKey<NavigatorState> root =
GlobalKey<NavigatorState>(debugLabel: 'root');
expect(
test(
'Does not throw with valid parentNavigatorKey configuration',
() {
final GlobalKey<NavigatorState> root =
GlobalKey<NavigatorState>(debugLabel: 'root');
final GlobalKey<NavigatorState> shell =
GlobalKey<NavigatorState>(debugLabel: 'shell');
final GlobalKey<NavigatorState> shell2 =
GlobalKey<NavigatorState>(debugLabel: 'shell2');
RouteConfiguration(
navigatorKey: root,
routes: <RouteBase>[
ShellRoute(
navigatorKey: shell,
routes: <RouteBase>[
GoRoute(
path: '/a',
path: '/',
builder: _mockScreenBuilder,
parentNavigatorKey: root,
routes: <RouteBase>[
GoRoute(
path: 'a',
builder: _mockScreenBuilder,
parentNavigatorKey: root,
routes: <RouteBase>[
ShellRoute(
navigatorKey: shell2,
routes: <RouteBase>[
GoRoute(
path: 'b',
builder: _mockScreenBuilder,
routes: <RouteBase>[
GoRoute(
path: 'b',
builder: _mockScreenBuilder,
parentNavigatorKey: shell2,
),
],
),
],
),
],
),
],
),
],
),
@ -451,8 +472,36 @@ void main() {
},
);
},
throwsAssertionError,
);
test('throws when ShellRoute contains a GoRoute with a parentNavigatorKey',
() {
final GlobalKey<NavigatorState> root =
GlobalKey<NavigatorState>(debugLabel: 'root');
expect(
() {
RouteConfiguration(
navigatorKey: root,
routes: <RouteBase>[
ShellRoute(
routes: <RouteBase>[
GoRoute(
path: '/a',
builder: _mockScreenBuilder,
parentNavigatorKey: root,
),
],
),
],
redirectLimit: 10,
topRedirect: (BuildContext context, GoRouterState state) {
return null;
},
);
},
throwsAssertionError,
);
});
});
}