Skip to content

[go_router] Add regression test for synchronous onEnter Block.then(router.go) (flutter#179370)#11725

Draft
NadeemIqbal wants to merge 2 commits into
flutter:mainfrom
NadeemIqbal:nadeem/179370-go-router-sync-on-enter
Draft

[go_router] Add regression test for synchronous onEnter Block.then(router.go) (flutter#179370)#11725
NadeemIqbal wants to merge 2 commits into
flutter:mainfrom
NadeemIqbal:nadeem/179370-go-router-sync-on-enter

Conversation

@NadeemIqbal
Copy link
Copy Markdown

@NadeemIqbal NadeemIqbal commented May 17, 2026

Adds a regression test for flutter/flutter#179370. The user-visible symptom — a synchronous `onEnter` returning `Block.then(() => router.go(...))` failing to redirect on the initial route — was fixed in go_router 17.2.0 by #11136 (which replaced `await Future.sync(callback)` with `scheduleMicrotask(() async { await callback(); })` in `_OnEnterHandler.handleTopOnEnter` to break the re-entrant parse cycle), but the linked issue is still open and there is no test that fails when that change is reverted.

The new test in `packages/go_router/test/on_enter_test.dart` mirrors the exact predicate the reporter used (`current.uri.path == '/dashboard'` on the initial parse, where `currentState` equals `nextState` because the router has no committed configuration yet) and asserts that the sync `Block.then(router.go('/login'))` redirect resolves to `/login`.

I verified the test is a real regression test by temporarily reverting parser.dart to the pre-#11136 implementation (`await Future.sync(callback)`) and confirming this test fails with that change in place; with the current implementation it passes alongside the rest of `on_enter_test.dart` (32/32, all locally with stable Flutter SDK 3.41.7).

Fixes flutter/flutter#179370.

Pre-Review Checklist

Test-only change, so no version bump / CHANGELOG entry per the published-package exemption. Happy to bump if the reviewer prefers.

…uter.go)

A synchronous onEnter callback that returns `Block.then(() => router.go(...))`
on the initial route must still run the `then` redirect. This was the
user-visible symptom in flutter/flutter#179370: replacing `async` with a
synchronous callback caused the initial redirect to be silently lost, which
the reporter worked around by re-adding `async`.

The underlying re-entrancy bug was fixed by flutter#11136 (replacing
`await Future<void>.sync(callback)` with `scheduleMicrotask(() async { await
callback(); })`). Lock in that behavior with a regression test mirroring the
exact predicate from the report (`current.uri.path == '/dashboard'`), which
on the initial parse matches because the router has no committed
configuration yet.

Verified that reverting `parser.dart` to the pre-flutter#11136 implementation makes
this test fail; with the current implementation it passes alongside the rest
of `on_enter_test.dart` (32/32).

Fixes flutter/flutter#179370.
@github-actions github-actions Bot added p: go_router triage-framework Should be looked at in framework triage labels May 17, 2026
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds a regression test for issue #179370 in packages/go_router/test/on_enter_test.dart to verify that synchronous onEnter redirects on the initial route function correctly. The reviewer suggested removing the redundant localRouter variable and using the group-level router variable directly to maintain consistency with the existing test suite.

Comment on lines +911 to +912
late GoRouter localRouter;
localRouter = GoRouter(
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The localRouter variable is redundant. You can assign the GoRouter instance directly to the group-level router variable, which is consistent with the implementation pattern used in other tests within this file.

Suggested change
late GoRouter localRouter;
localRouter = GoRouter(
router = GoRouter(

Comment on lines +944 to +949
router = localRouter;

await tester.pumpWidget(MaterialApp.router(routerConfig: localRouter));
await tester.pumpAndSettle();

expect(localRouter.state.uri.path, equals('/login'));
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Update these lines to use the group-level router variable directly and remove the redundant localRouter assignment to maintain consistency with the rest of the test suite.

Suggested change
router = localRouter;
await tester.pumpWidget(MaterialApp.router(routerConfig: localRouter));
await tester.pumpAndSettle();
expect(localRouter.state.uri.path, equals('/login'));
await tester.pumpWidget(MaterialApp.router(routerConfig: router));
await tester.pumpAndSettle();
expect(router.state.uri.path, equals('/login'));

…uter

Address gemini-code-assist feedback on flutter#11725: remove the redundant
`localRouter` variable and use the existing group-level `router` directly,
matching the pattern used in every other test in this file.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

p: go_router triage-framework Should be looked at in framework triage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[go_router] Top-level onEnter callback event loop problem

1 participant