diff --git a/packages/flutter/lib/src/material/app.dart b/packages/flutter/lib/src/material/app.dart index 795a8d5cb8..f75491f8ec 100644 --- a/packages/flutter/lib/src/material/app.dart +++ b/packages/flutter/lib/src/material/app.dart @@ -84,7 +84,7 @@ class MaterialApp extends StatefulWidget { /// The boolean arguments, [routes], and [navigatorObservers], must not be null. MaterialApp({ // can't be const because the asserts use methods on Map :-( Key key, - this.title, + this.title: '', this.color, this.theme, this.home, @@ -103,7 +103,8 @@ class MaterialApp extends StatefulWidget { this.checkerboardOffscreenLayers: false, this.showSemanticsDebugger: false, this.debugShowCheckedModeBanner: true - }) : assert(routes != null), + }) : assert(title != null), + assert(routes != null), assert(navigatorObservers != null), assert(debugShowMaterialGrid != null), assert(showPerformanceOverlay != null), diff --git a/packages/flutter/lib/src/widgets/app.dart b/packages/flutter/lib/src/widgets/app.dart index d528674d47..f5b3885bc8 100644 --- a/packages/flutter/lib/src/widgets/app.dart +++ b/packages/flutter/lib/src/widgets/app.dart @@ -70,7 +70,7 @@ class WidgetsApp extends StatefulWidget { Key key, @required this.onGenerateRoute, this.onUnknownRoute, - this.title, + this.title: '', this.textStyle, @required this.color, this.navigatorObservers: const [], @@ -86,7 +86,8 @@ class WidgetsApp extends StatefulWidget { this.debugShowWidgetInspector: false, this.debugShowCheckedModeBanner: true, this.inspectorSelectButtonBuilder, - }) : assert(onGenerateRoute != null), + }) : assert(title != null), + assert(onGenerateRoute != null), assert(color != null), assert(navigatorObservers != null), assert(supportedLocales != null && supportedLocales.isNotEmpty), diff --git a/packages/flutter/lib/src/widgets/title.dart b/packages/flutter/lib/src/widgets/title.dart index 8634a3194b..3ddecba524 100644 --- a/packages/flutter/lib/src/widgets/title.dart +++ b/packages/flutter/lib/src/widgets/title.dart @@ -11,18 +11,26 @@ import 'framework.dart'; /// A widget that describes this app in the operating system. class Title extends StatelessWidget { /// Creates a widget that describes this app to the operating system. + /// + /// [title] will default to the empty string if not supplied. + /// [color] must be an opaque color (i.e. color.alpha must be 255 (0xFF)). + /// [color] and [child] are required arguments. Title({ Key key, - this.title, - this.color, + this.title: '', + @required this.color, @required this.child, - }) : assert(color == null || color.alpha == 0xFF), + }) : assert(title != null), + assert(color != null && color.alpha == 0xFF), super(key: key); /// A one-line description of this app for use in the window manager. + /// Must not be null. final String title; - /// A color that the window manager should use to identify this app. + /// A color that the window manager should use to identify this app. Must be + /// an opaque color (i.e. color.alpha must be 255 (0xFF)), and must not be + /// null. final Color color; /// The widget below this widget in the tree. @@ -42,7 +50,7 @@ class Title extends StatelessWidget { @override void debugFillProperties(DiagnosticPropertiesBuilder description) { super.debugFillProperties(description); - description.add(new StringProperty('title', title, defaultValue: null)); + description.add(new StringProperty('title', title, defaultValue: '')); description.add(new DiagnosticsProperty('color', color, defaultValue: null)); } } diff --git a/packages/flutter/test/widgets/title_test.dart b/packages/flutter/test/widgets/title_test.dart index fe5e69a079..e9ca5c1fb2 100644 --- a/packages/flutter/test/widgets/title_test.dart +++ b/packages/flutter/test/widgets/title_test.dart @@ -4,6 +4,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter/widgets.dart'; +import 'package:flutter/services.dart'; void main() { testWidgets('toString control test', (WidgetTester tester) async { @@ -14,4 +15,52 @@ void main() { ); expect(widget.toString, isNot(throwsException)); }); + + testWidgets('should handle having no title', (WidgetTester tester) async { + final Title widget = new Title( + child: new Container(), + color: const Color(0xFF00FF00), + ); + expect(widget.toString, isNot(throwsException)); + expect(widget.title, equals('')); + expect(widget.color, equals(const Color(0xFF00FF00))); + }); + + testWidgets('should not allow null title or color', (WidgetTester tester) async { + expect(() => new Title( + title: null, + color: const Color(0xFF00FF00), + child: new Container(), + ), throwsAssertionError); + expect(() => new Title( + color: null, + child: new Container(), + ), throwsAssertionError); + }); + + testWidgets('should not allow non-opaque color', (WidgetTester tester) async { + expect(() => new Title( + color: const Color(0), + child: new Container(), + ), throwsAssertionError); + }); + + testWidgets('should not pass "null" to setApplicationSwitcherDescription', + (WidgetTester tester) async { + final List log = []; + + SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async { + log.add(methodCall); + }); + + await tester.pumpWidget(new Title( + child: new Container(), + color: const Color(0xFF00FF00), + )); + + expect(log, equals([new MethodCall( + 'SystemChrome.setApplicationSwitcherDescription', + {'label': '', 'primaryColor': 4278255360}, + )])); + }); }