Remove Material import from navigator replacement tests (#186674)

Part of flutter/flutter#177412
Refs flutter/flutter#177028

This removes the package:flutter/material.dart dependency from the
navigator replacement widget tests. The tests now use the widgets-only
TestWidgetsApp helper with an explicit PageRouteBuilder for transition
coverage and an explicit HeroController for the Hero assertions.

Validation:
- dart analyze
packages/flutter/test/widgets/navigator_replacement_test.dart
- ./bin/flutter test
packages/flutter/test/widgets/navigator_replacement_test.dart

---------

Co-authored-by: Victor Sanni <victorsanniay@gmail.com>
diff --git a/dev/bots/check_tests_cross_imports.dart b/dev/bots/check_tests_cross_imports.dart
index cbc3f2c..3d86720 100644
--- a/dev/bots/check_tests_cross_imports.dart
+++ b/dev/bots/check_tests_cross_imports.dart
@@ -111,7 +111,6 @@
     'packages/flutter/test/widgets/page_transitions_test.dart',
     'packages/flutter/test/widgets/routes_test.dart',
     'packages/flutter/test/widgets/app_test.dart',
-    'packages/flutter/test/widgets/navigator_replacement_test.dart',
     'packages/flutter/test/widgets/implicit_animations_test.dart',
     'packages/flutter/test/widgets/routes_transition_test.dart',
     'packages/flutter/test/widgets/editable_text_test.dart',
diff --git a/packages/flutter/test/widgets/navigator_replacement_test.dart b/packages/flutter/test/widgets/navigator_replacement_test.dart
index b7771bf..95912c0 100644
--- a/packages/flutter/test/widgets/navigator_replacement_test.dart
+++ b/packages/flutter/test/widgets/navigator_replacement_test.dart
@@ -2,19 +2,20 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
 import 'package:flutter_test/flutter_test.dart';
 
 import 'observer_tester.dart';
+import 'widgets_app_tester.dart';
 
 void main() {
   testWidgets('Back during pushReplacement', (WidgetTester tester) async {
     await tester.pumpWidget(
-      MaterialApp(
-        home: const Material(child: Text('home')),
+      _buildApp(
+        home: const Text('home'),
         routes: <String, WidgetBuilder>{
-          '/a': (BuildContext context) => const Material(child: Text('a')),
-          '/b': (BuildContext context) => const Material(child: Text('b')),
+          '/a': (BuildContext context) => const Text('a'),
+          '/b': (BuildContext context) => const Text('b'),
         },
       ),
     );
@@ -46,11 +47,11 @@
   group('pushAndRemoveUntil', () {
     testWidgets('notifies appropriately', (WidgetTester tester) async {
       final observer = TestObserver();
-      final Widget myApp = MaterialApp(
-        home: const Material(child: Text('home')),
+      final Widget myApp = _buildApp(
+        home: const Text('home'),
         routes: <String, WidgetBuilder>{
-          '/a': (BuildContext context) => const Material(child: Text('a')),
-          '/b': (BuildContext context) => const Material(child: Text('b')),
+          '/a': (BuildContext context) => const Text('a'),
+          '/b': (BuildContext context) => const Text('b'),
         },
         navigatorObservers: <NavigatorObserver>[observer],
       );
@@ -122,11 +123,11 @@
     });
 
     testWidgets('triggers page transition animation for pushed route', (WidgetTester tester) async {
-      final Widget myApp = MaterialApp(
-        home: const Material(child: Text('home')),
+      final Widget myApp = _buildApp(
+        home: const Text('home'),
         routes: <String, WidgetBuilder>{
-          '/a': (BuildContext context) => const Material(child: Text('a')),
-          '/b': (BuildContext context) => const Material(child: Text('b')),
+          '/a': (BuildContext context) => const Text('a'),
+          '/b': (BuildContext context) => const Text('b'),
         },
       );
 
@@ -154,18 +155,14 @@
       'Hero transition triggers when preceding route contains hero, and predicate route does not',
       (WidgetTester tester) async {
         const kHeroTag = 'hero';
-        final Widget myApp = MaterialApp(
+        final Widget myApp = _buildApp(
           initialRoute: '/',
           routes: <String, WidgetBuilder>{
-            '/': (BuildContext context) => const Material(child: Text('home')),
-            '/a': (BuildContext context) => const Material(
-              child: Hero(tag: kHeroTag, child: Text('a')),
-            ),
-            '/b': (BuildContext context) => const Material(
-              child: Padding(
-                padding: EdgeInsets.all(100.0),
-                child: Hero(tag: kHeroTag, child: Text('b')),
-              ),
+            '/': (BuildContext context) => const Text('home'),
+            '/a': (BuildContext context) => const Hero(tag: kHeroTag, child: Text('a')),
+            '/b': (BuildContext context) => const Padding(
+              padding: EdgeInsets.all(100.0),
+              child: Hero(tag: kHeroTag, child: Text('b')),
             ),
           },
         );
@@ -200,25 +197,14 @@
       'Hero transition does not trigger when preceding route does not contain hero, but predicate route does',
       (WidgetTester tester) async {
         const kHeroTag = 'hero';
-        final Widget myApp = MaterialApp(
-          theme: ThemeData(
-            pageTransitionsTheme: const PageTransitionsTheme(
-              builders: <TargetPlatform, PageTransitionsBuilder>{
-                TargetPlatform.android: FadeUpwardsPageTransitionsBuilder(),
-              },
-            ),
-          ),
+        final Widget myApp = _buildApp(
           initialRoute: '/',
           routes: <String, WidgetBuilder>{
-            '/': (BuildContext context) => const Material(
-              child: Hero(tag: kHeroTag, child: Text('home')),
-            ),
-            '/a': (BuildContext context) => const Material(child: Text('a')),
-            '/b': (BuildContext context) => const Material(
-              child: Padding(
-                padding: EdgeInsets.all(100.0),
-                child: Hero(tag: kHeroTag, child: Text('b')),
-              ),
+            '/': (BuildContext context) => const Hero(tag: kHeroTag, child: Text('home')),
+            '/a': (BuildContext context) => const Text('a'),
+            '/b': (BuildContext context) => const Padding(
+              padding: EdgeInsets.all(100.0),
+              child: Hero(tag: kHeroTag, child: Text('b')),
             ),
           },
         );
@@ -243,3 +229,44 @@
     );
   });
 }
+
+/// Builds a [TestWidgetsApp] for navigator replacement tests.
+Widget _buildApp({
+  Widget? home,
+  String? initialRoute,
+  Map<String, WidgetBuilder> routes = const <String, WidgetBuilder>{},
+  List<NavigatorObserver> navigatorObservers = const <NavigatorObserver>[],
+}) {
+  return TestWidgetsApp(
+    home: home,
+    initialRoute: initialRoute,
+    routes: routes,
+    pageRouteBuilder: _pageRouteBuilder,
+    navigatorObservers: <NavigatorObserver>[HeroController(), ...navigatorObservers],
+    textStyle: const TextStyle(color: Color(0xFF000000), fontSize: 14.0),
+  );
+}
+
+/// Creates a page route with the transition used by the replacement tests.
+PageRoute<T> _pageRouteBuilder<T>(RouteSettings settings, WidgetBuilder builder) {
+  return PageRouteBuilder<T>(
+    settings: settings,
+    pageBuilder:
+        (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) =>
+            builder(context),
+    transitionsBuilder:
+        (
+          BuildContext context,
+          Animation<double> animation,
+          Animation<double> secondaryAnimation,
+          Widget child,
+        ) {
+          return SlideTransition(
+            position: animation.drive(
+              Tween<Offset>(begin: const Offset(0.0, 0.25), end: Offset.zero),
+            ),
+            child: child,
+          );
+        },
+  );
+}