improve error message for navigator page api (#73153)
diff --git a/packages/flutter/lib/src/widgets/navigator.dart b/packages/flutter/lib/src/widgets/navigator.dart
index 4beefed..88bae80 100644
--- a/packages/flutter/lib/src/widgets/navigator.dart
+++ b/packages/flutter/lib/src/widgets/navigator.dart
@@ -3310,10 +3310,35 @@
@override
void initState() {
super.initState();
- assert(
- widget.pages.isEmpty || widget.onPopPage != null,
- 'The Navigator.onPopPage must be provided to use the Navigator.pages API',
- );
+ assert((){
+ if (widget.pages != const <Page<dynamic>>[]) {
+ // This navigator uses page API.
+ if (widget.pages.isEmpty) {
+ FlutterError.reportError(
+ FlutterErrorDetails(
+ exception: FlutterError(
+ 'The Navigator.pages must not be empty to use the '
+ 'Navigator.pages API'
+ ),
+ library: 'widget library',
+ stack: StackTrace.current,
+ ),
+ );
+ } else if (widget.onPopPage == null) {
+ FlutterError.reportError(
+ FlutterErrorDetails(
+ exception: FlutterError(
+ 'The Navigator.onPopPage must be provided to use the '
+ 'Navigator.pages API'
+ ),
+ library: 'widget library',
+ stack: StackTrace.current,
+ ),
+ );
+ }
+ }
+ return true;
+ }());
for (final NavigatorObserver observer in widget.observers) {
assert(observer.navigator == null);
observer._navigator = this;
@@ -3480,10 +3505,35 @@
@override
void didUpdateWidget(Navigator oldWidget) {
super.didUpdateWidget(oldWidget);
- assert(
- widget.pages.isEmpty || widget.onPopPage != null,
- 'The Navigator.onPopPage must be provided to use the Navigator.pages API',
- );
+ assert((){
+ if (widget.pages != const <Page<dynamic>>[]) {
+ // This navigator uses page API.
+ if (widget.pages.isEmpty) {
+ FlutterError.reportError(
+ FlutterErrorDetails(
+ exception: FlutterError(
+ 'The Navigator.pages must not be empty to use the '
+ 'Navigator.pages API'
+ ),
+ library: 'widget library',
+ stack: StackTrace.current,
+ ),
+ );
+ } else if (widget.onPopPage == null) {
+ FlutterError.reportError(
+ FlutterErrorDetails(
+ exception: FlutterError(
+ 'The Navigator.onPopPage must be provided to use the '
+ 'Navigator.pages API'
+ ),
+ library: 'widget library',
+ stack: StackTrace.current,
+ ),
+ );
+ }
+ }
+ return true;
+ }());
if (oldWidget.observers != widget.observers) {
for (final NavigatorObserver observer in oldWidget.observers)
observer._navigator = null;
@@ -3494,10 +3544,21 @@
_updateEffectiveObservers();
}
if (oldWidget.pages != widget.pages && !restorePending) {
- assert(
- widget.pages.isNotEmpty,
- 'To use the Navigator.pages, there must be at least one page in the list.'
- );
+ assert((){
+ if (widget.pages.isEmpty) {
+ FlutterError.reportError(
+ FlutterErrorDetails(
+ exception: FlutterError(
+ 'The Navigator.pages must not be empty to use the '
+ 'Navigator.pages API'
+ ),
+ library: 'widget library',
+ stack: StackTrace.current,
+ ),
+ );
+ }
+ return true;
+ }());
_updatePages();
}
diff --git a/packages/flutter/test/widgets/navigator_test.dart b/packages/flutter/test/widgets/navigator_test.dart
index 11bde97..1f36249 100644
--- a/packages/flutter/test/widgets/navigator_test.dart
+++ b/packages/flutter/test/widgets/navigator_test.dart
@@ -2608,6 +2608,79 @@
expect(find.text('initial'), findsOneWidget);
});
+ testWidgets('throw if onPopPage callback is not provided', (WidgetTester tester) async {
+ final List<TestPage> myPages = <TestPage>[
+ const TestPage(key: ValueKey<String>('1'), name:'initial'),
+ const TestPage(key: ValueKey<String>('2'), name:'second'),
+ const TestPage(key: ValueKey<String>('3'), name:'third'),
+ ];
+
+ await tester.pumpWidget(
+ MediaQuery(
+ data: MediaQueryData.fromWindow(WidgetsBinding.instance!.window),
+ child: Localizations(
+ locale: const Locale('en', 'US'),
+ delegates: const <LocalizationsDelegate<dynamic>>[
+ DefaultMaterialLocalizations.delegate,
+ DefaultWidgetsLocalizations.delegate
+ ],
+ child: Directionality(
+ textDirection: TextDirection.ltr,
+ child: Navigator(
+ pages: myPages,
+ ),
+ ),
+ ),
+ )
+ );
+
+ final dynamic exception = tester.takeException();
+ expect(exception, isFlutterError);
+ final FlutterError error = exception as FlutterError;
+ expect(
+ error.toStringDeep(),
+ equalsIgnoringHashCodes(
+ 'FlutterError\n'
+ ' The Navigator.onPopPage must be provided to use the\n'
+ ' Navigator.pages API\n'
+ ''
+ ),
+ );
+ });
+
+ testWidgets('throw if page list is empty', (WidgetTester tester) async {
+ final List<TestPage> myPages = <TestPage>[];
+ final FlutterExceptionHandler? originalOnError = FlutterError.onError;
+ FlutterErrorDetails? firstError;
+ FlutterError.onError = (FlutterErrorDetails? detail) {
+ // We only care about the first error;
+ firstError ??= detail;
+ };
+ await tester.pumpWidget(
+ MediaQuery(
+ data: MediaQueryData.fromWindow(WidgetsBinding.instance!.window),
+ child: Localizations(
+ locale: const Locale('en', 'US'),
+ delegates: const <LocalizationsDelegate<dynamic>>[
+ DefaultMaterialLocalizations.delegate,
+ DefaultWidgetsLocalizations.delegate
+ ],
+ child: Directionality(
+ textDirection: TextDirection.ltr,
+ child: Navigator(
+ pages: myPages,
+ ),
+ ),
+ ),
+ )
+ );
+ FlutterError.onError = originalOnError;
+ expect(
+ firstError!.exception.toString(),
+ 'The Navigator.pages must not be empty to use the Navigator.pages API',
+ );
+ });
+
testWidgets('can push and pop pages using page api', (WidgetTester tester) async {
late Animation<double> secondaryAnimationOfRouteOne;
late Animation<double> primaryAnimationOfRouteOne;