@@ -76,6 +76,57 @@ Future<GoRouter> createGoRouterWithStatefulShellRoute(
7676 return router;
7777}
7878
79+ Future <GoRouter > createGoRouterWithStatefulShellRouteAndPopScopes (
80+ WidgetTester tester, {
81+ bool canPopShellRouteBuilder = true ,
82+ bool canPopBranch = true ,
83+ bool canPopBranchSubRoute = true ,
84+ PopInvokedWithResultCallback <bool >? onPopShellRouteBuilder,
85+ PopInvokedWithResultCallback <bool >? onPopBranch,
86+ PopInvokedWithResultCallback <bool >? onPopBranchSubRoute,
87+ }) async {
88+ final GoRouter router = GoRouter (
89+ initialLocation: '/c' ,
90+ routes: < RouteBase > [
91+ StatefulShellRoute .indexedStack (
92+ branches: < StatefulShellBranch > [
93+ StatefulShellBranch (routes: < RouteBase > [
94+ GoRoute (
95+ path: '/c' ,
96+ builder: (_, __) => PopScope (
97+ onPopInvokedWithResult: onPopBranch,
98+ canPop: canPopBranch,
99+ child: const Text ('Home' )),
100+ routes: < RouteBase > [
101+ GoRoute (
102+ path: 'c1' ,
103+ builder: (_, __) => PopScope (
104+ onPopInvokedWithResult: onPopBranchSubRoute,
105+ canPop: canPopBranchSubRoute,
106+ child: const Text ('SubRoute' ),
107+ ),
108+ ),
109+ ]),
110+ ]),
111+ ],
112+ builder: (BuildContext context, GoRouterState state,
113+ StatefulNavigationShell navigationShell) =>
114+ PopScope (
115+ onPopInvokedWithResult: onPopShellRouteBuilder,
116+ canPop: canPopShellRouteBuilder,
117+ child: navigationShell,
118+ ),
119+ ),
120+ ],
121+ );
122+
123+ addTearDown (router.dispose);
124+ await tester.pumpWidget (MaterialApp .router (
125+ routerConfig: router,
126+ ));
127+ return router;
128+ }
129+
79130void main () {
80131 group ('pop' , () {
81132 testWidgets ('restore() update currentConfiguration in pop()' ,
@@ -152,6 +203,91 @@ void main() {
152203 expect (find.text ('Home' ), findsOneWidget);
153204 });
154205
206+ testWidgets (
207+ 'PopScope intercepts back button on StatefulShellRoute builder route' ,
208+ (WidgetTester tester) async {
209+ bool didPopShellRouteBuilder = false ;
210+ bool didPopBranch = false ;
211+ bool didPopBranchSubRoute = false ;
212+
213+ await createGoRouterWithStatefulShellRouteAndPopScopes (
214+ tester,
215+ canPopShellRouteBuilder: false ,
216+ onPopShellRouteBuilder: (_, __) => didPopShellRouteBuilder = true ,
217+ onPopBranch: (_, __) => didPopBranch = true ,
218+ onPopBranchSubRoute: (_, __) => didPopBranchSubRoute = true ,
219+ );
220+
221+ expect (find.text ('Home' ), findsOneWidget);
222+ await tester.binding.handlePopRoute ();
223+ await tester.pumpAndSettle ();
224+
225+ // Verify that PopScope intercepted the back button
226+ expect (didPopShellRouteBuilder, isTrue);
227+ expect (didPopBranch, isFalse);
228+ expect (didPopBranchSubRoute, isFalse);
229+
230+ expect (find.text ('Home' ), findsOneWidget);
231+ });
232+
233+ testWidgets (
234+ 'PopScope intercepts back button on StatefulShellRoute branch route' ,
235+ (WidgetTester tester) async {
236+ bool didPopShellRouteBuilder = false ;
237+ bool didPopBranch = false ;
238+ bool didPopBranchSubRoute = false ;
239+
240+ await createGoRouterWithStatefulShellRouteAndPopScopes (
241+ tester,
242+ canPopBranch: false ,
243+ onPopShellRouteBuilder: (_, __) => didPopShellRouteBuilder = true ,
244+ onPopBranch: (_, __) => didPopBranch = true ,
245+ onPopBranchSubRoute: (_, __) => didPopBranchSubRoute = true ,
246+ );
247+
248+ expect (find.text ('Home' ), findsOneWidget);
249+ await tester.binding.handlePopRoute ();
250+ await tester.pumpAndSettle ();
251+
252+ // Verify that PopScope intercepted the back button
253+ expect (didPopShellRouteBuilder, isFalse);
254+ expect (didPopBranch, isTrue);
255+ expect (didPopBranchSubRoute, isFalse);
256+
257+ expect (find.text ('Home' ), findsOneWidget);
258+ });
259+
260+ testWidgets (
261+ 'PopScope intercepts back button on StatefulShellRoute branch sub route' ,
262+ (WidgetTester tester) async {
263+ bool didPopShellRouteBuilder = false ;
264+ bool didPopBranch = false ;
265+ bool didPopBranchSubRoute = false ;
266+
267+ final GoRouter goRouter =
268+ await createGoRouterWithStatefulShellRouteAndPopScopes (
269+ tester,
270+ canPopBranchSubRoute: false ,
271+ onPopShellRouteBuilder: (_, __) => didPopShellRouteBuilder = true ,
272+ onPopBranch: (_, __) => didPopBranch = true ,
273+ onPopBranchSubRoute: (_, __) => didPopBranchSubRoute = true ,
274+ );
275+
276+ goRouter.push ('/c/c1' );
277+ await tester.pumpAndSettle ();
278+
279+ expect (find.text ('SubRoute' ), findsOneWidget);
280+ await tester.binding.handlePopRoute ();
281+ await tester.pumpAndSettle ();
282+
283+ // Verify that PopScope intercepted the back button
284+ expect (didPopShellRouteBuilder, isFalse);
285+ expect (didPopBranch, isFalse);
286+ expect (didPopBranchSubRoute, isTrue);
287+
288+ expect (find.text ('SubRoute' ), findsOneWidget);
289+ });
290+
155291 testWidgets ('pops more than matches count should return false' ,
156292 (WidgetTester tester) async {
157293 final GoRouter goRouter = await createGoRouter (tester)
0 commit comments