Fixed Typography null factory constructor (#24932)

diff --git a/packages/flutter/lib/src/material/tabs.dart b/packages/flutter/lib/src/material/tabs.dart
index ccc59c2..e2c9a53 100644
--- a/packages/flutter/lib/src/material/tabs.dart
+++ b/packages/flutter/lib/src/material/tabs.dart
@@ -1183,10 +1183,9 @@
     if (notification is ScrollUpdateNotification && !_controller.indexIsChanging) {
       if ((_pageController.page - _controller.index).abs() > 1.0) {
         _controller.index = _pageController.page.floor();
-        _currentIndex = _controller.index;
+        _currentIndex =_controller.index;
       }
-      if (_controller.length > 1)
-        _controller.offset = (_pageController.page - _controller.index).clamp(-1.0, 1.0);
+      _controller.offset = (_pageController.page - _controller.index).clamp(-1.0, 1.0);
     } else if (notification is ScrollEndNotification) {
       _controller.index = _pageController.page.round();
       _currentIndex = _controller.index;
diff --git a/packages/flutter/lib/src/material/typography.dart b/packages/flutter/lib/src/material/typography.dart
index 1338ba1..8d1fbcf 100644
--- a/packages/flutter/lib/src/material/typography.dart
+++ b/packages/flutter/lib/src/material/typography.dart
@@ -87,20 +87,22 @@
 class Typography extends Diagnosticable {
   /// Creates a typography instance.
   ///
-  /// If [platform] is specified, the default values for [black] and [white]
-  /// are [blackCupertino] and [whiteCupertino] respectively. Otherwise
-  /// they are [blackMountainView] and [whiteMoutainView].
+  /// If [platform] is [TargetPlatform.iOS], the default values for [black] and
+  /// [white] are [blackCupertino] and [whiteCupertino] respectively. Otherwise
+  /// they are [blackMountainView] and [whiteMoutainView]. If [platform] is
+  /// null then both [black] and [white] must be specified.
   ///
   /// The default values for [englishLike], [dense], and [tall] are
   /// [englishLike2014], [dense2014], and [tall2014].
   factory Typography({
-    TargetPlatform platform,
+    TargetPlatform platform = TargetPlatform.android,
     TextTheme black,
     TextTheme white,
     TextTheme englishLike,
     TextTheme dense,
     TextTheme tall,
   }) {
+    assert(platform != null || (black != null && white != null));
     switch (platform) {
       case TargetPlatform.iOS:
         black ??= blackCupertino;
diff --git a/packages/flutter/test/material/outline_button_test.dart b/packages/flutter/test/material/outline_button_test.dart
index cf47182..c56fcf2 100644
--- a/packages/flutter/test/material/outline_button_test.dart
+++ b/packages/flutter/test/material/outline_button_test.dart
@@ -271,20 +271,22 @@
     expect(tester.getSize(find.byType(Text)).height, equals(42.0));
   });
 
-  testWidgets('OutlineButton implements debugFillDescription', (WidgetTester tester) async {
+  testWidgets('OutlineButton implements debugFillProperties', (WidgetTester tester) async {
     final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
     OutlineButton(
-        onPressed: () {},
-        textColor: const Color(0xFF00FF00),
-        disabledTextColor: const Color(0xFFFF0000),
-        color: const Color(0xFF000000),
-        highlightColor: const Color(0xFF1565C0),
-        splashColor: const Color(0xFF9E9E9E),
-        child: const Text('Hello'),
+      onPressed: () {},
+      textColor: const Color(0xFF00FF00),
+      disabledTextColor: const Color(0xFFFF0000),
+      color: const Color(0xFF000000),
+      highlightColor: const Color(0xFF1565C0),
+      splashColor: const Color(0xFF9E9E9E),
+      child: const Text('Hello'),
     ).debugFillProperties(builder);
+
     final List<String> description = builder.properties
-        .where((DiagnosticsNode n) => !n.isFiltered(DiagnosticLevel.info))
-        .map((DiagnosticsNode n) => n.toString()).toList();
+      .where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
+      .map((DiagnosticsNode node) => node.toString()).toList();
+
     expect(description, <String>[
       'textColor: Color(0xff00ff00)',
       'disabledTextColor: Color(0xffff0000)',
diff --git a/packages/flutter/test/material/tabs_test.dart b/packages/flutter/test/material/tabs_test.dart
index 9e4a8c3..69742c5 100644
--- a/packages/flutter/test/material/tabs_test.dart
+++ b/packages/flutter/test/material/tabs_test.dart
@@ -1976,55 +1976,4 @@
     expect(find.text(AlwaysKeepAliveWidget.text, skipOffstage: false), findsOneWidget);
     expect(find.text('4'), findsOneWidget);
   });
-
-  testWidgets('Removing the last tab', (WidgetTester tester) async {
-    // This is a regression test for https://github.com/flutter/flutter/issues/24424
-
-    final List<Tab> tabs = <Tab>[const Tab(text: 'LEFT'), const Tab(text: 'RIGHT')];
-
-    Widget buildFrame(TabController controller) {
-      return boilerplate(
-        child: Container(
-          alignment: Alignment.topLeft,
-          child: Column(
-            children: <Widget>[
-              TabBar(controller: controller, tabs: tabs),
-              Expanded(child: TabBarView(controller: controller, children: tabs)),
-            ]
-          ),
-        ),
-      );
-    }
-
-    final TabController controller1 = TabController(
-      vsync: const TestVSync(),
-      length: 2,
-      initialIndex: 0,
-    );
-
-    await tester.pumpWidget(buildFrame(controller1));
-    expect(controller1.index, 0);
-
-    await tester.tap(find.text('RIGHT'));
-    expect(controller1.index, 1);
-    expect(controller1.indexIsChanging, true);
-
-    // At this point the change selected tab animation hasn't completed.
-    // When the controller is replaced the TabBarView will see one last
-    // scroll notification. Since there's only one tab left, it can be
-    // ignored.
-
-    final TabController controller2 = TabController(
-      vsync: const TestVSync(),
-      length: 1,
-      initialIndex: 0,
-    );
-
-    tabs.removeAt(1);
-    await tester.pumpWidget(buildFrame(controller2));
-    await tester.pumpAndSettle();
-    expect(controller1.indexIsChanging, false);
-    expect(controller2.index, 0);
-
-  });
 }
diff --git a/packages/flutter/test/material/typography_test.dart b/packages/flutter/test/material/typography_test.dart
index 8109452..0e3aac0 100644
--- a/packages/flutter/test/material/typography_test.dart
+++ b/packages/flutter/test/material/typography_test.dart
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import 'package:flutter/foundation.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_test/flutter_test.dart';
 
@@ -47,4 +48,22 @@
       expect(textTheme.overline, isTextFont);
     }
   });
+
+  testWidgets('Typography implements debugFillProperties', (WidgetTester tester) async {
+    final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
+    Typography(
+      platform: TargetPlatform.android,
+      black: Typography.blackCupertino,
+      white: Typography.whiteCupertino,
+      englishLike: Typography.englishLike2018,
+      dense: Typography.dense2018,
+      tall: Typography.tall2018,
+    ).debugFillProperties(builder);
+
+    final List<String> nonDefaultPropertyNames = builder.properties
+      .where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
+      .map((DiagnosticsNode node) => node.name).toList();
+
+    expect(nonDefaultPropertyNames, <String>['black', 'white', 'englishLike', 'dense', 'tall']);
+  });
 }