Cover more tests with leak tracking. (#132806)

This PR replaces some `testWidgets` with `testWidgestsWithLeakTracking`.
This commit is contained in:
Polina Cherkasova 2023-08-22 08:50:48 -07:00 committed by GitHub
parent c00bdc832d
commit 4e6da2dcc7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 255 additions and 251 deletions

File diff suppressed because it is too large Load Diff

View File

@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() { void main() {
const AppBarTheme appBarTheme = AppBarTheme( const AppBarTheme appBarTheme = AppBarTheme(
@ -42,7 +43,7 @@ void main() {
expect(identical(AppBarTheme.lerp(data, data, 0.5), data), true); expect(identical(AppBarTheme.lerp(data, data, 0.5), data), true);
}); });
testWidgets('Material2 - Passing no AppBarTheme returns defaults', (WidgetTester tester) async { testWidgetsWithLeakTracking('Material2 - Passing no AppBarTheme returns defaults', (WidgetTester tester) async {
final ThemeData theme = ThemeData(useMaterial3: false); final ThemeData theme = ThemeData(useMaterial3: false);
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
@ -77,7 +78,7 @@ void main() {
expect(tester.getSize(find.byType(AppBar)).width, 800); expect(tester.getSize(find.byType(AppBar)).width, 800);
}); });
testWidgets('Material3 - Passing no AppBarTheme returns defaults', (WidgetTester tester) async { testWidgetsWithLeakTracking('Material3 - Passing no AppBarTheme returns defaults', (WidgetTester tester) async {
final ThemeData theme = ThemeData(useMaterial3: true); final ThemeData theme = ThemeData(useMaterial3: true);
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
@ -117,7 +118,7 @@ void main() {
expect(tester.getSize(find.byType(AppBar)).width, 800); expect(tester.getSize(find.byType(AppBar)).width, 800);
}); });
testWidgets('AppBar uses values from AppBarTheme', (WidgetTester tester) async { testWidgetsWithLeakTracking('AppBar uses values from AppBarTheme', (WidgetTester tester) async {
final AppBarTheme appBarTheme = _appBarTheme(); final AppBarTheme appBarTheme = _appBarTheme();
await tester.pumpWidget( await tester.pumpWidget(
@ -154,7 +155,7 @@ void main() {
expect(tester.getSize(find.byType(AppBar)).width, 800); expect(tester.getSize(find.byType(AppBar)).width, 800);
}); });
testWidgets('AppBar widget properties take priority over theme', (WidgetTester tester) async { testWidgetsWithLeakTracking('AppBar widget properties take priority over theme', (WidgetTester tester) async {
const Brightness brightness = Brightness.dark; const Brightness brightness = Brightness.dark;
const SystemUiOverlayStyle systemOverlayStyle = SystemUiOverlayStyle.light; const SystemUiOverlayStyle systemOverlayStyle = SystemUiOverlayStyle.light;
const Color color = Colors.orange; const Color color = Colors.orange;
@ -210,7 +211,7 @@ void main() {
expect(text.style, toolbarTextStyle); expect(text.style, toolbarTextStyle);
}); });
testWidgets('AppBar icon color takes priority over everything', (WidgetTester tester) async { testWidgetsWithLeakTracking('AppBar icon color takes priority over everything', (WidgetTester tester) async {
const Color color = Colors.lime; const Color color = Colors.lime;
const IconThemeData iconThemeData = IconThemeData(color: Colors.green); const IconThemeData iconThemeData = IconThemeData(color: Colors.green);
const IconThemeData actionsIconThemeData = IconThemeData(color: Colors.lightBlue); const IconThemeData actionsIconThemeData = IconThemeData(color: Colors.lightBlue);
@ -230,7 +231,7 @@ void main() {
expect(actionIconText.text.style!.color, color); expect(actionIconText.text.style!.color, color);
}); });
testWidgets('AppBarTheme properties take priority over ThemeData properties', (WidgetTester tester) async { testWidgetsWithLeakTracking('AppBarTheme properties take priority over ThemeData properties', (WidgetTester tester) async {
final AppBarTheme appBarTheme = _appBarTheme(); final AppBarTheme appBarTheme = _appBarTheme();
await tester.pumpWidget( await tester.pumpWidget(
@ -264,7 +265,7 @@ void main() {
expect(text.style, appBarTheme.toolbarTextStyle); expect(text.style, appBarTheme.toolbarTextStyle);
}); });
testWidgets('Material2 - ThemeData colorScheme is used when no AppBarTheme is set', (WidgetTester tester) async { testWidgetsWithLeakTracking('Material2 - ThemeData colorScheme is used when no AppBarTheme is set', (WidgetTester tester) async {
final ThemeData lightTheme = ThemeData.from(colorScheme: const ColorScheme.light(), useMaterial3: false); final ThemeData lightTheme = ThemeData.from(colorScheme: const ColorScheme.light(), useMaterial3: false);
final ThemeData darkTheme = ThemeData.from(colorScheme: const ColorScheme.dark(), useMaterial3: false); final ThemeData darkTheme = ThemeData.from(colorScheme: const ColorScheme.dark(), useMaterial3: false);
Widget buildFrame(ThemeData appTheme) { Widget buildFrame(ThemeData appTheme) {
@ -338,7 +339,7 @@ void main() {
expect(text.style, Typography.material2014().englishLike.bodyMedium!.merge(Typography.material2014().black.bodyMedium).copyWith(color: darkTheme.colorScheme.onSurface)); expect(text.style, Typography.material2014().englishLike.bodyMedium!.merge(Typography.material2014().black.bodyMedium).copyWith(color: darkTheme.colorScheme.onSurface));
}); });
testWidgets('Material3 - ThemeData colorScheme is used when no AppBarTheme is set', (WidgetTester tester) async { testWidgetsWithLeakTracking('Material3 - ThemeData colorScheme is used when no AppBarTheme is set', (WidgetTester tester) async {
final ThemeData lightTheme = ThemeData.from(colorScheme: const ColorScheme.light(), useMaterial3: true); final ThemeData lightTheme = ThemeData.from(colorScheme: const ColorScheme.light(), useMaterial3: true);
final ThemeData darkTheme = ThemeData.from(colorScheme: const ColorScheme.dark(), useMaterial3: true); final ThemeData darkTheme = ThemeData.from(colorScheme: const ColorScheme.dark(), useMaterial3: true);
Widget buildFrame(ThemeData appTheme) { Widget buildFrame(ThemeData appTheme) {
@ -412,7 +413,7 @@ void main() {
expect(text.style, Typography.material2021().englishLike.bodyMedium!.merge(Typography.material2021().black.bodyMedium).copyWith(color: darkTheme.colorScheme.onSurface, decorationColor: darkTheme.colorScheme.onSurface)); expect(text.style, Typography.material2021().englishLike.bodyMedium!.merge(Typography.material2021().black.bodyMedium).copyWith(color: darkTheme.colorScheme.onSurface, decorationColor: darkTheme.colorScheme.onSurface));
}); });
testWidgets('AppBar iconTheme with color=null defers to outer IconTheme', (WidgetTester tester) async { testWidgetsWithLeakTracking('AppBar iconTheme with color=null defers to outer IconTheme', (WidgetTester tester) async {
// Verify claim made in https://github.com/flutter/flutter/pull/71184#issuecomment-737419215 // Verify claim made in https://github.com/flutter/flutter/pull/71184#issuecomment-737419215
Widget buildFrame({ Color? appIconColor, Color? appBarIconColor }) { Widget buildFrame({ Color? appIconColor, Color? appBarIconColor }) {
@ -452,7 +453,7 @@ void main() {
expect(getIconText().text.style!.color, Colors.purple); expect(getIconText().text.style!.color, Colors.purple);
}); });
testWidgets('AppBar uses AppBarTheme.centerTitle when centerTitle is null', (WidgetTester tester) async { testWidgetsWithLeakTracking('AppBar uses AppBarTheme.centerTitle when centerTitle is null', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
theme: ThemeData(appBarTheme: const AppBarTheme(centerTitle: true)), theme: ThemeData(appBarTheme: const AppBarTheme(centerTitle: true)),
home: Scaffold(appBar: AppBar( home: Scaffold(appBar: AppBar(
@ -464,7 +465,7 @@ void main() {
expect(navToolBar.centerMiddle, true); expect(navToolBar.centerMiddle, true);
}); });
testWidgets('AppBar.centerTitle takes priority over AppBarTheme.centerTitle', (WidgetTester tester) async { testWidgetsWithLeakTracking('AppBar.centerTitle takes priority over AppBarTheme.centerTitle', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
theme: ThemeData(appBarTheme: const AppBarTheme(centerTitle: true)), theme: ThemeData(appBarTheme: const AppBarTheme(centerTitle: true)),
home: Scaffold( home: Scaffold(
@ -480,7 +481,7 @@ void main() {
expect(navToolBar.centerMiddle, false); expect(navToolBar.centerMiddle, false);
}); });
testWidgets('AppBar.centerTitle adapts to TargetPlatform when AppBarTheme.centerTitle is null', (WidgetTester tester) async{ testWidgetsWithLeakTracking('AppBar.centerTitle adapts to TargetPlatform when AppBarTheme.centerTitle is null', (WidgetTester tester) async{
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
theme: ThemeData(platform: TargetPlatform.iOS), theme: ThemeData(platform: TargetPlatform.iOS),
home: Scaffold(appBar: AppBar( home: Scaffold(appBar: AppBar(
@ -494,7 +495,7 @@ void main() {
expect(navToolBar.centerMiddle, true); expect(navToolBar.centerMiddle, true);
}); });
testWidgets('AppBar.shadowColor takes priority over AppBarTheme.shadowColor', (WidgetTester tester) async { testWidgetsWithLeakTracking('AppBar.shadowColor takes priority over AppBarTheme.shadowColor', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
theme: ThemeData(appBarTheme: const AppBarTheme(shadowColor: Colors.red)), theme: ThemeData(appBarTheme: const AppBarTheme(shadowColor: Colors.red)),
home: Scaffold( home: Scaffold(
@ -510,7 +511,7 @@ void main() {
expect(appBar.shadowColor, Colors.yellow); expect(appBar.shadowColor, Colors.yellow);
}); });
testWidgets('AppBar.surfaceTintColor takes priority over AppBarTheme.surfaceTintColor', (WidgetTester tester) async { testWidgetsWithLeakTracking('AppBar.surfaceTintColor takes priority over AppBarTheme.surfaceTintColor', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
theme: ThemeData(appBarTheme: const AppBarTheme(surfaceTintColor: Colors.red)), theme: ThemeData(appBarTheme: const AppBarTheme(surfaceTintColor: Colors.red)),
home: Scaffold( home: Scaffold(
@ -526,7 +527,7 @@ void main() {
expect(appBar.surfaceTintColor, Colors.yellow); expect(appBar.surfaceTintColor, Colors.yellow);
}); });
testWidgets('Material3 - AppBarTheme.iconTheme.color takes priority over IconButtonTheme.foregroundColor', (WidgetTester tester) async { testWidgetsWithLeakTracking('Material3 - AppBarTheme.iconTheme.color takes priority over IconButtonTheme.foregroundColor', (WidgetTester tester) async {
const IconThemeData overallIconTheme = IconThemeData(color: Colors.yellow); const IconThemeData overallIconTheme = IconThemeData(color: Colors.yellow);
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
theme: ThemeData( theme: ThemeData(
@ -552,7 +553,7 @@ void main() {
expect(actionIconButtonColor, overallIconTheme.color); expect(actionIconButtonColor, overallIconTheme.color);
}); });
testWidgets('Material3 - AppBarTheme.iconTheme.size takes priority over IconButtonTheme.iconSize', (WidgetTester tester) async { testWidgetsWithLeakTracking('Material3 - AppBarTheme.iconTheme.size takes priority over IconButtonTheme.iconSize', (WidgetTester tester) async {
const IconThemeData overallIconTheme = IconThemeData(size: 30.0); const IconThemeData overallIconTheme = IconThemeData(size: 30.0);
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
theme: ThemeData( theme: ThemeData(
@ -579,7 +580,7 @@ void main() {
}); });
testWidgets('Material3 - AppBarTheme.actionsIconTheme.color takes priority over IconButtonTheme.foregroundColor', (WidgetTester tester) async { testWidgetsWithLeakTracking('Material3 - AppBarTheme.actionsIconTheme.color takes priority over IconButtonTheme.foregroundColor', (WidgetTester tester) async {
const IconThemeData actionsIconTheme = IconThemeData(color: Colors.yellow); const IconThemeData actionsIconTheme = IconThemeData(color: Colors.yellow);
final IconButtonThemeData iconButtonTheme = IconButtonThemeData( final IconButtonThemeData iconButtonTheme = IconButtonThemeData(
style: IconButton.styleFrom(foregroundColor: Colors.red), style: IconButton.styleFrom(foregroundColor: Colors.red),
@ -607,7 +608,7 @@ void main() {
expect(actionIconButtonColor, actionsIconTheme.color); expect(actionIconButtonColor, actionsIconTheme.color);
}); });
testWidgets('Material3 - AppBarTheme.actionsIconTheme.size takes priority over IconButtonTheme.iconSize', (WidgetTester tester) async { testWidgetsWithLeakTracking('Material3 - AppBarTheme.actionsIconTheme.size takes priority over IconButtonTheme.iconSize', (WidgetTester tester) async {
const IconThemeData actionsIconTheme = IconThemeData(size: 30.0); const IconThemeData actionsIconTheme = IconThemeData(size: 30.0);
final IconButtonThemeData iconButtonTheme = IconButtonThemeData( final IconButtonThemeData iconButtonTheme = IconButtonThemeData(
style: IconButton.styleFrom(iconSize: 32.0), style: IconButton.styleFrom(iconSize: 32.0),
@ -634,7 +635,7 @@ void main() {
expect(actionIconButtonSize, actionsIconTheme.size); expect(actionIconButtonSize, actionsIconTheme.size);
}); });
testWidgets('Material3 - AppBarTheme.foregroundColor takes priority over IconButtonTheme.foregroundColor', (WidgetTester tester) async { testWidgetsWithLeakTracking('Material3 - AppBarTheme.foregroundColor takes priority over IconButtonTheme.foregroundColor', (WidgetTester tester) async {
final IconButtonThemeData iconButtonTheme = IconButtonThemeData( final IconButtonThemeData iconButtonTheme = IconButtonThemeData(
style: IconButton.styleFrom(foregroundColor: Colors.red), style: IconButton.styleFrom(foregroundColor: Colors.red),
); );
@ -669,7 +670,7 @@ void main() {
expect(actionIconButtonColor, appBarTheme.foregroundColor); expect(actionIconButtonColor, appBarTheme.foregroundColor);
}); });
testWidgets('AppBar uses AppBarTheme.titleSpacing', (WidgetTester tester) async { testWidgetsWithLeakTracking('AppBar uses AppBarTheme.titleSpacing', (WidgetTester tester) async {
const double kTitleSpacing = 10; const double kTitleSpacing = 10;
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
theme: ThemeData(appBarTheme: const AppBarTheme(titleSpacing: kTitleSpacing)), theme: ThemeData(appBarTheme: const AppBarTheme(titleSpacing: kTitleSpacing)),
@ -684,7 +685,7 @@ void main() {
expect(navToolBar.middleSpacing, kTitleSpacing); expect(navToolBar.middleSpacing, kTitleSpacing);
}); });
testWidgets('AppBar.titleSpacing takes priority over AppBarTheme.titleSpacing', (WidgetTester tester) async { testWidgetsWithLeakTracking('AppBar.titleSpacing takes priority over AppBarTheme.titleSpacing', (WidgetTester tester) async {
const double kTitleSpacing = 10; const double kTitleSpacing = 10;
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
theme: ThemeData(appBarTheme: const AppBarTheme(titleSpacing: kTitleSpacing)), theme: ThemeData(appBarTheme: const AppBarTheme(titleSpacing: kTitleSpacing)),
@ -700,7 +701,7 @@ void main() {
expect(navToolBar.middleSpacing, 40); expect(navToolBar.middleSpacing, 40);
}); });
testWidgets('SliverAppBar uses AppBarTheme.titleSpacing', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverAppBar uses AppBarTheme.titleSpacing', (WidgetTester tester) async {
const double kTitleSpacing = 10; const double kTitleSpacing = 10;
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
theme: ThemeData(appBarTheme: const AppBarTheme(titleSpacing: kTitleSpacing)), theme: ThemeData(appBarTheme: const AppBarTheme(titleSpacing: kTitleSpacing)),
@ -717,7 +718,7 @@ void main() {
expect(navToolBar.middleSpacing, kTitleSpacing); expect(navToolBar.middleSpacing, kTitleSpacing);
}); });
testWidgets('SliverAppBar.titleSpacing takes priority over AppBarTheme.titleSpacing ', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverAppBar.titleSpacing takes priority over AppBarTheme.titleSpacing ', (WidgetTester tester) async {
const double kTitleSpacing = 10; const double kTitleSpacing = 10;
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
theme: ThemeData(appBarTheme: const AppBarTheme(titleSpacing: kTitleSpacing)), theme: ThemeData(appBarTheme: const AppBarTheme(titleSpacing: kTitleSpacing)),
@ -735,7 +736,7 @@ void main() {
expect(navToolbar.middleSpacing, 40); expect(navToolbar.middleSpacing, 40);
}); });
testWidgets('SliverAppBar.medium uses AppBarTheme properties', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverAppBar.medium uses AppBarTheme properties', (WidgetTester tester) async {
const String title = 'Medium App Bar'; const String title = 'Medium App Bar';
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
@ -791,7 +792,7 @@ void main() {
expect(titleOffset.dx, iconOffset.dx + appBarTheme.titleSpacing!); expect(titleOffset.dx, iconOffset.dx + appBarTheme.titleSpacing!);
}); });
testWidgets('SliverAppBar.medium properties take priority over AppBarTheme properties', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverAppBar.medium properties take priority over AppBarTheme properties', (WidgetTester tester) async {
const String title = 'Medium App Bar'; const String title = 'Medium App Bar';
const Color backgroundColor = Color(0xff000099); const Color backgroundColor = Color(0xff000099);
const Color foregroundColor = Color(0xff00ff98); const Color foregroundColor = Color(0xff00ff98);
@ -868,7 +869,7 @@ void main() {
expect(titleOffset.dx, iconOffset.dx + titleSpacing); expect(titleOffset.dx, iconOffset.dx + titleSpacing);
}); });
testWidgets('SliverAppBar.large uses AppBarTheme properties', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverAppBar.large uses AppBarTheme properties', (WidgetTester tester) async {
const String title = 'Large App Bar'; const String title = 'Large App Bar';
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
@ -924,7 +925,7 @@ void main() {
expect(titleOffset.dx, iconOffset.dx + appBarTheme.titleSpacing!); expect(titleOffset.dx, iconOffset.dx + appBarTheme.titleSpacing!);
}); });
testWidgets('SliverAppBar.large properties take priority over AppBarTheme properties', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverAppBar.large properties take priority over AppBarTheme properties', (WidgetTester tester) async {
const String title = 'Large App Bar'; const String title = 'Large App Bar';
const Color backgroundColor = Color(0xff000099); const Color backgroundColor = Color(0xff000099);
const Color foregroundColor = Color(0xff00ff98); const Color foregroundColor = Color(0xff00ff98);
@ -1001,7 +1002,7 @@ void main() {
expect(titleOffset.dx, iconOffset.dx + titleSpacing); expect(titleOffset.dx, iconOffset.dx + titleSpacing);
}); });
testWidgets( testWidgetsWithLeakTracking(
'SliverAppBar medium & large supports foregroundColor', (WidgetTester tester) async { 'SliverAppBar medium & large supports foregroundColor', (WidgetTester tester) async {
const String title = 'AppBar title'; const String title = 'AppBar title';
const AppBarTheme appBarTheme = AppBarTheme(foregroundColor: Color(0xff00ff20)); const AppBarTheme appBarTheme = AppBarTheme(foregroundColor: Color(0xff00ff20));
@ -1045,7 +1046,7 @@ void main() {
expect(largeTitle.text.style!.color, foregroundColor); expect(largeTitle.text.style!.color, foregroundColor);
}); });
testWidgets('Default AppBarTheme debugFillProperties', (WidgetTester tester) async { testWidgetsWithLeakTracking('Default AppBarTheme debugFillProperties', (WidgetTester tester) async {
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder(); final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
const AppBarTheme().debugFillProperties(builder); const AppBarTheme().debugFillProperties(builder);
@ -1057,7 +1058,7 @@ void main() {
expect(description, <String>[]); expect(description, <String>[]);
}); });
testWidgets('AppBarTheme implements debugFillProperties', (WidgetTester tester) async { testWidgetsWithLeakTracking('AppBarTheme implements debugFillProperties', (WidgetTester tester) async {
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder(); final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
const AppBarTheme( const AppBarTheme(
backgroundColor: Color(0xff000000), backgroundColor: Color(0xff000000),
@ -1112,7 +1113,7 @@ void main() {
}, skip: kIsWeb); // https://github.com/flutter/flutter/issues/87364 }, skip: kIsWeb); // https://github.com/flutter/flutter/issues/87364
// This is a regression test for https://github.com/flutter/flutter/issues/130485. // This is a regression test for https://github.com/flutter/flutter/issues/130485.
testWidgets('Material3 - AppBarTheme.iconTheme correctly applies custom white color in dark mode', (WidgetTester tester) async { testWidgetsWithLeakTracking('Material3 - AppBarTheme.iconTheme correctly applies custom white color in dark mode', (WidgetTester tester) async {
final ThemeData themeData = ThemeData( final ThemeData themeData = ThemeData(
useMaterial3: true, useMaterial3: true,
brightness: Brightness.dark, brightness: Brightness.dark,

View File

@ -8,6 +8,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
class StateMarker extends StatefulWidget { class StateMarker extends StatefulWidget {
const StateMarker({ super.key, this.child }); const StateMarker({ super.key, this.child });
@ -31,7 +32,7 @@ class StateMarkerState extends State<StateMarker> {
} }
void main() { void main() {
testWidgets('Can nest apps', (WidgetTester tester) async { testWidgetsWithLeakTracking('Can nest apps', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const MaterialApp( const MaterialApp(
home: MaterialApp( home: MaterialApp(
@ -43,7 +44,7 @@ void main() {
expect(find.text('Home sweet home'), findsOneWidget); expect(find.text('Home sweet home'), findsOneWidget);
}); });
testWidgets('Focus handling', (WidgetTester tester) async { testWidgetsWithLeakTracking('Focus handling', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(); final FocusNode focusNode = FocusNode();
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
home: Material( home: Material(
@ -70,7 +71,7 @@ void main() {
expect(find.text('Home'), findsOneWidget); expect(find.text('Home'), findsOneWidget);
}); });
testWidgets('Can show grid without losing sync', (WidgetTester tester) async { testWidgetsWithLeakTracking('Can show grid without losing sync', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const MaterialApp( const MaterialApp(
home: StateMarker(), home: StateMarker(),
@ -92,7 +93,7 @@ void main() {
expect(state2.marker, equals('original')); expect(state2.marker, equals('original'));
}); });
testWidgets('Do not rebuild page during a route transition', (WidgetTester tester) async { testWidgetsWithLeakTracking('Do not rebuild page during a route transition', (WidgetTester tester) async {
int buildCounter = 0; int buildCounter = 0;
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
@ -137,7 +138,7 @@ void main() {
expect(find.text('Y'), findsOneWidget); expect(find.text('Y'), findsOneWidget);
}); });
testWidgets('Do rebuild the home page if it changes', (WidgetTester tester) async { testWidgetsWithLeakTracking('Do rebuild the home page if it changes', (WidgetTester tester) async {
int buildCounter = 0; int buildCounter = 0;
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
@ -165,7 +166,7 @@ void main() {
expect(find.text('B'), findsOneWidget); expect(find.text('B'), findsOneWidget);
}); });
testWidgets('Do not rebuild the home page if it does not actually change', (WidgetTester tester) async { testWidgetsWithLeakTracking('Do not rebuild the home page if it does not actually change', (WidgetTester tester) async {
int buildCounter = 0; int buildCounter = 0;
final Widget home = Builder( final Widget home = Builder(
builder: (BuildContext context) { builder: (BuildContext context) {
@ -187,7 +188,7 @@ void main() {
expect(buildCounter, 1); expect(buildCounter, 1);
}); });
testWidgets('Do rebuild pages that come from the routes table if the MaterialApp changes', (WidgetTester tester) async { testWidgetsWithLeakTracking('Do rebuild pages that come from the routes table if the MaterialApp changes', (WidgetTester tester) async {
int buildCounter = 0; int buildCounter = 0;
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{ final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
'/': (BuildContext context) { '/': (BuildContext context) {
@ -209,7 +210,7 @@ void main() {
expect(buildCounter, 2); expect(buildCounter, 2);
}); });
testWidgets('Cannot pop the initial route', (WidgetTester tester) async { testWidgetsWithLeakTracking('Cannot pop the initial route', (WidgetTester tester) async {
await tester.pumpWidget(const MaterialApp(home: Text('Home'))); await tester.pumpWidget(const MaterialApp(home: Text('Home')));
expect(find.text('Home'), findsOneWidget); expect(find.text('Home'), findsOneWidget);
@ -222,7 +223,7 @@ void main() {
expect(find.text('Home'), findsOneWidget); expect(find.text('Home'), findsOneWidget);
}); });
testWidgets('Default initialRoute', (WidgetTester tester) async { testWidgetsWithLeakTracking('Default initialRoute', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(routes: <String, WidgetBuilder>{ await tester.pumpWidget(MaterialApp(routes: <String, WidgetBuilder>{
'/': (BuildContext context) => const Text('route "/"'), '/': (BuildContext context) => const Text('route "/"'),
})); }));
@ -230,7 +231,7 @@ void main() {
expect(find.text('route "/"'), findsOneWidget); expect(find.text('route "/"'), findsOneWidget);
}); });
testWidgets('One-step initial route', (WidgetTester tester) async { testWidgetsWithLeakTracking('One-step initial route', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
initialRoute: '/a', initialRoute: '/a',
@ -249,7 +250,7 @@ void main() {
expect(find.text('route "/b"', skipOffstage: false), findsNothing); expect(find.text('route "/b"', skipOffstage: false), findsNothing);
}); });
testWidgets('Return value from pop is correct', (WidgetTester tester) async { testWidgetsWithLeakTracking('Return value from pop is correct', (WidgetTester tester) async {
late Future<Object?> result; late Future<Object?> result;
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
@ -289,7 +290,7 @@ void main() {
expect(await result, equals('all done')); expect(await result, equals('all done'));
}); });
testWidgets('Two-step initial route', (WidgetTester tester) async { testWidgetsWithLeakTracking('Two-step initial route', (WidgetTester tester) async {
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{ final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
'/': (BuildContext context) => const Text('route "/"'), '/': (BuildContext context) => const Text('route "/"'),
'/a': (BuildContext context) => const Text('route "/a"'), '/a': (BuildContext context) => const Text('route "/a"'),
@ -334,7 +335,7 @@ void main() {
} }
}); });
testWidgets('Make sure initialRoute is only used the first time', (WidgetTester tester) async { testWidgetsWithLeakTracking('Make sure initialRoute is only used the first time', (WidgetTester tester) async {
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{ final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
'/': (BuildContext context) => const Text('route "/"'), '/': (BuildContext context) => const Text('route "/"'),
'/a': (BuildContext context) => const Text('route "/a"'), '/a': (BuildContext context) => const Text('route "/a"'),
@ -369,7 +370,7 @@ void main() {
expect(find.text('route "/b"', skipOffstage: false), findsNothing); expect(find.text('route "/b"', skipOffstage: false), findsNothing);
}); });
testWidgets('onGenerateRoute / onUnknownRoute', (WidgetTester tester) async { testWidgetsWithLeakTracking('onGenerateRoute / onUnknownRoute', (WidgetTester tester) async {
final List<String> log = <String>[]; final List<String> log = <String>[];
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
@ -391,7 +392,7 @@ void main() {
expect(tester.takeException(), isAssertionError); expect(tester.takeException(), isAssertionError);
}); });
testWidgets('MaterialApp with builder and no route information works.', (WidgetTester tester) async { testWidgetsWithLeakTracking('MaterialApp with builder and no route information works.', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/18904 // Regression test for https://github.com/flutter/flutter/issues/18904
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
@ -402,7 +403,7 @@ void main() {
); );
}); });
testWidgets("WidgetsApp doesn't rebuild routes when MediaQuery updates", (WidgetTester tester) async { testWidgetsWithLeakTracking("WidgetsApp doesn't rebuild routes when MediaQuery updates", (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/37878 // Regression test for https://github.com/flutter/flutter/issues/37878
addTearDown(tester.platformDispatcher.clearAllTestValues); addTearDown(tester.platformDispatcher.clearAllTestValues);
addTearDown(tester.view.reset); addTearDown(tester.view.reset);
@ -462,7 +463,7 @@ void main() {
expect(dependentBuildCount, equals(5)); expect(dependentBuildCount, equals(5));
}); });
testWidgets('Can get text scale from media query', (WidgetTester tester) async { testWidgetsWithLeakTracking('Can get text scale from media query', (WidgetTester tester) async {
TextScaler? textScaler; TextScaler? textScaler;
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
home: Builder(builder:(BuildContext context) { home: Builder(builder:(BuildContext context) {
@ -473,7 +474,7 @@ void main() {
expect(textScaler, TextScaler.noScaling); expect(textScaler, TextScaler.noScaling);
}); });
testWidgets('MaterialApp.navigatorKey', (WidgetTester tester) async { testWidgetsWithLeakTracking('MaterialApp.navigatorKey', (WidgetTester tester) async {
final GlobalKey<NavigatorState> key = GlobalKey<NavigatorState>(); final GlobalKey<NavigatorState> key = GlobalKey<NavigatorState>();
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
navigatorKey: key, navigatorKey: key,
@ -494,7 +495,7 @@ void main() {
expect(key.currentState, isA<NavigatorState>()); expect(key.currentState, isA<NavigatorState>());
}); });
testWidgets('Has default material and cupertino localizations', (WidgetTester tester) async { testWidgetsWithLeakTracking('Has default material and cupertino localizations', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
home: Builder( home: Builder(
@ -516,7 +517,7 @@ void main() {
expect(find.text('Select All'), findsOneWidget); expect(find.text('Select All'), findsOneWidget);
}); });
testWidgets('MaterialApp uses regular theme when themeMode is light', (WidgetTester tester) async { testWidgetsWithLeakTracking('MaterialApp uses regular theme when themeMode is light', (WidgetTester tester) async {
addTearDown(tester.platformDispatcher.clearAllTestValues); addTearDown(tester.platformDispatcher.clearAllTestValues);
// Mock the test to explicitly report a light platformBrightness. // Mock the test to explicitly report a light platformBrightness.
@ -564,7 +565,7 @@ void main() {
expect(appliedTheme.brightness, Brightness.light); expect(appliedTheme.brightness, Brightness.light);
}); });
testWidgets('MaterialApp uses darkTheme when themeMode is dark', (WidgetTester tester) async { testWidgetsWithLeakTracking('MaterialApp uses darkTheme when themeMode is dark', (WidgetTester tester) async {
addTearDown(tester.platformDispatcher.clearAllTestValues); addTearDown(tester.platformDispatcher.clearAllTestValues);
// Mock the test to explicitly report a light platformBrightness. // Mock the test to explicitly report a light platformBrightness.
@ -612,7 +613,7 @@ void main() {
expect(appliedTheme.brightness, Brightness.dark); expect(appliedTheme.brightness, Brightness.dark);
}); });
testWidgets('MaterialApp uses regular theme when themeMode is system and platformBrightness is light', (WidgetTester tester) async { testWidgetsWithLeakTracking('MaterialApp uses regular theme when themeMode is system and platformBrightness is light', (WidgetTester tester) async {
addTearDown(tester.platformDispatcher.clearAllTestValues); addTearDown(tester.platformDispatcher.clearAllTestValues);
// Mock the test to explicitly report a light platformBrightness. // Mock the test to explicitly report a light platformBrightness.
@ -640,7 +641,7 @@ void main() {
expect(appliedTheme.brightness, Brightness.light); expect(appliedTheme.brightness, Brightness.light);
}); });
testWidgets('MaterialApp uses darkTheme when themeMode is system and platformBrightness is dark', (WidgetTester tester) async { testWidgetsWithLeakTracking('MaterialApp uses darkTheme when themeMode is system and platformBrightness is dark', (WidgetTester tester) async {
addTearDown(tester.platformDispatcher.clearAllTestValues); addTearDown(tester.platformDispatcher.clearAllTestValues);
// Mock the test to explicitly report a dark platformBrightness. // Mock the test to explicitly report a dark platformBrightness.
@ -666,7 +667,7 @@ void main() {
expect(appliedTheme.brightness, Brightness.dark); expect(appliedTheme.brightness, Brightness.dark);
}); });
testWidgets('MaterialApp uses light theme when platformBrightness is dark but no dark theme is provided', (WidgetTester tester) async { testWidgetsWithLeakTracking('MaterialApp uses light theme when platformBrightness is dark but no dark theme is provided', (WidgetTester tester) async {
addTearDown(tester.platformDispatcher.clearAllTestValues); addTearDown(tester.platformDispatcher.clearAllTestValues);
// Mock the test to explicitly report a dark platformBrightness. // Mock the test to explicitly report a dark platformBrightness.
@ -691,7 +692,7 @@ void main() {
expect(appliedTheme.brightness, Brightness.light); expect(appliedTheme.brightness, Brightness.light);
}); });
testWidgets('MaterialApp uses fallback light theme when platformBrightness is dark but no theme is provided at all', (WidgetTester tester) async { testWidgetsWithLeakTracking('MaterialApp uses fallback light theme when platformBrightness is dark but no theme is provided at all', (WidgetTester tester) async {
addTearDown(tester.platformDispatcher.clearAllTestValues); addTearDown(tester.platformDispatcher.clearAllTestValues);
// Mock the test to explicitly report a dark platformBrightness. // Mock the test to explicitly report a dark platformBrightness.
@ -713,7 +714,7 @@ void main() {
expect(appliedTheme.brightness, Brightness.light); expect(appliedTheme.brightness, Brightness.light);
}); });
testWidgets('MaterialApp uses fallback light theme when platformBrightness is light and a dark theme is provided', (WidgetTester tester) async { testWidgetsWithLeakTracking('MaterialApp uses fallback light theme when platformBrightness is light and a dark theme is provided', (WidgetTester tester) async {
addTearDown(tester.platformDispatcher.clearAllTestValues); addTearDown(tester.platformDispatcher.clearAllTestValues);
// Mock the test to explicitly report a dark platformBrightness. // Mock the test to explicitly report a dark platformBrightness.
@ -738,7 +739,7 @@ void main() {
expect(appliedTheme.brightness, Brightness.light); expect(appliedTheme.brightness, Brightness.light);
}); });
testWidgets('MaterialApp uses dark theme when platformBrightness is dark', (WidgetTester tester) async { testWidgetsWithLeakTracking('MaterialApp uses dark theme when platformBrightness is dark', (WidgetTester tester) async {
addTearDown(tester.platformDispatcher.clearAllTestValues); addTearDown(tester.platformDispatcher.clearAllTestValues);
// Mock the test to explicitly report a dark platformBrightness. // Mock the test to explicitly report a dark platformBrightness.
@ -766,7 +767,7 @@ void main() {
expect(appliedTheme.brightness, Brightness.dark); expect(appliedTheme.brightness, Brightness.dark);
}); });
testWidgets('MaterialApp uses high contrast theme when appropriate', (WidgetTester tester) async { testWidgetsWithLeakTracking('MaterialApp uses high contrast theme when appropriate', (WidgetTester tester) async {
addTearDown(tester.platformDispatcher.clearAllTestValues); addTearDown(tester.platformDispatcher.clearAllTestValues);
tester.platformDispatcher.platformBrightnessTestValue = Brightness.light; tester.platformDispatcher.platformBrightnessTestValue = Brightness.light;
@ -794,7 +795,7 @@ void main() {
expect(appliedTheme.primaryColor, Colors.blue); expect(appliedTheme.primaryColor, Colors.blue);
}); });
testWidgets('MaterialApp uses high contrast dark theme when appropriate', (WidgetTester tester) async { testWidgetsWithLeakTracking('MaterialApp uses high contrast dark theme when appropriate', (WidgetTester tester) async {
addTearDown(tester.platformDispatcher.clearAllTestValues); addTearDown(tester.platformDispatcher.clearAllTestValues);
tester.platformDispatcher.platformBrightnessTestValue = Brightness.dark; tester.platformDispatcher.platformBrightnessTestValue = Brightness.dark;
@ -828,7 +829,7 @@ void main() {
expect(appliedTheme.primaryColor, Colors.green); expect(appliedTheme.primaryColor, Colors.green);
}); });
testWidgets('MaterialApp uses dark theme when no high contrast dark theme is provided', (WidgetTester tester) async { testWidgetsWithLeakTracking('MaterialApp uses dark theme when no high contrast dark theme is provided', (WidgetTester tester) async {
addTearDown(tester.platformDispatcher.clearAllTestValues); addTearDown(tester.platformDispatcher.clearAllTestValues);
tester.platformDispatcher.platformBrightnessTestValue = Brightness.dark; tester.platformDispatcher.platformBrightnessTestValue = Brightness.dark;
@ -856,7 +857,7 @@ void main() {
expect(appliedTheme.primaryColor, Colors.lightGreen); expect(appliedTheme.primaryColor, Colors.lightGreen);
}); });
testWidgets('MaterialApp animates theme changes', (WidgetTester tester) async { testWidgetsWithLeakTracking('MaterialApp animates theme changes', (WidgetTester tester) async {
final ThemeData lightTheme = ThemeData.light(); final ThemeData lightTheme = ThemeData.light();
final ThemeData darkTheme = ThemeData.dark(); final ThemeData darkTheme = ThemeData.dark();
await tester.pumpWidget( await tester.pumpWidget(
@ -896,7 +897,7 @@ void main() {
expect(tester.widget<Material>(find.byType(Material)).color, halfBGColor); expect(tester.widget<Material>(find.byType(Material)).color, halfBGColor);
}); });
testWidgets('MaterialApp theme animation can be turned off', (WidgetTester tester) async { testWidgetsWithLeakTracking('MaterialApp theme animation can be turned off', (WidgetTester tester) async {
final ThemeData lightTheme = ThemeData.light(); final ThemeData lightTheme = ThemeData.light();
final ThemeData darkTheme = ThemeData.dark(); final ThemeData darkTheme = ThemeData.dark();
int scaffoldRebuilds = 0; int scaffoldRebuilds = 0;
@ -938,7 +939,7 @@ void main() {
expect(scaffoldRebuilds, 2); expect(scaffoldRebuilds, 2);
}); });
testWidgets('MaterialApp switches themes when the platformBrightness changes.', (WidgetTester tester) async { testWidgetsWithLeakTracking('MaterialApp switches themes when the platformBrightness changes.', (WidgetTester tester) async {
addTearDown(tester.platformDispatcher.clearAllTestValues); addTearDown(tester.platformDispatcher.clearAllTestValues);
// Mock the test to explicitly report a light platformBrightness. // Mock the test to explicitly report a light platformBrightness.
@ -977,7 +978,7 @@ void main() {
expect(themeAfterBrightnessChange!.brightness, Brightness.dark); expect(themeAfterBrightnessChange!.brightness, Brightness.dark);
}); });
testWidgets('Material2 - MaterialApp provides default overscroll color', (WidgetTester tester) async { testWidgetsWithLeakTracking('Material2 - MaterialApp provides default overscroll color', (WidgetTester tester) async {
Future<void> slowDrag(WidgetTester tester, Offset start, Offset offset) async { Future<void> slowDrag(WidgetTester tester, Offset start, Offset offset) async {
final TestGesture gesture = await tester.startGesture(start); final TestGesture gesture = await tester.startGesture(start);
for (int index = 0; index < 10; index += 1) { for (int index = 0; index < 10; index += 1) {
@ -1009,7 +1010,7 @@ void main() {
expect(painter, paints..circle(color: glowSecondaryColor)); expect(painter, paints..circle(color: glowSecondaryColor));
}); });
testWidgets('MaterialApp can customize initial routes', (WidgetTester tester) async { testWidgetsWithLeakTracking('MaterialApp can customize initial routes', (WidgetTester tester) async {
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>(); final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
@ -1056,7 +1057,7 @@ void main() {
expect(find.text('regular page two'), findsNothing); expect(find.text('regular page two'), findsNothing);
}); });
testWidgets('MaterialApp does create HeroController with the MaterialRectArcTween', (WidgetTester tester) async { testWidgetsWithLeakTracking('MaterialApp does create HeroController with the MaterialRectArcTween', (WidgetTester tester) async {
final HeroController controller = MaterialApp.createMaterialHeroController(); final HeroController controller = MaterialApp.createMaterialHeroController();
final Tween<Rect?> tween = controller.createRectTween!( final Tween<Rect?> tween = controller.createRectTween!(
const Rect.fromLTRB(0.0, 0.0, 10.0, 10.0), const Rect.fromLTRB(0.0, 0.0, 10.0, 10.0),
@ -1065,7 +1066,7 @@ void main() {
expect(tween, isA<MaterialRectArcTween>()); expect(tween, isA<MaterialRectArcTween>());
}); });
testWidgets('MaterialApp.navigatorKey can be updated', (WidgetTester tester) async { testWidgetsWithLeakTracking('MaterialApp.navigatorKey can be updated', (WidgetTester tester) async {
final GlobalKey<NavigatorState> key1 = GlobalKey<NavigatorState>(); final GlobalKey<NavigatorState> key1 = GlobalKey<NavigatorState>();
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
navigatorKey: key1, navigatorKey: key1,
@ -1137,7 +1138,7 @@ void main() {
expect(find.text('popped'), findsOneWidget); expect(find.text('popped'), findsOneWidget);
}); });
testWidgets('MaterialApp.router throw if route information provider is provided but no route information parser', (WidgetTester tester) async { testWidgetsWithLeakTracking('MaterialApp.router throw if route information provider is provided but no route information parser', (WidgetTester tester) async {
final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate( final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate(
builder: (BuildContext context, RouteInformation information) { builder: (BuildContext context, RouteInformation information) {
return Text(information.uri.toString()); return Text(information.uri.toString());
@ -1162,7 +1163,7 @@ void main() {
expect(tester.takeException(), isAssertionError); expect(tester.takeException(), isAssertionError);
}); });
testWidgets('MaterialApp.router throw if route configuration is provided along with other delegate', (WidgetTester tester) async { testWidgetsWithLeakTracking('MaterialApp.router throw if route configuration is provided along with other delegate', (WidgetTester tester) async {
final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate( final SimpleNavigatorRouterDelegate delegate = SimpleNavigatorRouterDelegate(
builder: (BuildContext context, RouteInformation information) { builder: (BuildContext context, RouteInformation information) {
return Text(information.uri.toString()); return Text(information.uri.toString());
@ -1216,7 +1217,7 @@ void main() {
expect(find.text('popped'), findsOneWidget); expect(find.text('popped'), findsOneWidget);
}); });
testWidgets('MaterialApp.builder can build app without a Navigator', (WidgetTester tester) async { testWidgetsWithLeakTracking('MaterialApp.builder can build app without a Navigator', (WidgetTester tester) async {
Widget? builderChild; Widget? builderChild;
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
builder: (BuildContext context, Widget? child) { builder: (BuildContext context, Widget? child) {
@ -1227,7 +1228,7 @@ void main() {
expect(builderChild, isNull); expect(builderChild, isNull);
}); });
testWidgets('MaterialApp has correct default ScrollBehavior', (WidgetTester tester) async { testWidgetsWithLeakTracking('MaterialApp has correct default ScrollBehavior', (WidgetTester tester) async {
late BuildContext capturedContext; late BuildContext capturedContext;
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
@ -1242,7 +1243,7 @@ void main() {
expect(ScrollConfiguration.of(capturedContext).runtimeType, MaterialScrollBehavior); expect(ScrollConfiguration.of(capturedContext).runtimeType, MaterialScrollBehavior);
}); });
testWidgets('A ScrollBehavior can be set for MaterialApp', (WidgetTester tester) async { testWidgetsWithLeakTracking('A ScrollBehavior can be set for MaterialApp', (WidgetTester tester) async {
late BuildContext capturedContext; late BuildContext capturedContext;
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
@ -1260,7 +1261,7 @@ void main() {
expect(scrollBehavior.getScrollPhysics(capturedContext).runtimeType, NeverScrollableScrollPhysics); expect(scrollBehavior.getScrollPhysics(capturedContext).runtimeType, NeverScrollableScrollPhysics);
}); });
testWidgets('Material2 - ScrollBehavior default android overscroll indicator', (WidgetTester tester) async { testWidgetsWithLeakTracking('Material2 - ScrollBehavior default android overscroll indicator', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: false), theme: ThemeData(useMaterial3: false),
scrollBehavior: const MaterialScrollBehavior(), scrollBehavior: const MaterialScrollBehavior(),
@ -1279,7 +1280,7 @@ void main() {
expect(find.byType(GlowingOverscrollIndicator), findsOneWidget); expect(find.byType(GlowingOverscrollIndicator), findsOneWidget);
}, variant: TargetPlatformVariant.only(TargetPlatform.android)); }, variant: TargetPlatformVariant.only(TargetPlatform.android));
testWidgets('Material3 - ScrollBehavior default android overscroll indicator', (WidgetTester tester) async { testWidgetsWithLeakTracking('Material3 - ScrollBehavior default android overscroll indicator', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: true), theme: ThemeData(useMaterial3: true),
scrollBehavior: const MaterialScrollBehavior(), scrollBehavior: const MaterialScrollBehavior(),
@ -1298,7 +1299,7 @@ void main() {
expect(find.byType(GlowingOverscrollIndicator), findsNothing); expect(find.byType(GlowingOverscrollIndicator), findsNothing);
}, variant: TargetPlatformVariant.only(TargetPlatform.android)); }, variant: TargetPlatformVariant.only(TargetPlatform.android));
testWidgets('ScrollBehavior stretch android overscroll indicator', (WidgetTester tester) async { testWidgetsWithLeakTracking('ScrollBehavior stretch android overscroll indicator', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
scrollBehavior: const MaterialScrollBehavior(androidOverscrollIndicator: AndroidOverscrollIndicator.stretch), scrollBehavior: const MaterialScrollBehavior(androidOverscrollIndicator: AndroidOverscrollIndicator.stretch),
home: ListView( home: ListView(
@ -1316,7 +1317,7 @@ void main() {
expect(find.byType(GlowingOverscrollIndicator), findsNothing); expect(find.byType(GlowingOverscrollIndicator), findsNothing);
}, variant: TargetPlatformVariant.only(TargetPlatform.android)); }, variant: TargetPlatformVariant.only(TargetPlatform.android));
testWidgets('Overscroll indicator can be set by theme', (WidgetTester tester) async { testWidgetsWithLeakTracking('Overscroll indicator can be set by theme', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
// The current default is glowing, setting via the theme should override. // The current default is glowing, setting via the theme should override.
theme: ThemeData().copyWith(androidOverscrollIndicator: AndroidOverscrollIndicator.stretch), theme: ThemeData().copyWith(androidOverscrollIndicator: AndroidOverscrollIndicator.stretch),
@ -1335,7 +1336,7 @@ void main() {
expect(find.byType(GlowingOverscrollIndicator), findsNothing); expect(find.byType(GlowingOverscrollIndicator), findsNothing);
}, variant: TargetPlatformVariant.only(TargetPlatform.android)); }, variant: TargetPlatformVariant.only(TargetPlatform.android));
testWidgets('Overscroll indicator in MaterialScrollBehavior takes precedence over theme', (WidgetTester tester) async { testWidgetsWithLeakTracking('Overscroll indicator in MaterialScrollBehavior takes precedence over theme', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
// MaterialScrollBehavior.androidOverscrollIndicator takes precedence over theme. // MaterialScrollBehavior.androidOverscrollIndicator takes precedence over theme.
scrollBehavior: const MaterialScrollBehavior(androidOverscrollIndicator: AndroidOverscrollIndicator.stretch), scrollBehavior: const MaterialScrollBehavior(androidOverscrollIndicator: AndroidOverscrollIndicator.stretch),
@ -1355,7 +1356,7 @@ void main() {
expect(find.byType(GlowingOverscrollIndicator), findsNothing); expect(find.byType(GlowingOverscrollIndicator), findsNothing);
}, variant: TargetPlatformVariant.only(TargetPlatform.android)); }, variant: TargetPlatformVariant.only(TargetPlatform.android));
testWidgets('Material3 - ListView clip behavior updates overscroll indicator clip behavior', (WidgetTester tester) async { testWidgetsWithLeakTracking('Material3 - ListView clip behavior updates overscroll indicator clip behavior', (WidgetTester tester) async {
Widget buildFrame(Clip clipBehavior) { Widget buildFrame(Clip clipBehavior) {
return MaterialApp( return MaterialApp(
theme: ThemeData(useMaterial3: true), theme: ThemeData(useMaterial3: true),
@ -1431,7 +1432,7 @@ void main() {
await tester.pumpAndSettle(); await tester.pumpAndSettle();
}, variant: TargetPlatformVariant.only(TargetPlatform.android)); }, variant: TargetPlatformVariant.only(TargetPlatform.android));
testWidgets('When `useInheritedMediaQuery` is true an existing MediaQuery is used if one is available', (WidgetTester tester) async { testWidgetsWithLeakTracking('When `useInheritedMediaQuery` is true an existing MediaQuery is used if one is available', (WidgetTester tester) async {
late BuildContext capturedContext; late BuildContext capturedContext;
final UniqueKey uniqueKey = UniqueKey(); final UniqueKey uniqueKey = UniqueKey();
await tester.pumpWidget( await tester.pumpWidget(
@ -1451,7 +1452,7 @@ void main() {
expect(capturedContext.dependOnInheritedWidgetOfExactType<MediaQuery>()?.key, uniqueKey); expect(capturedContext.dependOnInheritedWidgetOfExactType<MediaQuery>()?.key, uniqueKey);
}); });
testWidgets('Assert in buildScrollbar that controller != null when using it (vertical)', (WidgetTester tester) async { testWidgetsWithLeakTracking('Assert in buildScrollbar that controller != null when using it (vertical)', (WidgetTester tester) async {
const ScrollBehavior defaultBehavior = MaterialScrollBehavior(); const ScrollBehavior defaultBehavior = MaterialScrollBehavior();
late BuildContext capturedContext; late BuildContext capturedContext;
@ -1496,7 +1497,7 @@ void main() {
} }
}, variant: TargetPlatformVariant.all()); }, variant: TargetPlatformVariant.all());
testWidgets('Assert in buildScrollbar that controller != null when using it (horizontal)', (WidgetTester tester) async { testWidgetsWithLeakTracking('Assert in buildScrollbar that controller != null when using it (horizontal)', (WidgetTester tester) async {
const ScrollBehavior defaultBehavior = MaterialScrollBehavior(); const ScrollBehavior defaultBehavior = MaterialScrollBehavior();
late BuildContext capturedContext; late BuildContext capturedContext;

View File

@ -8,7 +8,7 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() { void main() {
testWidgets('BackButton control test', (WidgetTester tester) async { testWidgetsWithLeakTracking('BackButton control test', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
home: const Material(child: Text('Home')), home: const Material(child: Text('Home')),

View File

@ -8,6 +8,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import '../widgets/semantics_tester.dart'; import '../widgets/semantics_tester.dart';
import 'feedback_tester.dart'; import 'feedback_tester.dart';
@ -23,7 +24,7 @@ Widget wrap({Widget? child}) {
} }
void main() { void main() {
testWidgets('RadioListTile should initialize according to groupValue', (WidgetTester tester) async { testWidgetsWithLeakTracking('RadioListTile should initialize according to groupValue', (WidgetTester tester) async {
final List<int> values = <int>[0, 1, 2]; final List<int> values = <int>[0, 1, 2];
int? selectedValue; int? selectedValue;
// Constructor parameters are required for [RadioListTile], but they are // Constructor parameters are required for [RadioListTile], but they are
@ -83,7 +84,7 @@ void main() {
expect(generatedRadioListTiles[2].checked, equals(false)); expect(generatedRadioListTiles[2].checked, equals(false));
}); });
testWidgets('RadioListTile simple control test', (WidgetTester tester) async { testWidgetsWithLeakTracking('RadioListTile simple control test', (WidgetTester tester) async {
final Key key = UniqueKey(); final Key key = UniqueKey();
final Key titleKey = UniqueKey(); final Key titleKey = UniqueKey();
final List<int?> log = <int?>[]; final List<int?> log = <int?>[];
@ -155,7 +156,7 @@ void main() {
expect(log, equals(<int>[1])); expect(log, equals(<int>[1]));
}); });
testWidgets('RadioListTile control tests', (WidgetTester tester) async { testWidgetsWithLeakTracking('RadioListTile control tests', (WidgetTester tester) async {
final List<int> values = <int>[0, 1, 2]; final List<int> values = <int>[0, 1, 2];
int? selectedValue; int? selectedValue;
// Constructor parameters are required for [Radio], but they are irrelevant // Constructor parameters are required for [Radio], but they are irrelevant
@ -222,7 +223,7 @@ void main() {
expect(log, equals(<dynamic>[1, '-', 2])); expect(log, equals(<dynamic>[1, '-', 2]));
}); });
testWidgets('Selected RadioListTile should not trigger onChanged', (WidgetTester tester) async { testWidgetsWithLeakTracking('Selected RadioListTile should not trigger onChanged', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/30311 // Regression test for https://github.com/flutter/flutter/issues/30311
final List<int> values = <int>[0, 1, 2]; final List<int> values = <int>[0, 1, 2];
int? selectedValue; int? selectedValue;
@ -274,7 +275,7 @@ void main() {
expect(log, equals(<int>[0])); expect(log, equals(<int>[0]));
}); });
testWidgets('Selected RadioListTile should trigger onChanged when toggleable', (WidgetTester tester) async { testWidgetsWithLeakTracking('Selected RadioListTile should trigger onChanged when toggleable', (WidgetTester tester) async {
final List<int> values = <int>[0, 1, 2]; final List<int> values = <int>[0, 1, 2];
int? selectedValue; int? selectedValue;
// Constructor parameters are required for [Radio], but they are irrelevant // Constructor parameters are required for [Radio], but they are irrelevant
@ -328,7 +329,7 @@ void main() {
expect(log, equals(<int?>[0, null, 0])); expect(log, equals(<int?>[0, null, 0]));
}); });
testWidgets('RadioListTile can be toggled when toggleable is set', (WidgetTester tester) async { testWidgetsWithLeakTracking('RadioListTile can be toggled when toggleable is set', (WidgetTester tester) async {
final Key key = UniqueKey(); final Key key = UniqueKey();
final List<int?> log = <int?>[]; final List<int?> log = <int?>[];
@ -383,7 +384,7 @@ void main() {
expect(log, equals(<int>[1])); expect(log, equals(<int>[1]));
}); });
testWidgets('RadioListTile semantics', (WidgetTester tester) async { testWidgetsWithLeakTracking('RadioListTile semantics', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget( await tester.pumpWidget(
@ -532,7 +533,7 @@ void main() {
semantics.dispose(); semantics.dispose();
}); });
testWidgets('RadioListTile has semantic events', (WidgetTester tester) async { testWidgetsWithLeakTracking('RadioListTile has semantic events', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
final Key key = UniqueKey(); final Key key = UniqueKey();
dynamic semanticEvent; dynamic semanticEvent;
@ -571,7 +572,7 @@ void main() {
tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(SystemChannels.accessibility, null); tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(SystemChannels.accessibility, null);
}); });
testWidgets('RadioListTile can autofocus unless disabled.', (WidgetTester tester) async { testWidgetsWithLeakTracking('RadioListTile can autofocus unless disabled.', (WidgetTester tester) async {
final GlobalKey childKey = GlobalKey(); final GlobalKey childKey = GlobalKey();
await tester.pumpWidget( await tester.pumpWidget(
@ -605,7 +606,7 @@ void main() {
expect(Focus.of(childKey.currentContext!).hasPrimaryFocus, isFalse); expect(Focus.of(childKey.currentContext!).hasPrimaryFocus, isFalse);
}); });
testWidgets('RadioListTile contentPadding test', (WidgetTester tester) async { testWidgetsWithLeakTracking('RadioListTile contentPadding test', (WidgetTester tester) async {
final Type radioType = const Radio<bool>( final Type radioType = const Radio<bool>(
groupValue: true, groupValue: true,
value: true, value: true,
@ -645,7 +646,7 @@ void main() {
expect(paddingRect.right, titleRect.right + 15); //right padding expect(paddingRect.right, titleRect.right + 15); //right padding
}); });
testWidgets('RadioListTile respects shape', (WidgetTester tester) async { testWidgetsWithLeakTracking('RadioListTile respects shape', (WidgetTester tester) async {
const ShapeBorder shapeBorder = RoundedRectangleBorder( const ShapeBorder shapeBorder = RoundedRectangleBorder(
borderRadius: BorderRadius.horizontal(right: Radius.circular(100)), borderRadius: BorderRadius.horizontal(right: Radius.circular(100)),
); );
@ -665,7 +666,7 @@ void main() {
expect(tester.widget<InkWell>(find.byType(InkWell)).customBorder, shapeBorder); expect(tester.widget<InkWell>(find.byType(InkWell)).customBorder, shapeBorder);
}); });
testWidgets('RadioListTile respects tileColor', (WidgetTester tester) async { testWidgetsWithLeakTracking('RadioListTile respects tileColor', (WidgetTester tester) async {
final Color tileColor = Colors.red.shade500; final Color tileColor = Colors.red.shade500;
await tester.pumpWidget( await tester.pumpWidget(
@ -685,7 +686,7 @@ void main() {
expect(find.byType(Material), paints..rect(color: tileColor)); expect(find.byType(Material), paints..rect(color: tileColor));
}); });
testWidgets('RadioListTile respects selectedTileColor', (WidgetTester tester) async { testWidgetsWithLeakTracking('RadioListTile respects selectedTileColor', (WidgetTester tester) async {
final Color selectedTileColor = Colors.green.shade500; final Color selectedTileColor = Colors.green.shade500;
await tester.pumpWidget( await tester.pumpWidget(
@ -706,7 +707,7 @@ void main() {
expect(find.byType(Material), paints..rect(color: selectedTileColor)); expect(find.byType(Material), paints..rect(color: selectedTileColor));
}); });
testWidgets('RadioListTile selected item text Color', (WidgetTester tester) async { testWidgetsWithLeakTracking('RadioListTile selected item text Color', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/pull/76906 // Regression test for https://github.com/flutter/flutter/pull/76906
const Color activeColor = Color(0xff00ff00); const Color activeColor = Color(0xff00ff00);
@ -746,7 +747,7 @@ void main() {
expect(textColor('title'), activeColor); expect(textColor('title'), activeColor);
}); });
testWidgets('RadioListTile respects visualDensity', (WidgetTester tester) async { testWidgetsWithLeakTracking('RadioListTile respects visualDensity', (WidgetTester tester) async {
const Key key = Key('test'); const Key key = Key('test');
Future<void> buildTest(VisualDensity visualDensity) async { Future<void> buildTest(VisualDensity visualDensity) async {
return tester.pumpWidget( return tester.pumpWidget(
@ -771,7 +772,7 @@ void main() {
expect(box.size, equals(const Size(800, 56))); expect(box.size, equals(const Size(800, 56)));
}); });
testWidgets('RadioListTile respects focusNode', (WidgetTester tester) async { testWidgetsWithLeakTracking('RadioListTile respects focusNode', (WidgetTester tester) async {
final GlobalKey childKey = GlobalKey(); final GlobalKey childKey = GlobalKey();
await tester.pumpWidget( await tester.pumpWidget(
wrap( wrap(
@ -824,7 +825,7 @@ void main() {
expect(node.hasFocus, isFalse); expect(node.hasFocus, isFalse);
}); });
testWidgets('Radio changes mouse cursor when hovered', (WidgetTester tester) async { testWidgetsWithLeakTracking('Radio changes mouse cursor when hovered', (WidgetTester tester) async {
// Test Radio() constructor // Test Radio() constructor
await tester.pumpWidget( await tester.pumpWidget(
wrap(child: MouseRegion( wrap(child: MouseRegion(
@ -875,7 +876,7 @@ void main() {
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic); expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.basic);
}); });
testWidgets('RadioListTile respects fillColor in enabled/disabled states', (WidgetTester tester) async { testWidgetsWithLeakTracking('RadioListTile respects fillColor in enabled/disabled states', (WidgetTester tester) async {
const Color activeEnabledFillColor = Color(0xFF000001); const Color activeEnabledFillColor = Color(0xFF000001);
const Color activeDisabledFillColor = Color(0xFF000002); const Color activeDisabledFillColor = Color(0xFF000002);
const Color inactiveEnabledFillColor = Color(0xFF000003); const Color inactiveEnabledFillColor = Color(0xFF000003);
@ -962,7 +963,7 @@ void main() {
); );
}); });
testWidgets('RadioListTile respects fillColor in hovered state', (WidgetTester tester) async { testWidgetsWithLeakTracking('RadioListTile respects fillColor in hovered state', (WidgetTester tester) async {
tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional; tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
const Color hoveredFillColor = Color(0xFF000001); const Color hoveredFillColor = Color(0xFF000001);
@ -1011,7 +1012,7 @@ void main() {
); );
}); });
testWidgets('Material3 - RadioListTile respects hoverColor', (WidgetTester tester) async { testWidgetsWithLeakTracking('Material3 - RadioListTile respects hoverColor', (WidgetTester tester) async {
tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional; tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
int? groupValue = 0; int? groupValue = 0;
final Color? hoverColor = Colors.orange[500]; final Color? hoverColor = Colors.orange[500];
@ -1077,7 +1078,7 @@ void main() {
); );
}); });
testWidgets('Material3 - RadioListTile respects overlayColor in active/pressed/hovered states', (WidgetTester tester) async { testWidgetsWithLeakTracking('Material3 - RadioListTile respects overlayColor in active/pressed/hovered states', (WidgetTester tester) async {
tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional; tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
const Color fillColor = Color(0xFF000000); const Color fillColor = Color(0xFF000000);
@ -1202,7 +1203,7 @@ void main() {
); );
}); });
testWidgets('RadioListTile respects splashRadius', (WidgetTester tester) async { testWidgetsWithLeakTracking('RadioListTile respects splashRadius', (WidgetTester tester) async {
tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional; tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
const double splashRadius = 30; const double splashRadius = 30;
Widget buildApp() { Widget buildApp() {
@ -1234,7 +1235,7 @@ void main() {
); );
}); });
testWidgets('Radio respects materialTapTargetSize', (WidgetTester tester) async { testWidgetsWithLeakTracking('Radio respects materialTapTargetSize', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
wrap(child: RadioListTile<bool>( wrap(child: RadioListTile<bool>(
groupValue: true, groupValue: true,
@ -1258,7 +1259,7 @@ void main() {
expect(tester.getSize(find.byType(Radio<bool>)), const Size(48.0, 48.0)); expect(tester.getSize(find.byType(Radio<bool>)), const Size(48.0, 48.0));
}); });
testWidgets('RadioListTile.adaptive shows the correct radio platform widget', (WidgetTester tester) async { testWidgetsWithLeakTracking('RadioListTile.adaptive shows the correct radio platform widget', (WidgetTester tester) async {
Widget buildApp(TargetPlatform platform) { Widget buildApp(TargetPlatform platform) {
return MaterialApp( return MaterialApp(
theme: ThemeData(platform: platform), theme: ThemeData(platform: platform),
@ -1300,7 +1301,7 @@ void main() {
feedback.dispose(); feedback.dispose();
}); });
testWidgets('RadioListTile respects enableFeedback', (WidgetTester tester) async { testWidgetsWithLeakTracking('RadioListTile respects enableFeedback', (WidgetTester tester) async {
const Key key = Key('test'); const Key key = Key('test');
Future<void> buildTest(bool enableFeedback) async { Future<void> buildTest(bool enableFeedback) async {
return tester.pumpWidget( return tester.pumpWidget(
@ -1338,7 +1339,7 @@ void main() {
// support is deprecated and the APIs are removed, these tests // support is deprecated and the APIs are removed, these tests
// can be deleted. // can be deleted.
testWidgets('Material2 - RadioListTile respects overlayColor in active/pressed/hovered states', (WidgetTester tester) async { testWidgetsWithLeakTracking('Material2 - RadioListTile respects overlayColor in active/pressed/hovered states', (WidgetTester tester) async {
tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional; tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
const Color fillColor = Color(0xFF000000); const Color fillColor = Color(0xFF000000);
@ -1442,7 +1443,7 @@ void main() {
); );
}); });
testWidgets('Material2 - RadioListTile respects hoverColor', (WidgetTester tester) async { testWidgetsWithLeakTracking('Material2 - RadioListTile respects hoverColor', (WidgetTester tester) async {
tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional; tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
int? groupValue = 0; int? groupValue = 0;
final Color? hoverColor = Colors.orange[500]; final Color? hoverColor = Colors.orange[500];