Skip to content
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
3f48e22
fix: call route.didPop(result) when onExit returns true
techouse Mar 23, 2025
f8d2118
test: add tests for PopScope onPopInvokedWithResult behavior
techouse Mar 23, 2025
e001872
chore: bump version to 14.8.2-dev in pubspec.yaml
techouse Mar 23, 2025
d3dfd24
chore: update CHANGELOG for version 14.8.2-dec with PopScope fix
techouse Mar 23, 2025
88d9739
chore: fix typo in changelog
techouse Mar 23, 2025
d5cb229
Merge branch 'main' into fix/double-call-onPopInvokedWithResult
techouse Mar 24, 2025
fcd8dfc
chore: fix version number
techouse Mar 26, 2025
9ecd5eb
Merge branch 'main' into fix/double-call-onPopInvokedWithResult
techouse Mar 26, 2025
ea27f87
Merge branch 'main' into fix/double-call-onPopInvokedWithResult
techouse Mar 27, 2025
46b9738
Merge branch 'main' into fix/double-call-onPopInvokedWithResult
techouse Mar 27, 2025
ec5184f
Merge branch 'main' into fix/double-call-onPopInvokedWithResult
techouse Mar 28, 2025
8a137b9
Merge branch 'main' into fix/double-call-onPopInvokedWithResult
techouse Mar 28, 2025
7f4defc
Merge branch 'main' into fix/double-call-onPopInvokedWithResult
techouse Mar 31, 2025
d273d97
Merge branch 'main' into fix/double-call-onPopInvokedWithResult
techouse Apr 1, 2025
9e23a5c
Merge branch 'main' into fix/double-call-onPopInvokedWithResult
techouse Apr 1, 2025
ec6137e
fix: update onExit callback to handle null values and improve type sa…
techouse Apr 1, 2025
6df5625
Merge branch 'main' into fix/double-call-onPopInvokedWithResult
techouse Apr 1, 2025
469c8cf
:recycle: convert SubRoute.onExit to a getter
techouse Apr 1, 2025
b3f27f8
Merge branch 'main' into fix/double-call-onPopInvokedWithResult
techouse Apr 2, 2025
5a8a741
Merge branch 'main' into fix/double-call-onPopInvokedWithResult
techouse Apr 2, 2025
6205101
Merge branch 'main' into fix/double-call-onPopInvokedWithResult
techouse Apr 3, 2025
57989d4
Merge branch 'main' into fix/double-call-onPopInvokedWithResult
techouse Apr 6, 2025
edc3b7c
Merge branch 'main' into fix/double-call-onPopInvokedWithResult
techouse Apr 10, 2025
564dd10
Merge branch 'main' into fix/double-call-onPopInvokedWithResult
techouse Apr 15, 2025
3a856a1
Merge remote-tracking branch 'origin/main' into fix/double-call-onPop…
techouse Apr 22, 2025
573eefe
Merge remote-tracking branch 'refs/remotes/origin/main' into fix/doub…
techouse May 6, 2025
a55947f
Merge branch 'main' into fix/double-call-onPopInvokedWithResult
techouse May 7, 2025
a0c1ae1
Merge branch 'main' into fix/double-call-onPopInvokedWithResult
techouse May 8, 2025
4a83178
fix: ensure non-null onExit callback usage to prevent potential null …
techouse May 8, 2025
6b6d08d
Merge remote-tracking branch 'origin/fix/double-call-onPopInvokedWith…
techouse May 8, 2025
15c58a9
Merge branch 'main' into fix/double-call-onPopInvokedWithResult
techouse May 8, 2025
9accb64
fix: update onExit to return a FutureOr<bool> and ensure proper callb…
techouse May 8, 2025
c3e6ace
chore: revert change
techouse May 8, 2025
0b3119f
chore: add copyright notice to on_exit_on_pop_invoked_with_result_tes…
techouse May 8, 2025
c4f47b7
fix: bump version to 15.1.2
techouse May 8, 2025
2dff8e8
test: move onPopInvokedWithResult tests to on_exit_test.dart
techouse May 8, 2025
bd46023
Merge branch 'main' into fix/double-call-onPopInvokedWithResult
techouse May 8, 2025
a1228df
test: simplify parameters in onPopInvokedWithResult and buildPage met…
techouse May 8, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/go_router/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 14.8.2-dev

- Fixes `PopScope.onPopInvokedWithResult` getting called twice when popping a route when `GoRouteData.onExit` is not null

## 14.8.1

- Secured canPop method for the lack of matches in routerDelegate's configuration.
Expand Down
1 change: 1 addition & 0 deletions packages/go_router/lib/src/delegate.dart
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ class GoRouterDelegate extends RouterDelegate<RouteMatchList>
match.buildState(_configuration, currentConfiguration),
);
if (onExitResult) {
route.didPop(result);
_completeRouteMatch(result, match);
}
});
Expand Down
2 changes: 1 addition & 1 deletion packages/go_router/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -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.8.1
version: 14.8.2-dev
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

Expand Down
138 changes: 138 additions & 0 deletions packages/go_router/test/on_exit_on_pop_invoked_with_result_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:go_router/go_router.dart';

void main() {
testWidgets(
'PopScope onPopInvokedWithResult should be called only once',
(WidgetTester tester) async {
int counter = 0;

final GoRouter goRouter = GoRouter(
initialLocation: '/',
routes: <GoRoute>[
GoRoute(path: '/', builder: (_, __) => const DummyStatefulWidget()),
GoRoute(
path: '/page-1',
onExit: (_, __) => true,
builder: (_, __) => PopScope(
onPopInvokedWithResult: (bool didPop, __) {
if (didPop) {
counter++;
return;
}
},
child: const Text('Page 1'),
),
),
],
);

addTearDown(goRouter.dispose);

await tester.pumpWidget(MaterialApp.router(
routeInformationProvider: goRouter.routeInformationProvider,
routeInformationParser: goRouter.routeInformationParser,
routerDelegate: goRouter.routerDelegate,
));

goRouter.push('/page-1');

await tester.pumpAndSettle();

expect(find.text('Page 1'), findsOneWidget);
expect(
goRouter.routerDelegate.currentConfiguration.matches.length,
equals(2),
);
expect(goRouter.routerDelegate.canPop(), true);

goRouter.routerDelegate.pop();

await tester.pumpAndSettle();

expect(counter, equals(1));
},
);

testWidgets(
r'PopScope onPopInvokedWithResult should be called only once with GoRouteData.$route',
(WidgetTester tester) async {
int counter = 0;

final GoRouter goRouter = GoRouter(
initialLocation: '/',
routes: <GoRoute>[
GoRoute(path: '/', builder: (_, __) => const DummyStatefulWidget()),
GoRouteData.$route(
path: '/page-1',
factory: (GoRouterState state) => _Page1(
onPop: () {
counter++;
},
),
),
],
);

addTearDown(goRouter.dispose);

await tester.pumpWidget(MaterialApp.router(
routeInformationProvider: goRouter.routeInformationProvider,
routeInformationParser: goRouter.routeInformationParser,
routerDelegate: goRouter.routerDelegate,
));

goRouter.push('/page-1');

await tester.pumpAndSettle();

expect(find.text('Page 1'), findsOneWidget);
expect(
goRouter.routerDelegate.currentConfiguration.matches.length,
equals(2),
);
expect(goRouter.routerDelegate.canPop(), true);

goRouter.routerDelegate.pop();

await tester.pumpAndSettle();

expect(counter, equals(1));
},
);
}

class _Page1 extends GoRouteData {
const _Page1({
required this.onPop,
});

final VoidCallback onPop;

@override
Page<void> buildPage(BuildContext context, GoRouterState state) =>
MaterialPage<void>(
child: PopScope(
onPopInvokedWithResult: (bool didPop, __) {
if (didPop) {
onPop();
return;
}
},
child: const Text('Page 1'),
),
);
}

class DummyStatefulWidget extends StatefulWidget {
const DummyStatefulWidget({super.key});

@override
State<DummyStatefulWidget> createState() => _DummyStatefulWidgetState();
}

class _DummyStatefulWidgetState extends State<DummyStatefulWidget> {
@override
Widget build(BuildContext context) => Container();
}