diff --git a/packages/go_router/CHANGELOG.md b/packages/go_router/CHANGELOG.md index b1154beb7ed..82df3001eeb 100644 --- a/packages/go_router/CHANGELOG.md +++ b/packages/go_router/CHANGELOG.md @@ -1,3 +1,7 @@ +## 14.1.1 + +- Fixes correctness of the state provided in the `onExit`. + ## 14.1.0 - Adds route redirect to ShellRoutes diff --git a/packages/go_router/lib/src/delegate.dart b/packages/go_router/lib/src/delegate.dart index f0185893bb3..eba3ef0c801 100644 --- a/packages/go_router/lib/src/delegate.dart +++ b/packages/go_router/lib/src/delegate.dart @@ -233,7 +233,6 @@ class GoRouterDelegate extends RouterDelegate exitingMatches.length - 1, context: navigatorContext, matches: exitingMatches, - configuration: configuration, ).then((bool exit) { if (!exit) { return SynchronousFuture(null); @@ -254,7 +253,6 @@ class GoRouterDelegate extends RouterDelegate int index, { required BuildContext context, required List matches, - required RouteMatchList configuration, }) { if (index < 0) { return SynchronousFuture(true); @@ -266,7 +264,6 @@ class GoRouterDelegate extends RouterDelegate index - 1, context: context, matches: matches, - configuration: configuration, ); } @@ -276,7 +273,6 @@ class GoRouterDelegate extends RouterDelegate index - 1, context: context, matches: matches, - configuration: configuration, ); } return SynchronousFuture(false); @@ -284,7 +280,7 @@ class GoRouterDelegate extends RouterDelegate final FutureOr exitFuture = goRoute.onExit!( context, - match.buildState(_configuration, configuration), + match.buildState(_configuration, currentConfiguration), ); if (exitFuture is bool) { return handleOnExitResult(exitFuture); diff --git a/packages/go_router/pubspec.yaml b/packages/go_router/pubspec.yaml index f04e5433ae3..5aac8fbec38 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: 14.1.0 +version: 14.1.1 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/on_exit_test.dart b/packages/go_router/test/on_exit_test.dart index ceeb6806d15..8a7bd83ab64 100644 --- a/packages/go_router/test/on_exit_test.dart +++ b/packages/go_router/test/on_exit_test.dart @@ -244,7 +244,7 @@ void main() { expect(await router.routerDelegate.popRoute(), false); }); - testWidgets('It should provide the correct state to the onExit callback', + testWidgets('It should provide the correct uri to the onExit callback', (WidgetTester tester) async { final UniqueKey home = UniqueKey(); final UniqueKey page1 = UniqueKey(); @@ -314,4 +314,161 @@ void main() { expect(find.byKey(home), findsOneWidget); expect(onExitState1.uri.toString(), '/1'); }); + + testWidgets( + 'It should provide the correct path parameters to the onExit callback', + (WidgetTester tester) async { + final UniqueKey page0 = UniqueKey(); + final UniqueKey page1 = UniqueKey(); + final UniqueKey page2 = UniqueKey(); + final UniqueKey page3 = UniqueKey(); + late final GoRouterState onExitState1; + late final GoRouterState onExitState2; + late final GoRouterState onExitState3; + final List routes = [ + GoRoute( + path: '/route-0/:id0', + builder: (BuildContext context, GoRouterState state) => + DummyScreen(key: page0), + ), + GoRoute( + path: '/route-1/:id1', + builder: (BuildContext context, GoRouterState state) => + DummyScreen(key: page1), + onExit: (BuildContext context, GoRouterState state) { + onExitState1 = state; + return true; + }, + ), + GoRoute( + path: '/route-2/:id2', + builder: (BuildContext context, GoRouterState state) => + DummyScreen(key: page2), + onExit: (BuildContext context, GoRouterState state) { + onExitState2 = state; + return true; + }, + ), + GoRoute( + path: '/route-3/:id3', + builder: (BuildContext context, GoRouterState state) { + return DummyScreen(key: page3); + }, + onExit: (BuildContext context, GoRouterState state) { + onExitState3 = state; + return true; + }, + ), + ]; + + final GoRouter router = await createRouter( + routes, + tester, + initialLocation: '/route-0/0?param0=0', + ); + unawaited(router.push('/route-1/1?param1=1')); + unawaited(router.push('/route-2/2?param2=2')); + unawaited(router.push('/route-3/3?param3=3')); + + await tester.pumpAndSettle(); + expect(find.byKey(page3), findsOne); + + router.pop(); + await tester.pumpAndSettle(); + expect(find.byKey(page2), findsOne); + expect(onExitState3.uri.toString(), '/route-3/3?param3=3'); + expect(onExitState3.pathParameters, const {'id3': '3'}); + expect(onExitState3.fullPath, '/route-3/:id3'); + + router.pop(); + await tester.pumpAndSettle(); + expect(find.byKey(page1), findsOne); + expect(onExitState2.uri.toString(), '/route-2/2?param2=2'); + expect(onExitState2.pathParameters, const {'id2': '2'}); + expect(onExitState2.fullPath, '/route-2/:id2'); + + router.pop(); + await tester.pumpAndSettle(); + expect(find.byKey(page0), findsOne); + expect(onExitState1.uri.toString(), '/route-1/1?param1=1'); + expect(onExitState1.pathParameters, const {'id1': '1'}); + expect(onExitState1.fullPath, '/route-1/:id1'); + }, + ); + + testWidgets( + 'It should provide the correct path parameters to the onExit callback during a go', + (WidgetTester tester) async { + final UniqueKey page0 = UniqueKey(); + final UniqueKey page1 = UniqueKey(); + final UniqueKey page2 = UniqueKey(); + final UniqueKey page3 = UniqueKey(); + late final GoRouterState onExitState0; + late final GoRouterState onExitState1; + late final GoRouterState onExitState2; + final List routes = [ + GoRoute( + path: '/route-0/:id0', + builder: (BuildContext context, GoRouterState state) => + DummyScreen(key: page0), + onExit: (BuildContext context, GoRouterState state) { + onExitState0 = state; + return true; + }, + ), + GoRoute( + path: '/route-1/:id1', + builder: (BuildContext context, GoRouterState state) => + DummyScreen(key: page1), + onExit: (BuildContext context, GoRouterState state) { + onExitState1 = state; + return true; + }, + ), + GoRoute( + path: '/route-2/:id2', + builder: (BuildContext context, GoRouterState state) => + DummyScreen(key: page2), + onExit: (BuildContext context, GoRouterState state) { + onExitState2 = state; + return true; + }, + ), + GoRoute( + path: '/route-3/:id3', + builder: (BuildContext context, GoRouterState state) { + return DummyScreen(key: page3); + }, + ), + ]; + + final GoRouter router = await createRouter( + routes, + tester, + initialLocation: '/route-0/0?param0=0', + ); + expect(find.byKey(page0), findsOne); + + router.go('/route-1/1?param1=1'); + await tester.pumpAndSettle(); + expect(find.byKey(page1), findsOne); + expect(onExitState0.uri.toString(), '/route-0/0?param0=0'); + expect(onExitState0.pathParameters, const {'id0': '0'}); + expect(onExitState0.fullPath, '/route-0/:id0'); + + router.go('/route-2/2?param2=2'); + await tester.pumpAndSettle(); + expect(find.byKey(page2), findsOne); + expect(onExitState1.uri.toString(), '/route-1/1?param1=1'); + expect(onExitState1.pathParameters, const {'id1': '1'}); + expect(onExitState1.fullPath, '/route-1/:id1'); + + router.go('/route-3/3?param3=3'); + await tester.pumpAndSettle(); + expect(find.byKey(page3), findsOne); + expect(onExitState2.uri.toString(), '/route-2/2?param2=2'); + expect(onExitState2.pathParameters, const {'id2': '2'}); + expect(onExitState2.fullPath, '/route-2/:id2'); + }, + ); }