diff --git a/dev/integration_tests/ui/lib/commands.dart b/dev/integration_tests/ui/lib/commands.dart index f5d758f369..e15bbad87d 100644 --- a/dev/integration_tests/ui/lib/commands.dart +++ b/dev/integration_tests/ui/lib/commands.dart @@ -15,7 +15,7 @@ void main() { await WidgetsBinding.instance.reassembleApplication(); return log; }); - runApp(const MaterialApp(home: Test())); + runApp(MaterialApp(home: const Test())); } class Test extends SingleChildRenderObjectWidget { diff --git a/dev/manual_tests/lib/animated_icons.dart b/dev/manual_tests/lib/animated_icons.dart index 3cf6f10e1f..718dba876d 100644 --- a/dev/manual_tests/lib/animated_icons.dart +++ b/dev/manual_tests/lib/animated_icons.dart @@ -7,9 +7,9 @@ import 'package:flutter/material.dart'; class AnimatedIconsTestApp extends StatelessWidget { @override Widget build(BuildContext context) { - return const MaterialApp( + return MaterialApp( title: 'Animated Icons Test', - home: Scaffold( + home: const Scaffold( body: IconsList(), ), ); diff --git a/dev/manual_tests/lib/material_arc.dart b/dev/manual_tests/lib/material_arc.dart index 5b7fadaef3..06cdf9f45a 100644 --- a/dev/manual_tests/lib/material_arc.dart +++ b/dev/manual_tests/lib/material_arc.dart @@ -474,7 +474,7 @@ class _AnimationDemoState extends State with TickerProviderStateM } void main() { - runApp(const MaterialApp( - home: AnimationDemo(), + runApp(MaterialApp( + home: const AnimationDemo(), )); } diff --git a/examples/flutter_gallery/test/accessibility_test.dart b/examples/flutter_gallery/test/accessibility_test.dart index 5668126554..423469cc5f 100644 --- a/examples/flutter_gallery/test/accessibility_test.dart +++ b/examples/flutter_gallery/test/accessibility_test.dart @@ -91,7 +91,7 @@ void main() { testWidgets('grid_list_demo', (WidgetTester tester) async { final SemanticsHandle handle = tester.ensureSemantics(); - await tester.pumpWidget(const MaterialApp(home: GridListDemo())); + await tester.pumpWidget(MaterialApp(home: const GridListDemo())); expect(tester, meetsGuideline(androidTapTargetGuideline)); handle.dispose(); }); @@ -105,21 +105,21 @@ void main() { testWidgets('leave_behind_demo', (WidgetTester tester) async { final SemanticsHandle handle = tester.ensureSemantics(); - await tester.pumpWidget(const MaterialApp(home: LeaveBehindDemo())); + await tester.pumpWidget(MaterialApp(home: const LeaveBehindDemo())); expect(tester, meetsGuideline(androidTapTargetGuideline)); handle.dispose(); }); testWidgets('list_demo', (WidgetTester tester) async { final SemanticsHandle handle = tester.ensureSemantics(); - await tester.pumpWidget(const MaterialApp(home: ListDemo())); + await tester.pumpWidget(MaterialApp(home: const ListDemo())); expect(tester, meetsGuideline(androidTapTargetGuideline)); handle.dispose(); }); testWidgets('menu_demo', (WidgetTester tester) async { final SemanticsHandle handle = tester.ensureSemantics(); - await tester.pumpWidget(const MaterialApp(home: MenuDemo())); + await tester.pumpWidget(MaterialApp(home: const MenuDemo())); expect(tester, meetsGuideline(androidTapTargetGuideline)); handle.dispose(); }); @@ -133,7 +133,7 @@ void main() { testWidgets('overscroll_demo', (WidgetTester tester) async { final SemanticsHandle handle = tester.ensureSemantics(); - await tester.pumpWidget(const MaterialApp(home: OverscrollDemo())); + await tester.pumpWidget(MaterialApp(home: const OverscrollDemo())); expect(tester, meetsGuideline(androidTapTargetGuideline)); handle.dispose(); }); @@ -161,7 +161,7 @@ void main() { testWidgets('reorderable_list_demo', (WidgetTester tester) async { final SemanticsHandle handle = tester.ensureSemantics(); - await tester.pumpWidget(const MaterialApp(home: ReorderableListDemo())); + await tester.pumpWidget(MaterialApp(home: const ReorderableListDemo())); expect(tester, meetsGuideline(androidTapTargetGuideline)); handle.dispose(); }); @@ -196,7 +196,7 @@ void main() { testWidgets('snack_bar_demo', (WidgetTester tester) async { final SemanticsHandle handle = tester.ensureSemantics(); - await tester.pumpWidget(const MaterialApp(home: SnackBarDemo())); + await tester.pumpWidget(MaterialApp(home: const SnackBarDemo())); expect(tester, meetsGuideline(androidTapTargetGuideline)); handle.dispose(); }); @@ -217,7 +217,7 @@ void main() { testWidgets('text_form_field_demo', (WidgetTester tester) async { final SemanticsHandle handle = tester.ensureSemantics(); - await tester.pumpWidget(const MaterialApp(home: TextFormFieldDemo())); + await tester.pumpWidget(MaterialApp(home: const TextFormFieldDemo())); expect(tester, meetsGuideline(androidTapTargetGuideline)); handle.dispose(); }); @@ -380,12 +380,12 @@ void main() { handle.dispose(); }); - testWidgets('overscroll_demo', (WidgetTester tester) async { - final SemanticsHandle handle = tester.ensureSemantics(); - await tester.pumpWidget(const MaterialApp(home: OverscrollDemo())); - await expectLater(tester, meetsGuideline(textContrastGuideline)); - handle.dispose(); - }); + testWidgets('overscroll_demo $themeName', (WidgetTester tester) async { + final SemanticsHandle handle = tester.ensureSemantics(); + await tester.pumpWidget(MaterialApp(theme: theme, home: const OverscrollDemo())); + await expectLater(tester, meetsGuideline(textContrastGuideline)); + handle.dispose(); + }); testWidgets('page_selector_demo $themeName', (WidgetTester tester) async { final SemanticsHandle handle = tester.ensureSemantics(); diff --git a/examples/flutter_gallery/test/calculator/smoke_test.dart b/examples/flutter_gallery/test/calculator/smoke_test.dart index 8f4b2e56b8..177ac3d2e1 100644 --- a/examples/flutter_gallery/test/calculator/smoke_test.dart +++ b/examples/flutter_gallery/test/calculator/smoke_test.dart @@ -14,7 +14,7 @@ void main() { // We press the "1" and the "2" buttons and check that the display // reads "12". testWidgets('Flutter calculator app smoke test', (WidgetTester tester) async { - await tester.pumpWidget(const MaterialApp(home: CalculatorDemo())); + await tester.pumpWidget(MaterialApp(home: const CalculatorDemo())); final Finder oneButton = find.widgetWithText(InkResponse, '1'); expect(oneButton, findsOneWidget); diff --git a/examples/flutter_gallery/test/demo/material/text_form_field_demo_test.dart b/examples/flutter_gallery/test/demo/material/text_form_field_demo_test.dart index 7a79303c99..8ca1a276f9 100644 --- a/examples/flutter_gallery/test/demo/material/text_form_field_demo_test.dart +++ b/examples/flutter_gallery/test/demo/material/text_form_field_demo_test.dart @@ -8,7 +8,7 @@ import 'package:flutter_test/flutter_test.dart'; void main() { testWidgets('validates name field correctly', (WidgetTester tester) async { - await tester.pumpWidget(const MaterialApp(home: TextFormFieldDemo())); + await tester.pumpWidget(MaterialApp(home: const TextFormFieldDemo())); final Finder submitButton = find.widgetWithText(RaisedButton, 'SUBMIT'); expect(submitButton, findsOneWidget); diff --git a/packages/flutter/lib/src/cupertino/app.dart b/packages/flutter/lib/src/cupertino/app.dart index b356140877..1bb7d6a268 100644 --- a/packages/flutter/lib/src/cupertino/app.dart +++ b/packages/flutter/lib/src/cupertino/app.dart @@ -8,7 +8,7 @@ import 'package:flutter/widgets.dart'; import 'button.dart'; import 'colors.dart'; import 'icons.dart'; -import 'route.dart'; +import 'tab_view.dart'; // Based on specs from https://developer.apple.com/design/resources/ for // iOS 12. @@ -74,9 +74,8 @@ class CupertinoApp extends StatefulWidget { /// This class creates an instance of [WidgetsApp]. /// /// The boolean arguments, [routes], and [navigatorObservers], must not be null. - const CupertinoApp({ + CupertinoApp({ // can't be const because the asserts use methods on Map :-( Key key, - this.navigatorKey, this.home, this.routes = const {}, this.initialRoute, @@ -98,6 +97,43 @@ class CupertinoApp extends StatefulWidget { this.debugShowCheckedModeBanner = true, }) : assert(routes != null), assert(navigatorObservers != null), + assert( + home == null || + !routes.containsKey(Navigator.defaultRouteName), + 'If the home property is specified, the routes table ' + 'cannot include an entry for "/", since it would be redundant.' + ), + assert( + builder != null || + home != null || + routes.containsKey(Navigator.defaultRouteName) || + onGenerateRoute != null || + onUnknownRoute != null, + 'Either the home property must be specified, ' + 'or the routes table must include an entry for "/", ' + 'or there must be on onGenerateRoute callback specified, ' + 'or there must be an onUnknownRoute callback specified, ' + 'or the builder property must be specified, ' + 'because otherwise there is nothing to fall back on if the ' + 'app is started with an intent that specifies an unknown route.' + ), + assert( + (home != null || + routes.isNotEmpty || + onGenerateRoute != null || + onUnknownRoute != null) + || + (builder != null && + initialRoute == null && + navigatorObservers.isEmpty), + 'If no route is provided using ' + 'home, routes, onGenerateRoute, or onUnknownRoute, ' + 'a non-null callback for the builder property must be provided, ' + 'and the other navigator-related properties, ' + 'navigatorKey, initialRoute, and navigatorObservers, ' + 'must have their initial values ' + '(null, null, and the empty list, respectively).' + ), assert(title != null), assert(showPerformanceOverlay != null), assert(checkerboardRasterCacheImages != null), @@ -106,10 +142,31 @@ class CupertinoApp extends StatefulWidget { assert(debugShowCheckedModeBanner != null), super(key: key); - /// {@macro flutter.widgets.widgetsApp.navigatorKey} - final GlobalKey navigatorKey; - - /// {@macro flutter.widgets.widgetsApp.home} + /// The widget for the default route of the app ([Navigator.defaultRouteName], + /// which is `/`). + /// + /// This is the route that is displayed first when the application is started + /// normally, unless [initialRoute] is specified. It's also the route that's + /// displayed if the [initialRoute] can't be displayed. + /// + /// To be able to directly call [MediaQuery.of], [Navigator.of], etc, in the + /// code that sets the [home] argument in the constructor, you can use a + /// [Builder] widget to get a [BuildContext]. + /// + /// If [home] is specified, then [routes] must not include an entry for `/`, + /// as [home] takes its place. + /// + /// The [Navigator] is only built if routes are provided (either via [home], + /// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not, + /// [builder] must not be null. + /// + /// The difference between using [home] and using [builder] is that the [home] + /// subtree is inserted into the application below a [Navigator] (and thus + /// below an [Overlay], which [Navigator] uses). With [home], therefore, + /// dialog boxes will work automatically, the [routes] table will be used, and + /// APIs such as [Navigator.push] and [Navigator.pop] will work as expected. + /// In contrast, the widget returned from [builder] is inserted _above_ the + /// [CupertinoApp]'s [Navigator] (if any). final Widget home; /// The application's top-level routing table. @@ -119,22 +176,81 @@ class CupertinoApp extends StatefulWidget { /// [WidgetBuilder] is used to construct a [CupertinoPageRoute] that performs /// an appropriate transition, including [Hero] animations, to the new route. /// - /// {@macro flutter.widgets.widgetsApp.routes} + /// If the app only has one page, then you can specify it using [home] instead. + /// + /// If [home] is specified, then it implies an entry in this table for the + /// [Navigator.defaultRouteName] route (`/`), and it is an error to + /// redundantly provide such a route in the [routes] table. + /// + /// If a route is requested that is not specified in this table (or by + /// [home]), then the [onGenerateRoute] callback is called to build the page + /// instead. + /// + /// The [Navigator] is only built if routes are provided (either via [home], + /// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not, + /// [builder] must not be null. final Map routes; /// {@macro flutter.widgets.widgetsApp.initialRoute} + /// + /// The [Navigator] is only built if routes are provided (either via [home], + /// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not, + /// [initialRoute] must be null and [builder] must not be null. + /// + /// See also: + /// + /// * [Navigator.initialRoute], which is used to implement this property. + /// * [Navigator.push], for pushing additional routes. + /// * [Navigator.pop], for removing a route from the stack. final String initialRoute; /// {@macro flutter.widgets.widgetsApp.onGenerateRoute} + /// + /// This is used if [routes] does not contain the requested route. + /// + /// The [Navigator] is only built if routes are provided (either via [home], + /// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not, + /// [builder] must not be null. final RouteFactory onGenerateRoute; + /// Called when [onGenerateRoute] fails to generate a route, except for the + /// [initialRoute]. + /// /// {@macro flutter.widgets.widgetsApp.onUnknownRoute} + /// + /// The [Navigator] is only built if routes are provided (either via [home], + /// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not, + /// [builder] must not be null. final RouteFactory onUnknownRoute; /// {@macro flutter.widgets.widgetsApp.navigatorObservers} + /// + /// The [Navigator] is only built if routes are provided (either via [home], + /// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not, + /// [navigatorObservers] must be the empty list and [builder] must not be null. final List navigatorObservers; /// {@macro flutter.widgets.widgetsApp.builder} + /// + /// If no routes are provided using [home], [routes], [onGenerateRoute], or + /// [onUnknownRoute], the `child` will be null, and it is the responsibility + /// of the [builder] to provide the application's routing machinery. + /// + /// If routes _are_ provided using one or more of those properties, then + /// `child` is not null, and the returned value should include the `child` in + /// the widget subtree; if it does not, then the application will have no + /// navigator and the [navigatorKey], [home], [routes], [onGenerateRoute], + /// [onUnknownRoute], [initialRoute], and [navigatorObservers] properties will + /// have no effect. + /// + /// If [builder] is null, it is as if a builder was specified that returned + /// the `child` directly. If it is null, routes must be provided using one of + /// the other properties listed above. + /// + /// Unless a [Navigator] is provided, either implicitly from [builder] being + /// null, or by a [builder] including its `child` argument, or by a [builder] + /// explicitly providing a [Navigator] of its own, widgets and APIs such as + /// [Hero], [Navigator.push] and [Navigator.pop], will not function. final TransitionBuilder builder; /// {@macro flutter.widgets.widgetsApp.title} @@ -188,12 +304,6 @@ class CupertinoApp extends StatefulWidget { @override _CupertinoAppState createState() => _CupertinoAppState(); - - /// The [HeroController] used for Cupertino page transitions. - /// - /// Used by [CupertinoTabView] and [CupertinoApp]. - static HeroController createCupertinoHeroController() => - HeroController(); // Linear tweening. } class _AlwaysCupertinoScrollBehavior extends ScrollBehavior { @@ -210,39 +320,51 @@ class _AlwaysCupertinoScrollBehavior extends ScrollBehavior { } class _CupertinoAppState extends State { - HeroController _heroController; @override void initState() { super.initState(); - _heroController = CupertinoApp.createCupertinoHeroController(); _updateNavigator(); } @override void didUpdateWidget(CupertinoApp oldWidget) { super.didUpdateWidget(oldWidget); - if (widget.navigatorKey != oldWidget.navigatorKey) { - // If the Navigator changes, we have to create a new observer, because the - // old Navigator won't be disposed (and thus won't unregister with its - // observers) until after the new one has been created (because the - // Navigator has a GlobalKey). - _heroController = CupertinoApp.createCupertinoHeroController(); - } _updateNavigator(); } - List _navigatorObservers; - + bool _haveNavigator; void _updateNavigator() { - if (widget.home != null || - widget.routes.isNotEmpty || - widget.onGenerateRoute != null || - widget.onUnknownRoute != null) { - _navigatorObservers = List.from(widget.navigatorObservers) - ..add(_heroController); + _haveNavigator = widget.home != null || + widget.routes.isNotEmpty || + widget.onGenerateRoute != null || + widget.onUnknownRoute != null; + } + + Widget defaultBuilder(BuildContext context, Widget child) { + // The `child` coming back out from WidgetsApp will always be null since + // we never passed in anything for it to create a Navigator inside + // WidgetsApp. + assert(child == null); + if (_haveNavigator) { + // Reuse CupertinoTabView which creates a routing Navigator for us. + final Widget navigator = CupertinoTabView( + builder: widget.home != null + ? (BuildContext context) => widget.home + : null, + routes: widget.routes, + onGenerateRoute: widget.onGenerateRoute, + onUnknownRoute: widget.onUnknownRoute, + navigatorObservers: widget.navigatorObservers, + ); + if (widget.builder != null) { + return widget.builder(context, navigator); + } else { + return navigator; + } } else { - _navigatorObservers = null; + // We asserted that child is null above. + return widget.builder(context, null); } } @@ -252,16 +374,10 @@ class _CupertinoAppState extends State { behavior: _AlwaysCupertinoScrollBehavior(), child: WidgetsApp( key: GlobalObjectKey(this), - navigatorKey: widget.navigatorKey, - navigatorObservers: _navigatorObservers, - pageRouteBuilder: (RouteSettings settings, WidgetBuilder builder) => - CupertinoPageRoute(settings: settings, builder: builder), - home: widget.home, - routes: widget.routes, - initialRoute: widget.initialRoute, - onGenerateRoute: widget.onGenerateRoute, - onUnknownRoute: widget.onUnknownRoute, - builder: widget.builder, + // We're passing in a builder and nothing else that the WidgetsApp uses + // to build its own Navigator because we're building a Navigator with + // routes in this class. + builder: defaultBuilder, title: widget.title, onGenerateTitle: widget.onGenerateTitle, textStyle: _kDefaultTextStyle, diff --git a/packages/flutter/lib/src/cupertino/tab_view.dart b/packages/flutter/lib/src/cupertino/tab_view.dart index 08bb6151e8..d27a86cd9c 100644 --- a/packages/flutter/lib/src/cupertino/tab_view.dart +++ b/packages/flutter/lib/src/cupertino/tab_view.dart @@ -4,7 +4,6 @@ import 'package:flutter/widgets.dart'; -import 'app.dart' show CupertinoApp; import 'route.dart'; /// A single tab view with its own [Navigator] state and history. @@ -115,7 +114,7 @@ class _CupertinoTabViewState extends State { @override void initState() { super.initState(); - _heroController = CupertinoApp.createCupertinoHeroController(); + _heroController = HeroController(); // Linear tweening. _updateObservers(); } diff --git a/packages/flutter/lib/src/material/app.dart b/packages/flutter/lib/src/material/app.dart index 429811712f..a47f803f82 100644 --- a/packages/flutter/lib/src/material/app.dart +++ b/packages/flutter/lib/src/material/app.dart @@ -79,7 +79,7 @@ class MaterialApp extends StatefulWidget { /// This class creates an instance of [WidgetsApp]. /// /// The boolean arguments, [routes], and [navigatorObservers], must not be null. - const MaterialApp({ + MaterialApp({ // can't be const because the asserts use methods on Map :-( Key key, this.navigatorKey, this.home, @@ -105,6 +105,44 @@ class MaterialApp extends StatefulWidget { this.debugShowCheckedModeBanner = true, }) : assert(routes != null), assert(navigatorObservers != null), + assert( + home == null || + !routes.containsKey(Navigator.defaultRouteName), + 'If the home property is specified, the routes table ' + 'cannot include an entry for "/", since it would be redundant.' + ), + assert( + builder != null || + home != null || + routes.containsKey(Navigator.defaultRouteName) || + onGenerateRoute != null || + onUnknownRoute != null, + 'Either the home property must be specified, ' + 'or the routes table must include an entry for "/", ' + 'or there must be on onGenerateRoute callback specified, ' + 'or there must be an onUnknownRoute callback specified, ' + 'or the builder property must be specified, ' + 'because otherwise there is nothing to fall back on if the ' + 'app is started with an intent that specifies an unknown route.' + ), + assert( + (home != null || + routes.isNotEmpty || + onGenerateRoute != null || + onUnknownRoute != null) + || + (builder != null && + navigatorKey == null && + initialRoute == null && + navigatorObservers.isEmpty), + 'If no route is provided using ' + 'home, routes, onGenerateRoute, or onUnknownRoute, ' + 'a non-null callback for the builder property must be provided, ' + 'and the other navigator-related properties, ' + 'navigatorKey, initialRoute, and navigatorObservers, ' + 'must have their initial values ' + '(null, null, and the empty list, respectively).' + ), assert(title != null), assert(debugShowMaterialGrid != null), assert(showPerformanceOverlay != null), @@ -114,10 +152,48 @@ class MaterialApp extends StatefulWidget { assert(debugShowCheckedModeBanner != null), super(key: key); - /// {@macro flutter.widgets.widgetsApp.navigatorKey} + /// A key to use when building the [Navigator]. + /// + /// If a [navigatorKey] is specified, the [Navigator] can be directly + /// manipulated without first obtaining it from a [BuildContext] via + /// [Navigator.of]: from the [navigatorKey], use the [GlobalKey.currentState] + /// getter. + /// + /// If this is changed, a new [Navigator] will be created, losing all the + /// application state in the process; in that case, the [navigatorObservers] + /// must also be changed, since the previous observers will be attached to the + /// previous navigator. + /// + /// The [Navigator] is only built if routes are provided (either via [home], + /// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not, + /// [navigatorKey] must be null and [builder] must not be null. final GlobalKey navigatorKey; - /// {@macro flutter.widgets.widgetsApp.home} + /// The widget for the default route of the app ([Navigator.defaultRouteName], + /// which is `/`). + /// + /// This is the route that is displayed first when the application is started + /// normally, unless [initialRoute] is specified. It's also the route that's + /// displayed if the [initialRoute] can't be displayed. + /// + /// To be able to directly call [Theme.of], [MediaQuery.of], etc, in the code + /// that sets the [home] argument in the constructor, you can use a [Builder] + /// widget to get a [BuildContext]. + /// + /// If [home] is specified, then [routes] must not include an entry for `/`, + /// as [home] takes its place. + /// + /// The [Navigator] is only built if routes are provided (either via [home], + /// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not, + /// [builder] must not be null. + /// + /// The difference between using [home] and using [builder] is that the [home] + /// subtree is inserted into the application below a [Navigator] (and thus + /// below an [Overlay], which [Navigator] uses). With [home], therefore, + /// dialog boxes will work automatically, [Tooltip]s will work, the [routes] + /// table will be used, and APIs such as [Navigator.push] and [Navigator.pop] + /// will work as expected. In contrast, the widget returned from [builder] is + /// inserted _above_ the [MaterialApp]'s [Navigator] (if any). final Widget home; /// The application's top-level routing table. @@ -127,25 +203,82 @@ class MaterialApp extends StatefulWidget { /// [WidgetBuilder] is used to construct a [MaterialPageRoute] that performs /// an appropriate transition, including [Hero] animations, to the new route. /// - /// {@macro flutter.widgets.widgetsApp.routes} + /// If the app only has one page, then you can specify it using [home] instead. + /// + /// If [home] is specified, then it implies an entry in this table for the + /// [Navigator.defaultRouteName] route (`/`), and it is an error to + /// redundantly provide such a route in the [routes] table. + /// + /// If a route is requested that is not specified in this table (or by + /// [home]), then the [onGenerateRoute] callback is called to build the page + /// instead. + /// + /// The [Navigator] is only built if routes are provided (either via [home], + /// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not, + /// [builder] must not be null. final Map routes; /// {@macro flutter.widgets.widgetsApp.initialRoute} + /// + /// The [Navigator] is only built if routes are provided (either via [home], + /// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not, + /// [initialRoute] must be null and [builder] must not be null. + /// + /// See also: + /// + /// * [Navigator.initialRoute], which is used to implement this property. + /// * [Navigator.push], for pushing additional routes. + /// * [Navigator.pop], for removing a route from the stack. final String initialRoute; /// {@macro flutter.widgets.widgetsApp.onGenerateRoute} + /// + /// This is used if [routes] does not contain the requested route. + /// + /// The [Navigator] is only built if routes are provided (either via [home], + /// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not, + /// [builder] must not be null. final RouteFactory onGenerateRoute; + /// Called when [onGenerateRoute] fails to generate a route, except for the + /// [initialRoute]. + /// /// {@macro flutter.widgets.widgetsApp.onUnknownRoute} + /// + /// The [Navigator] is only built if routes are provided (either via [home], + /// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not, + /// [builder] must not be null. final RouteFactory onUnknownRoute; /// {@macro flutter.widgets.widgetsApp.navigatorObservers} + /// + /// The [Navigator] is only built if routes are provided (either via [home], + /// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not, + /// [navigatorObservers] must be the empty list and [builder] must not be null. final List navigatorObservers; /// {@macro flutter.widgets.widgetsApp.builder} /// - /// Material specific features such as [showDialog] and [showMenu], and widgets - /// such as [Tooltip], [PopupMenuButton], also require a [Navigator] to properly + /// If no routes are provided using [home], [routes], [onGenerateRoute], or + /// [onUnknownRoute], the `child` will be null, and it is the responsibility + /// of the [builder] to provide the application's routing machinery. + /// + /// If routes _are_ provided using one or more of those properties, then + /// `child` is not null, and the returned value should include the `child` in + /// the widget subtree; if it does not, then the application will have no + /// navigator and the [navigatorKey], [home], [routes], [onGenerateRoute], + /// [onUnknownRoute], [initialRoute], and [navigatorObservers] properties will + /// have no effect. + /// + /// If [builder] is null, it is as if a builder was specified that returned + /// the `child` directly. If it is null, routes must be provided using one of + /// the other properties listed above. + /// + /// Unless a [Navigator] is provided, either implicitly from [builder] being + /// null, or by a [builder] including its `child` argument, or by a [builder] + /// explicitly providing a [Navigator] of its own, features such as + /// [showDialog] and [showMenu], widgets such as [Tooltip], [PopupMenuButton], + /// or [Hero], and APIs such as [Navigator.push] and [Navigator.pop], will not /// function. final TransitionBuilder builder; @@ -339,24 +472,73 @@ class _MaterialAppState extends State { _updateNavigator(); } + bool _haveNavigator; List _navigatorObservers; void _updateNavigator() { - if (widget.home != null || - widget.routes.isNotEmpty || - widget.onGenerateRoute != null || - widget.onUnknownRoute != null) { - _navigatorObservers = List.from(widget.navigatorObservers) - ..add(_heroController); - } else { - _navigatorObservers = null; - } + _haveNavigator = widget.home != null || + widget.routes.isNotEmpty || + widget.onGenerateRoute != null || + widget.onUnknownRoute != null; + _navigatorObservers = List.from(widget.navigatorObservers) + ..add(_heroController); } RectTween _createRectTween(Rect begin, Rect end) { return MaterialRectArcTween(begin: begin, end: end); } + Route _onGenerateRoute(RouteSettings settings) { + final String name = settings.name; + WidgetBuilder builder; + if (name == Navigator.defaultRouteName && widget.home != null) { + builder = (BuildContext context) => widget.home; + } else { + builder = widget.routes[name]; + } + if (builder != null) { + return MaterialPageRoute( + builder: builder, + settings: settings, + ); + } + if (widget.onGenerateRoute != null) + return widget.onGenerateRoute(settings); + return null; + } + + Route _onUnknownRoute(RouteSettings settings) { + assert(() { + if (widget.onUnknownRoute == null) { + throw FlutterError( + 'Could not find a generator for route $settings in the $runtimeType.\n' + 'Generators for routes are searched for in the following order:\n' + ' 1. For the "/" route, the "home" property, if non-null, is used.\n' + ' 2. Otherwise, the "routes" table is used, if it has an entry for ' + 'the route.\n' + ' 3. Otherwise, onGenerateRoute is called. It should return a ' + 'non-null value for any valid route not handled by "home" and "routes".\n' + ' 4. Finally if all else fails onUnknownRoute is called.\n' + 'Unfortunately, onUnknownRoute was not set.' + ); + } + return true; + }()); + final Route result = widget.onUnknownRoute(settings); + assert(() { + if (result == null) { + throw FlutterError( + 'The onUnknownRoute callback returned null.\n' + 'When the $runtimeType requested the route $settings from its ' + 'onUnknownRoute callback, the callback returned null. Such callbacks ' + 'must never return null.' + ); + } + return true; + }()); + return result; + } + // Combine the Localizations for Material with the ones contributed // by the localizationsDelegates parameter, if any. Only the first delegate // of a particular LocalizationsDelegate.type is loaded so the @@ -377,14 +559,10 @@ class _MaterialAppState extends State { child: WidgetsApp( key: GlobalObjectKey(this), navigatorKey: widget.navigatorKey, - navigatorObservers: _navigatorObservers, - pageRouteBuilder: (RouteSettings settings, WidgetBuilder builder) => - MaterialPageRoute(settings: settings, builder: builder), - home: widget.home, - routes: widget.routes, + navigatorObservers: _haveNavigator ? _navigatorObservers : null, initialRoute: widget.initialRoute, - onGenerateRoute: widget.onGenerateRoute, - onUnknownRoute: widget.onUnknownRoute, + onGenerateRoute: _haveNavigator ? _onGenerateRoute : null, + onUnknownRoute: _haveNavigator ? _onUnknownRoute : null, builder: widget.builder, title: widget.title, onGenerateTitle: widget.onGenerateTitle, diff --git a/packages/flutter/lib/src/widgets/app.dart b/packages/flutter/lib/src/widgets/app.dart index 627554868e..e8c95eaee4 100644 --- a/packages/flutter/lib/src/widgets/app.dart +++ b/packages/flutter/lib/src/widgets/app.dart @@ -14,7 +14,6 @@ import 'framework.dart'; import 'localizations.dart'; import 'media_query.dart'; import 'navigator.dart'; -import 'pages.dart'; import 'performance_overlay.dart'; import 'semantics_debugger.dart'; import 'text.dart'; @@ -44,11 +43,6 @@ typedef LocaleResolutionCallback = Locale Function(Locale locale, Iterable Function(RouteSettings settings, WidgetBuilder builder); - /// A convenience class that wraps a number of widgets that are commonly /// required for an application. /// @@ -64,10 +58,8 @@ class WidgetsApp extends StatefulWidget { /// /// The boolean arguments, [color], and [navigatorObservers] must not be null. /// - /// If the [builder] is null, the [onGenerateRoute] and [pageRouteBuilder] - /// arguments are required. The [onGenerateRoute] parameter corresponds to - /// [Navigator.onGenerateRoute], and [pageRouteBuilder] will create a [PageRoute] - /// that wraps newly built routes. If the [builder] is non-null + /// If the [builder] is null, the [onGenerateRoute] argument is required, and + /// corresponds to [Navigator.onGenerateRoute]. If the [builder] is non-null /// and the [onGenerateRoute] argument is null, then the [builder] will not be /// provided with a [Navigator]. If [onGenerateRoute] is not provided, /// [navigatorKey], [onUnknownRoute], [navigatorObservers], and [initialRoute] @@ -82,9 +74,6 @@ class WidgetsApp extends StatefulWidget { this.onUnknownRoute, this.navigatorObservers = const [], this.initialRoute, - this.pageRouteBuilder, - this.home, - this.routes = const {}, this.builder, this.title = '', this.onGenerateTitle, @@ -102,49 +91,11 @@ class WidgetsApp extends StatefulWidget { this.debugShowCheckedModeBanner = true, this.inspectorSelectButtonBuilder, }) : assert(navigatorObservers != null), - assert(routes != null), - assert( - home == null || - !routes.containsKey(Navigator.defaultRouteName), - 'If the home property is specified, the routes table ' - 'cannot include an entry for "/", since it would be redundant.' - ), - assert( - builder != null || - home != null || - routes.containsKey(Navigator.defaultRouteName) || - onGenerateRoute != null || - onUnknownRoute != null, - 'Either the home property must be specified, ' - 'or the routes table must include an entry for "/", ' - 'or there must be on onGenerateRoute callback specified, ' - 'or there must be an onUnknownRoute callback specified, ' - 'or the builder property must be specified, ' - 'because otherwise there is nothing to fall back on if the ' - 'app is started with an intent that specifies an unknown route.' - ), - assert( - (home != null || - routes.isNotEmpty || - onGenerateRoute != null || - onUnknownRoute != null) - || - (builder != null && - navigatorKey == null && - initialRoute == null && - navigatorObservers.isEmpty), - 'If no route is provided using ' - 'home, routes, onGenerateRoute, or onUnknownRoute, ' - 'a non-null callback for the builder property must be provided, ' - 'and the other navigator-related properties, ' - 'navigatorKey, initialRoute, and navigatorObservers, ' - 'must have their initial values ' - '(null, null, and the empty list, respectively).' - ), - assert(onGenerateRoute != null || pageRouteBuilder != null, - 'If onGenerateRoute is not provided, the pageRouteBuilder must be specified ' - 'so that the default handler will know what kind of PageRoute transition ' - 'bo build.'), + assert(onGenerateRoute != null || navigatorKey == null), + assert(onGenerateRoute != null || onUnknownRoute == null), + assert(onGenerateRoute != null || navigatorObservers == const []), + assert(onGenerateRoute != null || initialRoute == null), + assert(onGenerateRoute != null || builder != null), assert(title != null), assert(color != null), assert(supportedLocales != null && supportedLocales.isNotEmpty), @@ -156,7 +107,6 @@ class WidgetsApp extends StatefulWidget { assert(debugShowWidgetInspector != null), super(key: key); - /// {@template flutter.widgets.widgetsApp.navigatorKey} /// A key to use when building the [Navigator]. /// /// If a [navigatorKey] is specified, the [Navigator] can be directly @@ -171,7 +121,6 @@ class WidgetsApp extends StatefulWidget { /// /// The [Navigator] is only built if [onGenerateRoute] is not null; if it is /// null, [navigatorKey] must also be null. - /// {@endTemplate} final GlobalKey navigatorKey; /// {@template flutter.widgets.widgetsApp.onGenerateRoute} @@ -185,103 +134,25 @@ class WidgetsApp extends StatefulWidget { /// During normal app operation, the [onGenerateRoute] callback will only be /// applied to route names pushed by the application, and so should never /// return null. - /// - /// This is used if [routes] does not contain the requested route. - /// - /// The [Navigator] is only built if routes are provided (either via [home], - /// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not, - /// [builder] must not be null. /// {@endtemplate} /// - /// If this property is not set, either the [routes] or [home] properties must - /// be set, and the [pageRouteBuilder] must also be set so that the - /// default handler will know what routes and [PageRoute]s to build. + /// The [Navigator] is only built if [onGenerateRoute] is not null. If + /// [onGenerateRoute] is null, the [builder] must be non-null. final RouteFactory onGenerateRoute; - /// The [PageRoute] generator callback used when the app is navigated to a - /// named route. + /// Called when [onGenerateRoute] fails to generate a route. /// - /// This callback can be used, for example, to specify that a [MaterialPageRoute] - /// or a [CupertinoPageRoute] should be used for building page transitions. - final PageRouteFactory pageRouteBuilder; - - /// {@template flutter.widgets.widgetsApp.home} - /// The widget for the default route of the app ([Navigator.defaultRouteName], - /// which is `/`). - /// - /// This is the route that is displayed first when the application is started - /// normally, unless [initialRoute] is specified. It's also the route that's - /// displayed if the [initialRoute] can't be displayed. - /// - /// To be able to directly call [Theme.of], [MediaQuery.of], etc, in the code - /// that sets the [home] argument in the constructor, you can use a [Builder] - /// widget to get a [BuildContext]. - /// - /// If [home] is specified, then [routes] must not include an entry for `/`, - /// as [home] takes its place. - /// - /// The [Navigator] is only built if routes are provided (either via [home], - /// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not, - /// [builder] must not be null. - /// - /// The difference between using [home] and using [builder] is that the [home] - /// subtree is inserted into the application below a [Navigator] (and thus - /// below an [Overlay], which [Navigator] uses). With [home], therefore, - /// dialog boxes will work automatically, the [routes] table will be used, and - /// APIs such as [Navigator.push] and [Navigator.pop] will work as expected. - /// In contrast, the widget returned from [builder] is inserted _above_ the - /// app's [Navigator] (if any). - /// {@endTemplate} - /// - /// If this property is set, the [pageRouteBuilder] property must also be set - /// so that the default route handler will know what kind of [PageRoute]s to - /// build. - final Widget home; - - /// The application's top-level routing table. - /// - /// When a named route is pushed with [Navigator.pushNamed], the route name is - /// looked up in this map. If the name is present, the associated - /// [WidgetBuilder] is used to construct a [PageRoute] specified by - /// [pageRouteBuilder] to perform an appropriate transition, including [Hero] - /// animations, to the new route. - /// - /// {@template flutter.widgets.widgetsApp.routes} - /// If the app only has one page, then you can specify it using [home] instead. - /// - /// If [home] is specified, then it implies an entry in this table for the - /// [Navigator.defaultRouteName] route (`/`), and it is an error to - /// redundantly provide such a route in the [routes] table. - /// - /// If a route is requested that is not specified in this table (or by - /// [home]), then the [onGenerateRoute] callback is called to build the page - /// instead. - /// - /// The [Navigator] is only built if routes are provided (either via [home], - /// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not, - /// [builder] must not be null. - /// {@endTemplate} - /// - /// If the routes map is not empty, the [pageRouteBuilder] property must be set - /// so that the default route handler will know what kind of [PageRoute]s to - /// build. - final Map routes; - /// {@template flutter.widgets.widgetsApp.onUnknownRoute} - /// Called when [onGenerateRoute] fails to generate a route, except for the - /// [initialRoute]. - /// /// This callback is typically used for error handling. For example, this /// callback might always generate a "not found" page that describes the route /// that wasn't found. /// /// Unknown routes can arise either from errors in the app or from external /// requests to push routes, such as from Android intents. - /// - /// The [Navigator] is only built if routes are provided (either via [home], - /// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not, - /// [builder] must not be null. /// {@endtemplate} + /// + /// The [Navigator] is only built if [onGenerateRoute] is not null; if it is + /// null, [onUnknownRoute] must also be null. final RouteFactory onUnknownRoute; /// {@template flutter.widgets.widgetsApp.initialRoute} @@ -299,16 +170,16 @@ class WidgetsApp extends StatefulWidget { /// [initialRoute] is ignored and [Navigator.defaultRouteName] is used instead /// (`/`). This can happen if the app is started with an intent that specifies /// a non-existent route. - /// The [Navigator] is only built if routes are provided (either via [home], - /// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not, - /// [initialRoute] must be null and [builder] must not be null. + /// {@endtemplate} + /// + /// The [Navigator] is only built if [onGenerateRoute] is not null; if it is + /// null, [initialRoute] must also be null. /// /// See also: /// /// * [Navigator.initialRoute], which is used to implement this property. /// * [Navigator.push], for pushing additional routes. /// * [Navigator.pop], for removing a route from the stack. - /// {@endtemplate} final String initialRoute; /// {@template flutter.widgets.widgetsApp.navigatorObservers} @@ -316,11 +187,11 @@ class WidgetsApp extends StatefulWidget { /// /// This list must be replaced by a list of newly-created observers if the /// [navigatorKey] is changed. - /// - /// The [Navigator] is only built if routes are provided (either via [home], - /// [routes], [onGenerateRoute], or [onUnknownRoute]); if they are not, - /// [navigatorObservers] must be the empty list and [builder] must not be null. /// {@endtemplate} + /// + /// The [Navigator] is only built if [onGenerateRoute] is not null; if it is + /// null, [navigatorObservers] must be left to its default value, the empty + /// list. final List navigatorObservers; /// {@template flutter.widgets.widgetsApp.builder} @@ -343,27 +214,21 @@ class WidgetsApp extends StatefulWidget { /// /// The [builder] callback is passed two arguments, the [BuildContext] (as /// `context`) and a [Navigator] widget (as `child`). + /// {@endtemplate} /// - /// If no routes are provided using [home], [routes], [onGenerateRoute], or - /// [onUnknownRoute], the `child` will be null, and it is the responsibility - /// of the [builder] to provide the application's routing machinery. + /// If [onGenerateRoute] is null, the `child` will be null, and it is the + /// responsibility of the [builder] to provide the application's routing + /// machinery. /// - /// If routes _are_ provided using one or more of those properties, then - /// `child` is not null, and the returned value should include the `child` in - /// the widget subtree; if it does not, then the application will have no - /// navigator and the [navigatorKey], [home], [routes], [onGenerateRoute], - /// [onUnknownRoute], [initialRoute], and [navigatorObservers] properties will - /// have no effect. + /// If [onGenerateRoute] is not null, then `child` is not null, and the + /// returned value should include the `child` in the widget subtree; if it + /// does not, then the application will have no navigator and the + /// [navigatorKey], [onGenerateRoute], [onUnknownRoute], [initialRoute], and + /// [navigatorObservers] properties will have no effect. /// /// If [builder] is null, it is as if a builder was specified that returned - /// the `child` directly. If it is null, routes must be provided using one of - /// the other properties listed above. - /// - /// Unless a [Navigator] is provided, either implicitly from [builder] being - /// null, or by a [builder] including its `child` argument, or by a [builder] - /// explicitly providing a [Navigator] of its own, widgets and APIs such as - /// [Hero], [Navigator.push] and [Navigator.pop], will not function. - /// {@endtemplate} + /// the `child` directly. At least one of either [onGenerateRoute] or + /// [builder] must be non-null. final TransitionBuilder builder; /// {@template flutter.widgets.widgetsApp.title} @@ -590,64 +455,11 @@ class _WidgetsAppState extends State implements WidgetsBindingObserv GlobalKey _navigator; void _updateNavigator() { - _navigator = widget.navigatorKey ?? GlobalObjectKey(this); - } - - Route _onGenerateRoute(RouteSettings settings) { - final String name = settings.name; - WidgetBuilder builder; - if (name == Navigator.defaultRouteName && widget.home != null) { - builder = (BuildContext context) => widget.home; + if (widget.onGenerateRoute == null) { + _navigator = null; } else { - builder = widget.routes[name]; + _navigator = widget.navigatorKey ?? GlobalObjectKey(this); } - if (builder != null) { - assert(widget.pageRouteBuilder != null, - 'The default onGenerateRoute handler for WidgetsApp must have a ' - 'pageRouteBuilder set if the home or routes properties are set.'); - final Route route = widget.pageRouteBuilder( - settings, - builder, - ); - assert(route != null, - 'The pageRouteBuilder for WidgetsApp must return a valid non-null Route.'); - return route; - } - if (widget.onGenerateRoute != null) - return widget.onGenerateRoute(settings); - return null; - } - - Route _onUnknownRoute(RouteSettings settings) { - assert(() { - if (widget.onUnknownRoute == null) { - throw FlutterError( - 'Could not find a generator for route $settings in the $runtimeType.\n' - 'Generators for routes are searched for in the following order:\n' - ' 1. For the "/" route, the "home" property, if non-null, is used.\n' - ' 2. Otherwise, the "routes" table is used, if it has an entry for ' - 'the route.\n' - ' 3. Otherwise, onGenerateRoute is called. It should return a ' - 'non-null value for any valid route not handled by "home" and "routes".\n' - ' 4. Finally if all else fails onUnknownRoute is called.\n' - 'Unfortunately, onUnknownRoute was not set.' - ); - } - return true; - }()); - final Route result = widget.onUnknownRoute(settings); - assert(() { - if (result == null) { - throw FlutterError( - 'The onUnknownRoute callback returned null.\n' - 'When the $runtimeType requested the route $settings from its ' - 'onUnknownRoute callback, the callback returned null. Such callbacks ' - 'must never return null.' - ); - } - return true; - }()); - return result; } // On Android: the user has pressed the back button. @@ -754,14 +566,9 @@ class _WidgetsAppState extends State implements WidgetsBindingObserv if (_navigator != null) { navigator = Navigator( key: _navigator, - // If ui.window.defaultRouteName isn't '/', we should assume it was set - // intentionally via `setInitialRoute`, and should override whatever - // is in [widget.initialRoute]. - initialRoute: ui.window.defaultRouteName != Navigator.defaultRouteName - ? ui.window.defaultRouteName - : widget.initialRoute ?? ui.window.defaultRouteName, - onGenerateRoute: _onGenerateRoute, - onUnknownRoute: _onUnknownRoute, + initialRoute: widget.initialRoute ?? ui.window.defaultRouteName, + onGenerateRoute: widget.onGenerateRoute, + onUnknownRoute: widget.onUnknownRoute, observers: widget.navigatorObservers, ); } diff --git a/packages/flutter/test/cupertino/dialog_test.dart b/packages/flutter/test/cupertino/dialog_test.dart index 29a3bccb9e..65133e9d6f 100644 --- a/packages/flutter/test/cupertino/dialog_test.dart +++ b/packages/flutter/test/cupertino/dialog_test.dart @@ -66,7 +66,7 @@ void main() { testWidgets('Has semantic annotations', (WidgetTester tester) async { final SemanticsTester semantics = SemanticsTester(tester); - await tester.pumpWidget(const MaterialApp(home: Material( + await tester.pumpWidget(MaterialApp(home: const Material( child: CupertinoAlertDialog( title: Text('The Title'), content: Text('Content'), diff --git a/packages/flutter/test/cupertino/nav_bar_test.dart b/packages/flutter/test/cupertino/nav_bar_test.dart index 3ccadc00ed..8ca3f6c5df 100644 --- a/packages/flutter/test/cupertino/nav_bar_test.dart +++ b/packages/flutter/test/cupertino/nav_bar_test.dart @@ -16,8 +16,8 @@ int count = 0; void main() { testWidgets('Middle still in center with asymmetrical actions', (WidgetTester tester) async { await tester.pumpWidget( - const CupertinoApp( - home: CupertinoNavigationBar( + CupertinoApp( + home: const CupertinoNavigationBar( leading: CupertinoButton(child: Text('Something'), onPressed: null,), middle: Text('Title'), ), @@ -30,8 +30,8 @@ void main() { testWidgets('Middle still in center with back button', (WidgetTester tester) async { await tester.pumpWidget( - const CupertinoApp( - home: CupertinoNavigationBar( + CupertinoApp( + home: const CupertinoNavigationBar( middle: Text('Title'), ), ), @@ -54,8 +54,8 @@ void main() { testWidgets('Opaque background does not add blur effects', (WidgetTester tester) async { await tester.pumpWidget( - const CupertinoApp( - home: CupertinoNavigationBar( + CupertinoApp( + home: const CupertinoNavigationBar( middle: Text('Title'), backgroundColor: Color(0xFFE5E5E5), ), @@ -66,8 +66,8 @@ void main() { testWidgets('Non-opaque background adds blur effects', (WidgetTester tester) async { await tester.pumpWidget( - const CupertinoApp( - home: CupertinoNavigationBar( + CupertinoApp( + home: const CupertinoNavigationBar( middle: Text('Title'), ), ), @@ -120,8 +120,8 @@ void main() { testWidgets('Padding works in RTL', (WidgetTester tester) async { await tester.pumpWidget( - const CupertinoApp( - home: Directionality( + CupertinoApp( + home: const Directionality( textDirection: TextDirection.rtl, child: Align( alignment: Alignment.topCenter, @@ -151,8 +151,8 @@ void main() { testWidgets('Verify styles of each slot', (WidgetTester tester) async { count = 0x000000; await tester.pumpWidget( - const CupertinoApp( - home: CupertinoNavigationBar( + CupertinoApp( + home: const CupertinoNavigationBar( leading: _ExpectStyles(color: Color(0xFF001122), index: 0x000001), middle: _ExpectStyles(color: Color(0xFF000000), letterSpacing: -0.08, index: 0x000100), trailing: _ExpectStyles(color: Color(0xFF001122), index: 0x010000), @@ -165,8 +165,8 @@ void main() { testWidgets('No slivers with no large titles', (WidgetTester tester) async { await tester.pumpWidget( - const CupertinoApp( - home: CupertinoPageScaffold( + CupertinoApp( + home: const CupertinoPageScaffold( navigationBar: CupertinoNavigationBar( middle: Text('Title'), ), @@ -431,8 +431,8 @@ void main() { testWidgets('Auto back/close button', (WidgetTester tester) async { await tester.pumpWidget( - const CupertinoApp( - home: CupertinoNavigationBar( + CupertinoApp( + home: const CupertinoNavigationBar( middle: Text('Home page'), ), ), @@ -486,8 +486,8 @@ void main() { testWidgets('Long back label turns into "back"', (WidgetTester tester) async { await tester.pumpWidget( - const CupertinoApp( - home: Placeholder(), + CupertinoApp( + home: const Placeholder(), ), ); @@ -529,8 +529,8 @@ void main() { testWidgets('Border should be displayed by default', (WidgetTester tester) async { await tester.pumpWidget( - const CupertinoApp( - home: CupertinoNavigationBar( + CupertinoApp( + home: const CupertinoNavigationBar( middle: Text('Title'), ), ), @@ -551,8 +551,8 @@ void main() { testWidgets('Overrides border color', (WidgetTester tester) async { await tester.pumpWidget( - const CupertinoApp( - home: CupertinoNavigationBar( + CupertinoApp( + home: const CupertinoNavigationBar( middle: Text('Title'), border: Border( bottom: BorderSide( @@ -580,8 +580,8 @@ void main() { testWidgets('Border should not be displayed when null', (WidgetTester tester) async { await tester.pumpWidget( - const CupertinoApp( - home: CupertinoNavigationBar( + CupertinoApp( + home: const CupertinoNavigationBar( middle: Text('Title'), border: null, ), @@ -746,8 +746,8 @@ void main() { 'Standard title golden', (WidgetTester tester) async { await tester.pumpWidget( - const CupertinoApp( - home: RepaintBoundary( + CupertinoApp( + home: const RepaintBoundary( child: CupertinoPageScaffold( navigationBar: CupertinoNavigationBar( middle: Text('Bling bling'), diff --git a/packages/flutter/test/cupertino/nav_bar_transition_test.dart b/packages/flutter/test/cupertino/nav_bar_transition_test.dart index a4b2e8a688..d7715a4e56 100644 --- a/packages/flutter/test/cupertino/nav_bar_transition_test.dart +++ b/packages/flutter/test/cupertino/nav_bar_transition_test.dart @@ -14,8 +14,8 @@ Future startTransitionBetween( String toTitle, }) async { await tester.pumpWidget( - const CupertinoApp( - home: Placeholder(), + CupertinoApp( + home: const Placeholder(), ), ); @@ -195,8 +195,8 @@ void main() { testWidgets('Fullscreen dialogs do not create heroes', (WidgetTester tester) async { await tester.pumpWidget( - const CupertinoApp( - home: Placeholder(), + CupertinoApp( + home: const Placeholder(), ), ); diff --git a/packages/flutter/test/cupertino/page_test.dart b/packages/flutter/test/cupertino/page_test.dart index a6de3b22fc..5bf44ffc69 100644 --- a/packages/flutter/test/cupertino/page_test.dart +++ b/packages/flutter/test/cupertino/page_test.dart @@ -146,8 +146,8 @@ void main() { testWidgets('test iOS fullscreen dialog transition', (WidgetTester tester) async { await tester.pumpWidget( - const CupertinoApp( - home: Center(child: Text('Page 1')), + CupertinoApp( + home: const Center(child: Text('Page 1')), ), ); diff --git a/packages/flutter/test/cupertino/route_test.dart b/packages/flutter/test/cupertino/route_test.dart index de721c5ef1..3f74462db4 100644 --- a/packages/flutter/test/cupertino/route_test.dart +++ b/packages/flutter/test/cupertino/route_test.dart @@ -9,8 +9,8 @@ import 'package:flutter_test/flutter_test.dart'; void main() { testWidgets('Middle auto-populates with title', (WidgetTester tester) async { await tester.pumpWidget( - const CupertinoApp( - home: Placeholder(), + CupertinoApp( + home: const Placeholder(), ), ); @@ -39,8 +39,8 @@ void main() { testWidgets('Large title auto-populates with title', (WidgetTester tester) async { await tester.pumpWidget( - const CupertinoApp( - home: Placeholder(), + CupertinoApp( + home: const Placeholder(), ), ); @@ -104,8 +104,8 @@ void main() { testWidgets('Leading auto-populates with back button with previous title', (WidgetTester tester) async { await tester.pumpWidget( - const CupertinoApp( - home: Placeholder(), + CupertinoApp( + home: const Placeholder(), ), ); @@ -150,8 +150,8 @@ void main() { testWidgets('Previous title is correct on first transition frame', (WidgetTester tester) async { await tester.pumpWidget( - const CupertinoApp( - home: Placeholder(), + CupertinoApp( + home: const Placeholder(), ), ); @@ -193,8 +193,8 @@ void main() { testWidgets('Previous title stays up to date with changing routes', (WidgetTester tester) async { await tester.pumpWidget( - const CupertinoApp( - home: Placeholder(), + CupertinoApp( + home: const Placeholder(), ), ); diff --git a/packages/flutter/test/cupertino/scaffold_test.dart b/packages/flutter/test/cupertino/scaffold_test.dart index 6620e0018f..dbeca86934 100644 --- a/packages/flutter/test/cupertino/scaffold_test.dart +++ b/packages/flutter/test/cupertino/scaffold_test.dart @@ -11,8 +11,8 @@ import '../painting/mocks_for_image_cache.dart'; void main() { testWidgets('Contents are behind translucent bar', (WidgetTester tester) async { await tester.pumpWidget( - const CupertinoApp( - home: CupertinoPageScaffold( + CupertinoApp( + home: const CupertinoPageScaffold( // Default nav bar is translucent. navigationBar: CupertinoNavigationBar( middle: Text('Title'), @@ -276,8 +276,8 @@ void main() { testWidgets('Decorated with white background by default', (WidgetTester tester) async { await tester.pumpWidget( - const CupertinoApp( - home: CupertinoPageScaffold( + CupertinoApp( + home: const CupertinoPageScaffold( child: Center(), ), ), @@ -292,8 +292,8 @@ void main() { testWidgets('Overrides background color', (WidgetTester tester) async { await tester.pumpWidget( - const CupertinoApp( - home: CupertinoPageScaffold( + CupertinoApp( + home: const CupertinoPageScaffold( child: Center(), backgroundColor: Color(0xFF010203), ), diff --git a/packages/flutter/test/material/about_test.dart b/packages/flutter/test/material/about_test.dart index f71ba902a3..a4134a53d5 100644 --- a/packages/flutter/test/material/about_test.dart +++ b/packages/flutter/test/material/about_test.dart @@ -67,9 +67,9 @@ void main() { testWidgets('About box logic defaults to executable name for app name', (WidgetTester tester) async { await tester.pumpWidget( - const MaterialApp( + MaterialApp( title: 'flutter_tester', - home: Material(child: AboutListTile()), + home: const Material(child: AboutListTile()), ), ); expect(find.text('About flutter_tester'), findsOneWidget); @@ -89,8 +89,8 @@ void main() { }); await tester.pumpWidget( - const MaterialApp( - home: Center( + MaterialApp( + home: const Center( child: LicensePage(), ), ), diff --git a/packages/flutter/test/material/app_test.dart b/packages/flutter/test/material/app_test.dart index bbd05e7760..b42e86c847 100644 --- a/packages/flutter/test/material/app_test.dart +++ b/packages/flutter/test/material/app_test.dart @@ -28,9 +28,9 @@ class StateMarkerState extends State { void main() { testWidgets('Can nest apps', (WidgetTester tester) async { await tester.pumpWidget( - const MaterialApp( + MaterialApp( home: MaterialApp( - home: Text('Home sweet home'), + home: const Text('Home sweet home'), ), ), ); @@ -57,8 +57,8 @@ void main() { await tester.pumpWidget(FocusScope( autofocus: true, node: focusScopeNode, - child: const MaterialApp( - home: Text('Home'), + child: MaterialApp( + home: const Text('Home'), ), )); @@ -67,8 +67,8 @@ void main() { testWidgets('Can show grid without losing sync', (WidgetTester tester) async { await tester.pumpWidget( - const MaterialApp( - home: StateMarker(), + MaterialApp( + home: const StateMarker(), ), ); @@ -76,9 +76,9 @@ void main() { state1.marker = 'original'; await tester.pumpWidget( - const MaterialApp( + MaterialApp( debugShowMaterialGrid: true, - home: StateMarker(), + home: const StateMarker(), ), ); @@ -205,7 +205,7 @@ void main() { }); testWidgets('Cannot pop the initial route', (WidgetTester tester) async { - await tester.pumpWidget(const MaterialApp(home: Text('Home'))); + await tester.pumpWidget(MaterialApp(home: const Text('Home'))); expect(find.text('Home'), findsOneWidget); @@ -400,9 +400,9 @@ void main() { home: const Placeholder(), )); expect(key.currentState, isInstanceOf()); - await tester.pumpWidget(const MaterialApp( - color: Color(0xFF112233), - home: Placeholder(), + await tester.pumpWidget(MaterialApp( + color: const Color(0xFF112233), + home: const Placeholder(), )); expect(key.currentState, isNull); await tester.pumpWidget(MaterialApp( diff --git a/packages/flutter/test/material/bottom_app_bar_test.dart b/packages/flutter/test/material/bottom_app_bar_test.dart index 2d02016345..c783cc522b 100644 --- a/packages/flutter/test/material/bottom_app_bar_test.dart +++ b/packages/flutter/test/material/bottom_app_bar_test.dart @@ -9,8 +9,8 @@ import 'package:flutter/rendering.dart'; void main() { testWidgets('no overlap with floating action button', (WidgetTester tester) async { await tester.pumpWidget( - const MaterialApp( - home: Scaffold( + MaterialApp( + home: const Scaffold( floatingActionButton: FloatingActionButton( onPressed: null, ), @@ -95,8 +95,8 @@ void main() { // _BottomAppBarClipper will try an illegal downcast. testWidgets('toggle shape to null', (WidgetTester tester) async { await tester.pumpWidget( - const MaterialApp( - home: Scaffold( + MaterialApp( + home: const Scaffold( bottomNavigationBar: BottomAppBar( shape: RectangularNotch(), ), @@ -105,8 +105,8 @@ void main() { ); await tester.pumpWidget( - const MaterialApp( - home: Scaffold( + MaterialApp( + home: const Scaffold( bottomNavigationBar: BottomAppBar( shape: null, ), @@ -115,8 +115,8 @@ void main() { ); await tester.pumpWidget( - const MaterialApp( - home: Scaffold( + MaterialApp( + home: const Scaffold( bottomNavigationBar: BottomAppBar( shape: RectangularNotch(), ), @@ -127,8 +127,8 @@ void main() { testWidgets('no notch when notch param is null', (WidgetTester tester) async { await tester.pumpWidget( - const MaterialApp( - home: Scaffold( + MaterialApp( + home: const Scaffold( bottomNavigationBar: ShapeListener(BottomAppBar( shape: null, )), @@ -159,8 +159,8 @@ void main() { testWidgets('notch no margin', (WidgetTester tester) async { await tester.pumpWidget( - const MaterialApp( - home: Scaffold( + MaterialApp( + home: const Scaffold( bottomNavigationBar: ShapeListener( BottomAppBar( child: SizedBox(height: 100.0), @@ -211,8 +211,8 @@ void main() { testWidgets('notch with margin', (WidgetTester tester) async { await tester.pumpWidget( - const MaterialApp( - home: Scaffold( + MaterialApp( + home: const Scaffold( bottomNavigationBar: ShapeListener( BottomAppBar( child: SizedBox(height: 100.0), @@ -263,8 +263,8 @@ void main() { testWidgets('observes safe area', (WidgetTester tester) async { await tester.pumpWidget( - const MaterialApp( - home: MediaQuery( + MaterialApp( + home: const MediaQuery( data: MediaQueryData( padding: EdgeInsets.all(50.0), ), @@ -287,8 +287,8 @@ void main() { testWidgets('clipBehavior is propagated', (WidgetTester tester) async { await tester.pumpWidget( - const MaterialApp( - home: Scaffold( + MaterialApp( + home: const Scaffold( bottomNavigationBar: BottomAppBar( child: SizedBox(height: 100.0), @@ -303,8 +303,8 @@ void main() { expect(physicalShape.clipBehavior, Clip.none); await tester.pumpWidget( - const MaterialApp( - home: Scaffold( + MaterialApp( + home: const Scaffold( bottomNavigationBar: BottomAppBar( child: SizedBox(height: 100.0), diff --git a/packages/flutter/test/material/chip_test.dart b/packages/flutter/test/material/chip_test.dart index 43ff699f8d..082e8aed30 100644 --- a/packages/flutter/test/material/chip_test.dart +++ b/packages/flutter/test/material/chip_test.dart @@ -1181,8 +1181,8 @@ void main() { testWidgets('label only', (WidgetTester tester) async { final SemanticsTester semanticsTester = SemanticsTester(tester); - await tester.pumpWidget(const MaterialApp( - home: Material( + await tester.pumpWidget(MaterialApp( + home: const Material( child: RawChip( label: Text('test'), ), diff --git a/packages/flutter/test/material/dialog_test.dart b/packages/flutter/test/material/dialog_test.dart index 10ed47be7b..a275c4ae77 100644 --- a/packages/flutter/test/material/dialog_test.dart +++ b/packages/flutter/test/material/dialog_test.dart @@ -106,8 +106,8 @@ void main() { testWidgets('Simple dialog control test', (WidgetTester tester) async { await tester.pumpWidget( - const MaterialApp( - home: Material( + MaterialApp( + home: const Material( child: Center( child: RaisedButton( onPressed: null, @@ -149,8 +149,8 @@ void main() { testWidgets('Barrier dismissible', (WidgetTester tester) async { await tester.pumpWidget( - const MaterialApp( - home: Material( + MaterialApp( + home: const Material( child: Center( child: RaisedButton( onPressed: null, @@ -212,8 +212,8 @@ void main() { final SemanticsTester semantics = SemanticsTester(tester); const String buttonText = 'A button covered by dialog overlay'; await tester.pumpWidget( - const MaterialApp( - home: Material( + MaterialApp( + home: const Material( child: Center( child: RaisedButton( onPressed: null, diff --git a/packages/flutter/test/material/drawer_test.dart b/packages/flutter/test/material/drawer_test.dart index 9a542eb971..ff29764e09 100644 --- a/packages/flutter/test/material/drawer_test.dart +++ b/packages/flutter/test/material/drawer_test.dart @@ -61,8 +61,8 @@ void main() { final SemanticsTester semantics = SemanticsTester(tester); debugDefaultTargetPlatformOverride = TargetPlatform.iOS; await tester.pumpWidget( - const MaterialApp( - home: Scaffold( + MaterialApp( + home: const Scaffold( drawer: Drawer() ), ), @@ -86,8 +86,8 @@ void main() { testWidgets('Drawer dismiss barrier has no label on Android', (WidgetTester tester) async { final SemanticsTester semantics = SemanticsTester(tester); await tester.pumpWidget( - const MaterialApp( - home: Scaffold( + MaterialApp( + home: const Scaffold( drawer: Drawer() ), ), diff --git a/packages/flutter/test/material/floating_action_button_test.dart b/packages/flutter/test/material/floating_action_button_test.dart index 526419c632..63bf4ed616 100644 --- a/packages/flutter/test/material/floating_action_button_test.dart +++ b/packages/flutter/test/material/floating_action_button_test.dart @@ -36,8 +36,8 @@ void main() { testWidgets('Floating Action Button tooltip', (WidgetTester tester) async { await tester.pumpWidget( - const MaterialApp( - home: Scaffold( + MaterialApp( + home: const Scaffold( floatingActionButton: FloatingActionButton( onPressed: null, tooltip: 'Add', @@ -54,8 +54,8 @@ void main() { // Regression test for: https://github.com/flutter/flutter/pull/21084 testWidgets('Floating Action Button tooltip (long press button edge)', (WidgetTester tester) async { await tester.pumpWidget( - const MaterialApp( - home: Scaffold( + MaterialApp( + home: const Scaffold( floatingActionButton: FloatingActionButton( onPressed: null, tooltip: 'Add', @@ -75,8 +75,8 @@ void main() { // Regression test for: https://github.com/flutter/flutter/pull/21084 testWidgets('Floating Action Button tooltip (long press button edge - no child)', (WidgetTester tester) async { await tester.pumpWidget( - const MaterialApp( - home: Scaffold( + MaterialApp( + home: const Scaffold( floatingActionButton: FloatingActionButton( onPressed: null, tooltip: 'Add', @@ -94,8 +94,8 @@ void main() { testWidgets('Floating Action Button tooltip (no child)', (WidgetTester tester) async { await tester.pumpWidget( - const MaterialApp( - home: Scaffold( + MaterialApp( + home: const Scaffold( floatingActionButton: FloatingActionButton( onPressed: null, tooltip: 'Add', @@ -150,8 +150,8 @@ void main() { testWidgets('FloatingActionButton.isExtended', (WidgetTester tester) async { await tester.pumpWidget( - const MaterialApp( - home: Scaffold( + MaterialApp( + home: const Scaffold( floatingActionButton: FloatingActionButton(onPressed: null), ), ), diff --git a/packages/flutter/test/material/persistent_bottom_sheet_test.dart b/packages/flutter/test/material/persistent_bottom_sheet_test.dart index c880aeeca1..9b752168c3 100644 --- a/packages/flutter/test/material/persistent_bottom_sheet_test.dart +++ b/packages/flutter/test/material/persistent_bottom_sheet_test.dart @@ -180,8 +180,8 @@ void main() { // Remove the persistent bottomSheet await tester.pumpWidget( - const MaterialApp( - home: Scaffold( + MaterialApp( + home: const Scaffold( bottomSheet: null, body: Placeholder(), ), diff --git a/packages/flutter/test/material/scaffold_test.dart b/packages/flutter/test/material/scaffold_test.dart index 4c23e53b8b..2e807d707e 100644 --- a/packages/flutter/test/material/scaffold_test.dart +++ b/packages/flutter/test/material/scaffold_test.dart @@ -124,7 +124,7 @@ void main() { }); testWidgets('Floating action entrance/exit animation', (WidgetTester tester) async { - await tester.pumpWidget(const MaterialApp(home: Scaffold( + await tester.pumpWidget(MaterialApp(home: const Scaffold( floatingActionButton: FloatingActionButton( key: Key('one'), onPressed: null, @@ -134,7 +134,7 @@ void main() { expect(tester.binding.transientCallbackCount, 0); - await tester.pumpWidget(const MaterialApp(home: Scaffold( + await tester.pumpWidget(MaterialApp(home: const Scaffold( floatingActionButton: FloatingActionButton( key: Key('two'), onPressed: null, @@ -146,11 +146,11 @@ void main() { await tester.pumpWidget(Container()); expect(tester.binding.transientCallbackCount, 0); - await tester.pumpWidget(const MaterialApp(home: Scaffold())); + await tester.pumpWidget(MaterialApp(home: const Scaffold())); expect(tester.binding.transientCallbackCount, 0); - await tester.pumpWidget(const MaterialApp(home: Scaffold( + await tester.pumpWidget(MaterialApp(home: const Scaffold( floatingActionButton: FloatingActionButton( key: Key('one'), onPressed: null, @@ -569,7 +569,7 @@ void main() { const String drawerLabel = 'I am the reason for this test'; final SemanticsTester semantics = SemanticsTester(tester); - await tester.pumpWidget(const MaterialApp(home: Scaffold( + await tester.pumpWidget(MaterialApp(home: const Scaffold( body: Text(bodyLabel), persistentFooterButtons: [Text(persistentFooterButtonLabel)], bottomNavigationBar: Text(bottomNavigationBarLabel), @@ -970,7 +970,7 @@ void main() { const String endDrawerLabel = 'I am the label on end side'; final SemanticsTester semantics = SemanticsTester(tester); - await tester.pumpWidget(const MaterialApp(home: Scaffold( + await tester.pumpWidget(MaterialApp(home: const Scaffold( body: Text(bodyLabel), drawer: Drawer(child: Text(drawerLabel)), endDrawer: Drawer(child: Text(endDrawerLabel)), diff --git a/packages/flutter/test/material/text_field_focus_test.dart b/packages/flutter/test/material/text_field_focus_test.dart index a21594723c..4bb79d6c4c 100644 --- a/packages/flutter/test/material/text_field_focus_test.dart +++ b/packages/flutter/test/material/text_field_focus_test.dart @@ -37,8 +37,8 @@ void main() { expect(tester.testTextInput.isVisible, isFalse); await tester.pumpWidget( - const MaterialApp( - home: Material( + MaterialApp( + home: const Material( child: Center( child: TextField( autofocus: true, @@ -59,8 +59,8 @@ void main() { expect(tester.testTextInput.isVisible, isFalse); await tester.pumpWidget( - const MaterialApp( - home: Material( + MaterialApp( + home: const Material( child: Center( child: TextField(), ), @@ -93,8 +93,8 @@ void main() { expect(tester.testTextInput.isVisible, isFalse); await tester.pumpWidget( - const MaterialApp( - home: Material( + MaterialApp( + home: const Material( child: Center( child: TextField( autofocus: true, @@ -211,8 +211,8 @@ void main() { // Regression test for https://github.com/flutter/flutter/issues/16880 await tester.pumpWidget( - const MaterialApp( - home: Material( + MaterialApp( + home: const Material( child: Center( child: TextField( decoration: null diff --git a/packages/flutter/test/material/text_field_helper_text_test.dart b/packages/flutter/test/material/text_field_helper_text_test.dart index f4d68b3e0b..ff4d5cd33f 100644 --- a/packages/flutter/test/material/text_field_helper_text_test.dart +++ b/packages/flutter/test/material/text_field_helper_text_test.dart @@ -7,11 +7,11 @@ import 'package:flutter_test/flutter_test.dart'; void main() { testWidgets('TextField works correctly when changing helperText', (WidgetTester tester) async { - await tester.pumpWidget(const MaterialApp(home: Material(child: TextField(decoration: InputDecoration(helperText: 'Awesome'))))); + await tester.pumpWidget(MaterialApp(home: const Material(child: TextField(decoration: InputDecoration(helperText: 'Awesome'))))); expect(find.text('Awesome'), findsNWidgets(1)); await tester.pump(const Duration(milliseconds: 100)); expect(find.text('Awesome'), findsNWidgets(1)); - await tester.pumpWidget(const MaterialApp(home: Material(child: TextField(decoration: InputDecoration(errorText: 'Awesome'))))); + await tester.pumpWidget(MaterialApp(home: const Material(child: TextField(decoration: InputDecoration(errorText: 'Awesome'))))); expect(find.text('Awesome'), findsNWidgets(2)); }); } diff --git a/packages/flutter/test/material/text_field_test.dart b/packages/flutter/test/material/text_field_test.dart index 46979c5fb4..5a1d8d6d3a 100644 --- a/packages/flutter/test/material/text_field_test.dart +++ b/packages/flutter/test/material/text_field_test.dart @@ -1721,8 +1721,8 @@ void main() { }); testWidgets('setting maxLength shows counter', (WidgetTester tester) async { - await tester.pumpWidget(const MaterialApp( - home: Material( + await tester.pumpWidget(MaterialApp( + home: const Material( child: DefaultTextStyle( style: TextStyle(fontFamily: 'Ahem', fontSize: 10.0), child: Center( @@ -1746,8 +1746,8 @@ void main() { final SemanticsTester semantics = SemanticsTester(tester); await tester.pumpWidget( - const MaterialApp( - home: Material( + MaterialApp( + home: const Material( child: DefaultTextStyle( style: TextStyle(fontFamily: 'Ahem', fontSize: 10.0), child: Center( diff --git a/packages/flutter/test/material/tooltip_test.dart b/packages/flutter/test/material/tooltip_test.dart index b1bea3ad9e..8c117f81d7 100644 --- a/packages/flutter/test/material/tooltip_test.dart +++ b/packages/flutter/test/material/tooltip_test.dart @@ -610,8 +610,8 @@ void main() { final SemanticsTester semantics = SemanticsTester(tester); await tester.pumpWidget( - const MaterialApp( - home: Center( + MaterialApp( + home: const Center( child: Tooltip( message: 'Foo', child: Text('Bar'), @@ -645,8 +645,8 @@ void main() { final SemanticsTester semantics = SemanticsTester(tester); await tester.pumpWidget( - const MaterialApp( - home: Center( + MaterialApp( + home: const Center( child: Tooltip( message: 'Foo', child: Text('Bar'), diff --git a/packages/flutter/test/widgets/banner_test.dart b/packages/flutter/test/widgets/banner_test.dart index 58eb350b6e..c11a6e09b6 100644 --- a/packages/flutter/test/widgets/banner_test.dart +++ b/packages/flutter/test/widgets/banner_test.dart @@ -269,7 +269,7 @@ void main() { testWidgets('Banner widget in MaterialApp', (WidgetTester tester) async { debugDisableShadows = false; - await tester.pumpWidget(const MaterialApp(home: Placeholder())); + await tester.pumpWidget(MaterialApp(home: const Placeholder())); expect(find.byType(CheckedModeBanner), paints ..save() ..translate(x: 800.0, y: 0.0) diff --git a/packages/flutter/test/widgets/reassemble_test.dart b/packages/flutter/test/widgets/reassemble_test.dart index adc74baf98..c107812217 100644 --- a/packages/flutter/test/widgets/reassemble_test.dart +++ b/packages/flutter/test/widgets/reassemble_test.dart @@ -7,8 +7,8 @@ import 'package:flutter_test/flutter_test.dart'; void main() { testWidgets('reassemble does not crash', (WidgetTester tester) async { - await tester.pumpWidget(const MaterialApp( - home: Text('Hello World') + await tester.pumpWidget(MaterialApp( + home: const Text('Hello World') )); await tester.pump(); tester.binding.reassembleApplication(); diff --git a/packages/flutter_test/test/test_text_input_test.dart b/packages/flutter_test/test/test_text_input_test.dart index 2bed6132df..2c89f5669c 100644 --- a/packages/flutter_test/test/test_text_input_test.dart +++ b/packages/flutter_test/test/test_text_input_test.dart @@ -10,8 +10,8 @@ void main() { testWidgets('receiveAction() forwards exception when exception occurs during action processing', (WidgetTester tester) async { // Setup a widget that can receive focus so that we can open the keyboard. - const Widget widget = MaterialApp( - home: Material( + final Widget widget = MaterialApp( + home: const Material( child: TextField(), ), ); diff --git a/packages/flutter_test/test/widget_tester_test.dart b/packages/flutter_test/test/widget_tester_test.dart index ecb5ba0502..c26094f121 100644 --- a/packages/flutter_test/test/widget_tester_test.dart +++ b/packages/flutter_test/test/widget_tester_test.dart @@ -533,8 +533,8 @@ void main() { group('getSemanticsData', () { testWidgets('throws when there are no semantics', (WidgetTester tester) async { await tester.pumpWidget( - const MaterialApp( - home: Scaffold( + MaterialApp( + home: const Scaffold( body: Text('hello'), ), ),