Unverified Commit 1437aa2c authored by derdilla's avatar derdilla Committed by GitHub

Cover some cupertino tests with leak tracking (#135230)

parent 397da064
...@@ -15,11 +15,12 @@ import 'package:flutter/foundation.dart'; ...@@ -15,11 +15,12 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.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';
void main() { void main() {
testWidgets('Alert dialog control test', (WidgetTester tester) async { testWidgetsWithLeakTracking('Alert dialog control test', (WidgetTester tester) async {
bool didDelete = false; bool didDelete = false;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -58,7 +59,7 @@ void main() { ...@@ -58,7 +59,7 @@ void main() {
expect(find.text('Delete'), findsNothing); expect(find.text('Delete'), findsNothing);
}); });
testWidgets('Dialog not barrier dismissible by default', (WidgetTester tester) async { testWidgetsWithLeakTracking('Dialog not barrier dismissible by default', (WidgetTester tester) async {
await tester.pumpWidget(createAppWithCenteredButton(const Text('Go'))); await tester.pumpWidget(createAppWithCenteredButton(const Text('Go')));
final BuildContext context = tester.element(find.text('Go')); final BuildContext context = tester.element(find.text('Go'));
...@@ -86,7 +87,7 @@ void main() { ...@@ -86,7 +87,7 @@ void main() {
}); });
testWidgets('Dialog configurable to be barrier dismissible', (WidgetTester tester) async { testWidgetsWithLeakTracking('Dialog configurable to be barrier dismissible', (WidgetTester tester) async {
await tester.pumpWidget(createAppWithCenteredButton(const Text('Go'))); await tester.pumpWidget(createAppWithCenteredButton(const Text('Go')));
final BuildContext context = tester.element(find.text('Go')); final BuildContext context = tester.element(find.text('Go'));
...@@ -114,7 +115,7 @@ void main() { ...@@ -114,7 +115,7 @@ void main() {
expect(find.text('Dialog'), findsNothing); expect(find.text('Dialog'), findsNothing);
}); });
testWidgets('Dialog destructive action style', (WidgetTester tester) async { testWidgetsWithLeakTracking('Dialog destructive action style', (WidgetTester tester) async {
await tester.pumpWidget(boilerplate(const CupertinoDialogAction( await tester.pumpWidget(boilerplate(const CupertinoDialogAction(
isDestructiveAction: true, isDestructiveAction: true,
child: Text('Ok'), child: Text('Ok'),
...@@ -125,7 +126,7 @@ void main() { ...@@ -125,7 +126,7 @@ void main() {
expect(widget.style.color!.withAlpha(255), CupertinoColors.systemRed.color); expect(widget.style.color!.withAlpha(255), CupertinoColors.systemRed.color);
}); });
testWidgets('Dialog default action style', (WidgetTester tester) async { testWidgetsWithLeakTracking('Dialog default action style', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
CupertinoTheme( CupertinoTheme(
data: const CupertinoThemeData( data: const CupertinoThemeData(
...@@ -142,7 +143,7 @@ void main() { ...@@ -142,7 +143,7 @@ void main() {
expect(widget.style.color!.withAlpha(255), CupertinoColors.systemGreen.color); expect(widget.style.color!.withAlpha(255), CupertinoColors.systemGreen.color);
}); });
testWidgets('Dialog dark theme', (WidgetTester tester) async { testWidgetsWithLeakTracking('Dialog dark theme', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: MediaQuery( home: MediaQuery(
...@@ -178,7 +179,7 @@ void main() { ...@@ -178,7 +179,7 @@ void main() {
); );
}); });
testWidgets('Has semantic annotations', (WidgetTester tester) async { testWidgetsWithLeakTracking('Has semantic annotations', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(const MaterialApp(home: Material( await tester.pumpWidget(const MaterialApp(home: Material(
child: CupertinoAlertDialog( child: CupertinoAlertDialog(
...@@ -250,7 +251,7 @@ void main() { ...@@ -250,7 +251,7 @@ void main() {
semantics.dispose(); semantics.dispose();
}); });
testWidgets('Dialog default action style', (WidgetTester tester) async { testWidgetsWithLeakTracking('Dialog default action style', (WidgetTester tester) async {
await tester.pumpWidget(boilerplate(const CupertinoDialogAction( await tester.pumpWidget(boilerplate(const CupertinoDialogAction(
isDefaultAction: true, isDefaultAction: true,
child: Text('Ok'), child: Text('Ok'),
...@@ -261,7 +262,7 @@ void main() { ...@@ -261,7 +262,7 @@ void main() {
expect(widget.style.fontWeight, equals(FontWeight.w600)); expect(widget.style.fontWeight, equals(FontWeight.w600));
}); });
testWidgets('Dialog default and destructive action styles', (WidgetTester tester) async { testWidgetsWithLeakTracking('Dialog default and destructive action styles', (WidgetTester tester) async {
await tester.pumpWidget(boilerplate(const CupertinoDialogAction( await tester.pumpWidget(boilerplate(const CupertinoDialogAction(
isDefaultAction: true, isDefaultAction: true,
isDestructiveAction: true, isDestructiveAction: true,
...@@ -274,7 +275,7 @@ void main() { ...@@ -274,7 +275,7 @@ void main() {
expect(widget.style.fontWeight, equals(FontWeight.w600)); expect(widget.style.fontWeight, equals(FontWeight.w600));
}); });
testWidgets('Dialog disabled action style', (WidgetTester tester) async { testWidgetsWithLeakTracking('Dialog disabled action style', (WidgetTester tester) async {
await tester.pumpWidget(boilerplate(const CupertinoDialogAction( await tester.pumpWidget(boilerplate(const CupertinoDialogAction(
child: Text('Ok'), child: Text('Ok'),
))); )));
...@@ -285,7 +286,7 @@ void main() { ...@@ -285,7 +286,7 @@ void main() {
expect(widget.style.color!.opacity, lessThanOrEqualTo(128 / 255)); expect(widget.style.color!.opacity, lessThanOrEqualTo(128 / 255));
}); });
testWidgets('Dialog enabled action style', (WidgetTester tester) async { testWidgetsWithLeakTracking('Dialog enabled action style', (WidgetTester tester) async {
await tester.pumpWidget(boilerplate(CupertinoDialogAction( await tester.pumpWidget(boilerplate(CupertinoDialogAction(
child: const Text('Ok'), child: const Text('Ok'),
onPressed: () {}, onPressed: () {},
...@@ -296,8 +297,9 @@ void main() { ...@@ -296,8 +297,9 @@ void main() {
expect(widget.style.color!.opacity, equals(1.0)); expect(widget.style.color!.opacity, equals(1.0));
}); });
testWidgets('Message is scrollable, has correct padding with large text sizes', (WidgetTester tester) async { testWidgetsWithLeakTracking('Message is scrollable, has correct padding with large text sizes', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget( await tester.pumpWidget(
createAppWithButtonThatLaunchesDialog( createAppWithButtonThatLaunchesDialog(
dialogBuilder: (BuildContext context) { dialogBuilder: (BuildContext context) {
...@@ -352,8 +354,9 @@ void main() { ...@@ -352,8 +354,9 @@ void main() {
expect(tester.getSize(find.widgetWithText(CupertinoDialogAction, 'OK')), equals(const Size(310.0, 98.0))); expect(tester.getSize(find.widgetWithText(CupertinoDialogAction, 'OK')), equals(const Size(310.0, 98.0)));
}); });
testWidgets('Dialog respects small constraints.', (WidgetTester tester) async { testWidgetsWithLeakTracking('Dialog respects small constraints.', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget( await tester.pumpWidget(
createAppWithButtonThatLaunchesDialog( createAppWithButtonThatLaunchesDialog(
dialogBuilder: (BuildContext context) { dialogBuilder: (BuildContext context) {
...@@ -397,8 +400,9 @@ void main() { ...@@ -397,8 +400,9 @@ void main() {
); );
}); });
testWidgets('Button list is scrollable, has correct position with large text sizes.', (WidgetTester tester) async { testWidgetsWithLeakTracking('Button list is scrollable, has correct position with large text sizes.', (WidgetTester tester) async {
final ScrollController actionScrollController = ScrollController(); final ScrollController actionScrollController = ScrollController();
addTearDown(actionScrollController.dispose);
await tester.pumpWidget( await tester.pumpWidget(
createAppWithButtonThatLaunchesDialog( createAppWithButtonThatLaunchesDialog(
dialogBuilder: (BuildContext context) { dialogBuilder: (BuildContext context) {
...@@ -457,9 +461,10 @@ void main() { ...@@ -457,9 +461,10 @@ void main() {
expect(tester.getSize(find.widgetWithText(CupertinoDialogAction, 'Cancel')).height, equals(148.0)); expect(tester.getSize(find.widgetWithText(CupertinoDialogAction, 'Cancel')).height, equals(148.0));
}); });
testWidgets('Title Section is empty, Button section is not empty.', (WidgetTester tester) async { testWidgetsWithLeakTracking('Title Section is empty, Button section is not empty.', (WidgetTester tester) async {
const double textScaleFactor = 1.0; const double textScaleFactor = 1.0;
final ScrollController actionScrollController = ScrollController(); final ScrollController actionScrollController = ScrollController();
addTearDown(actionScrollController.dispose);
await tester.pumpWidget( await tester.pumpWidget(
createAppWithButtonThatLaunchesDialog( createAppWithButtonThatLaunchesDialog(
dialogBuilder: (BuildContext context) { dialogBuilder: (BuildContext context) {
...@@ -510,9 +515,10 @@ void main() { ...@@ -510,9 +515,10 @@ void main() {
); );
}); });
testWidgets('Button section is empty, Title section is not empty.', (WidgetTester tester) async { testWidgetsWithLeakTracking('Button section is empty, Title section is not empty.', (WidgetTester tester) async {
const double textScaleFactor = 1.0; const double textScaleFactor = 1.0;
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget( await tester.pumpWidget(
createAppWithButtonThatLaunchesDialog( createAppWithButtonThatLaunchesDialog(
dialogBuilder: (BuildContext context) { dialogBuilder: (BuildContext context) {
...@@ -551,8 +557,9 @@ void main() { ...@@ -551,8 +557,9 @@ void main() {
); );
}); });
testWidgets('Actions section height for 1 button is height of button.', (WidgetTester tester) async { testWidgetsWithLeakTracking('Actions section height for 1 button is height of button.', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget( await tester.pumpWidget(
createAppWithButtonThatLaunchesDialog( createAppWithButtonThatLaunchesDialog(
dialogBuilder: (BuildContext context) { dialogBuilder: (BuildContext context) {
...@@ -580,8 +587,9 @@ void main() { ...@@ -580,8 +587,9 @@ void main() {
expect(okButtonBox.size.height, actionsSectionBox.size.height); expect(okButtonBox.size.height, actionsSectionBox.size.height);
}); });
testWidgets('Actions section height for 2 side-by-side buttons is height of tallest button.', (WidgetTester tester) async { testWidgetsWithLeakTracking('Actions section height for 2 side-by-side buttons is height of tallest button.', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
late double dividerWidth; // Will be set when the dialog builder runs. Needs a BuildContext. late double dividerWidth; // Will be set when the dialog builder runs. Needs a BuildContext.
await tester.pumpWidget( await tester.pumpWidget(
createAppWithButtonThatLaunchesDialog( createAppWithButtonThatLaunchesDialog(
...@@ -625,8 +633,9 @@ void main() { ...@@ -625,8 +633,9 @@ void main() {
); );
}); });
testWidgets('Actions section height for 2 stacked buttons with enough room is height of both buttons.', (WidgetTester tester) async { testWidgetsWithLeakTracking('Actions section height for 2 stacked buttons with enough room is height of both buttons.', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
late double dividerThickness; // Will be set when the dialog builder runs. Needs a BuildContext. late double dividerThickness; // Will be set when the dialog builder runs. Needs a BuildContext.
await tester.pumpWidget( await tester.pumpWidget(
createAppWithButtonThatLaunchesDialog( createAppWithButtonThatLaunchesDialog(
...@@ -667,8 +676,9 @@ void main() { ...@@ -667,8 +676,9 @@ void main() {
); );
}); });
testWidgets('Actions section height for 2 stacked buttons without enough room and regular font is 1.5 buttons tall.', (WidgetTester tester) async { testWidgetsWithLeakTracking('Actions section height for 2 stacked buttons without enough room and regular font is 1.5 buttons tall.', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget( await tester.pumpWidget(
createAppWithButtonThatLaunchesDialog( createAppWithButtonThatLaunchesDialog(
dialogBuilder: (BuildContext context) { dialogBuilder: (BuildContext context) {
...@@ -701,8 +711,9 @@ void main() { ...@@ -701,8 +711,9 @@ void main() {
); );
}); });
testWidgets('Actions section height for 2 stacked buttons without enough room and large accessibility font is 50% of dialog height.', (WidgetTester tester) async { testWidgetsWithLeakTracking('Actions section height for 2 stacked buttons without enough room and large accessibility font is 50% of dialog height.', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget( await tester.pumpWidget(
createAppWithButtonThatLaunchesDialog( createAppWithButtonThatLaunchesDialog(
dialogBuilder: (BuildContext context) { dialogBuilder: (BuildContext context) {
...@@ -741,8 +752,9 @@ void main() { ...@@ -741,8 +752,9 @@ void main() {
); );
}); });
testWidgets('Actions section height for 3 buttons without enough room is 1.5 buttons tall.', (WidgetTester tester) async { testWidgetsWithLeakTracking('Actions section height for 3 buttons without enough room is 1.5 buttons tall.', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget( await tester.pumpWidget(
createAppWithButtonThatLaunchesDialog( createAppWithButtonThatLaunchesDialog(
dialogBuilder: (BuildContext context) { dialogBuilder: (BuildContext context) {
...@@ -785,8 +797,9 @@ void main() { ...@@ -785,8 +797,9 @@ void main() {
); );
}); });
testWidgets('Actions section overscroll is painted white.', (WidgetTester tester) async { testWidgetsWithLeakTracking('Actions section overscroll is painted white.', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget( await tester.pumpWidget(
createAppWithButtonThatLaunchesDialog( createAppWithButtonThatLaunchesDialog(
dialogBuilder: (BuildContext context) { dialogBuilder: (BuildContext context) {
...@@ -833,8 +846,9 @@ void main() { ...@@ -833,8 +846,9 @@ void main() {
)); ));
}); });
testWidgets('Pressed button changes appearance and dividers disappear.', (WidgetTester tester) async { testWidgetsWithLeakTracking('Pressed button changes appearance and dividers disappear.', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
late double dividerThickness; // Will be set when the dialog builder runs. Needs a BuildContext. late double dividerThickness; // Will be set when the dialog builder runs. Needs a BuildContext.
await tester.pumpWidget( await tester.pumpWidget(
createAppWithButtonThatLaunchesDialog( createAppWithButtonThatLaunchesDialog(
...@@ -946,7 +960,7 @@ void main() { ...@@ -946,7 +960,7 @@ void main() {
await gesture.up(); await gesture.up();
}); });
testWidgets('ScaleTransition animation for showCupertinoDialog()', (WidgetTester tester) async { testWidgetsWithLeakTracking('ScaleTransition animation for showCupertinoDialog()', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -1024,7 +1038,7 @@ void main() { ...@@ -1024,7 +1038,7 @@ void main() {
expect(find.byType(Transform), findsNothing); expect(find.byType(Transform), findsNothing);
}); });
testWidgets('FadeTransition animation for showCupertinoDialog()', (WidgetTester tester) async { testWidgetsWithLeakTracking('FadeTransition animation for showCupertinoDialog()', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: Center( home: Center(
...@@ -1117,7 +1131,7 @@ void main() { ...@@ -1117,7 +1131,7 @@ void main() {
expect(transition.opacity.value, moreOrLessEquals(0.0, epsilon: 0.001)); expect(transition.opacity.value, moreOrLessEquals(0.0, epsilon: 0.001));
}); });
testWidgets('Actions are accessible by key', (WidgetTester tester) async { testWidgetsWithLeakTracking('Actions are accessible by key', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
createAppWithButtonThatLaunchesDialog( createAppWithButtonThatLaunchesDialog(
dialogBuilder: (BuildContext context) { dialogBuilder: (BuildContext context) {
...@@ -1147,7 +1161,7 @@ void main() { ...@@ -1147,7 +1161,7 @@ void main() {
expect(find.byKey(const Key('option_3')), findsNothing); expect(find.byKey(const Key('option_3')), findsNothing);
}); });
testWidgets('Dialog widget insets by MediaQuery viewInsets', (WidgetTester tester) async { testWidgetsWithLeakTracking('Dialog widget insets by MediaQuery viewInsets', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const MaterialApp( const MaterialApp(
home: MediaQuery( home: MediaQuery(
...@@ -1177,7 +1191,7 @@ void main() { ...@@ -1177,7 +1191,7 @@ void main() {
expect(tester.getRect(find.byType(Placeholder)), placeholderRectWithoutInsets.translate(10, 10)); expect(tester.getRect(find.byType(Placeholder)), placeholderRectWithoutInsets.translate(10, 10));
}); });
testWidgets('Material2 - Default cupertino dialog golden', (WidgetTester tester) async { testWidgetsWithLeakTracking('Material2 - Default cupertino dialog golden', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
createAppWithButtonThatLaunchesDialog( createAppWithButtonThatLaunchesDialog(
useMaterial3: false, useMaterial3: false,
...@@ -1208,7 +1222,7 @@ void main() { ...@@ -1208,7 +1222,7 @@ void main() {
); );
}); });
testWidgets('Material3 - Default cupertino dialog golden', (WidgetTester tester) async { testWidgetsWithLeakTracking('Material3 - Default cupertino dialog golden', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
createAppWithButtonThatLaunchesDialog( createAppWithButtonThatLaunchesDialog(
useMaterial3: true, useMaterial3: true,
...@@ -1239,7 +1253,7 @@ void main() { ...@@ -1239,7 +1253,7 @@ void main() {
); );
}); });
testWidgets('showCupertinoDialog - custom barrierLabel', (WidgetTester tester) async { testWidgetsWithLeakTracking('showCupertinoDialog - custom barrierLabel', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget( await tester.pumpWidget(
...@@ -1279,7 +1293,7 @@ void main() { ...@@ -1279,7 +1293,7 @@ void main() {
semantics.dispose(); semantics.dispose();
}); });
testWidgets('CupertinoDialogRoute is state restorable', (WidgetTester tester) async { testWidgetsWithLeakTracking('CupertinoDialogRoute is state restorable', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const CupertinoApp( const CupertinoApp(
restorationScopeId: 'app', restorationScopeId: 'app',
...@@ -1309,10 +1323,11 @@ void main() { ...@@ -1309,10 +1323,11 @@ void main() {
expect(find.byType(CupertinoAlertDialog), findsOneWidget); expect(find.byType(CupertinoAlertDialog), findsOneWidget);
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/33615 }, skip: isBrowser); // https://github.com/flutter/flutter/issues/33615
testWidgets('Conflicting scrollbars are not applied by ScrollBehavior to CupertinoAlertDialog', (WidgetTester tester) async { testWidgetsWithLeakTracking('Conflicting scrollbars are not applied by ScrollBehavior to CupertinoAlertDialog', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/83819 // Regression test for https://github.com/flutter/flutter/issues/83819
const double textScaleFactor = 1.0; const double textScaleFactor = 1.0;
final ScrollController actionScrollController = ScrollController(); final ScrollController actionScrollController = ScrollController();
addTearDown(actionScrollController.dispose);
await tester.pumpWidget( await tester.pumpWidget(
createAppWithButtonThatLaunchesDialog( createAppWithButtonThatLaunchesDialog(
dialogBuilder: (BuildContext context) { dialogBuilder: (BuildContext context) {
...@@ -1348,7 +1363,7 @@ void main() { ...@@ -1348,7 +1363,7 @@ void main() {
expect(find.byType(CupertinoScrollbar), findsNWidgets(2)); expect(find.byType(CupertinoScrollbar), findsNWidgets(2));
}, variant: TargetPlatformVariant.all()); }, variant: TargetPlatformVariant.all());
testWidgets('CupertinoAlertDialog scrollbars controllers should be different', (WidgetTester tester) async { testWidgetsWithLeakTracking('CupertinoAlertDialog scrollbars controllers should be different', (WidgetTester tester) async {
// https://github.com/flutter/flutter/pull/81278 // https://github.com/flutter/flutter/pull/81278
await tester.pumpWidget( await tester.pumpWidget(
const MaterialApp( const MaterialApp(
...@@ -1375,7 +1390,7 @@ void main() { ...@@ -1375,7 +1390,7 @@ void main() {
}); });
group('showCupertinoDialog avoids overlapping display features', () { group('showCupertinoDialog avoids overlapping display features', () {
testWidgets('positioning using anchorPoint', (WidgetTester tester) async { testWidgetsWithLeakTracking('positioning using anchorPoint', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
builder: (BuildContext context, Widget? child) { builder: (BuildContext context, Widget? child) {
...@@ -1413,7 +1428,7 @@ void main() { ...@@ -1413,7 +1428,7 @@ void main() {
expect(tester.getBottomRight(find.byType(Placeholder)), const Offset(800.0, 600.0)); expect(tester.getBottomRight(find.byType(Placeholder)), const Offset(800.0, 600.0));
}); });
testWidgets('positioning using Directionality', (WidgetTester tester) async { testWidgetsWithLeakTracking('positioning using Directionality', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
builder: (BuildContext context, Widget? child) { builder: (BuildContext context, Widget? child) {
...@@ -1453,7 +1468,7 @@ void main() { ...@@ -1453,7 +1468,7 @@ void main() {
expect(tester.getBottomRight(find.byType(Placeholder)), const Offset(800.0, 600.0)); expect(tester.getBottomRight(find.byType(Placeholder)), const Offset(800.0, 600.0));
}); });
testWidgets('default positioning', (WidgetTester tester) async { testWidgetsWithLeakTracking('default positioning', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
builder: (BuildContext context, Widget? child) { builder: (BuildContext context, Widget? child) {
...@@ -1491,7 +1506,7 @@ void main() { ...@@ -1491,7 +1506,7 @@ void main() {
}); });
}); });
testWidgets('Hovering over Cupertino alert dialog action updates cursor to clickable on Web', (WidgetTester tester) async { testWidgetsWithLeakTracking('Hovering over Cupertino alert dialog action updates cursor to clickable on Web', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
createAppWithButtonThatLaunchesDialog( createAppWithButtonThatLaunchesDialog(
dialogBuilder: (BuildContext context) { dialogBuilder: (BuildContext context) {
......
...@@ -8,6 +8,7 @@ library; ...@@ -8,6 +8,7 @@ library;
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.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() {
final Offset basicOffset = Offset(CupertinoMagnifier.kDefaultSize.width / 2, final Offset basicOffset = Offset(CupertinoMagnifier.kDefaultSize.width / 2,
...@@ -48,7 +49,7 @@ void main() { ...@@ -48,7 +49,7 @@ void main() {
animatedPositioned.left ?? 0, animatedPositioned.top ?? 0); animatedPositioned.left ?? 0, animatedPositioned.top ?? 0);
} }
testWidgets('should be at gesture position if does not violate any positioning rules', (WidgetTester tester) async { testWidgetsWithLeakTracking('should be at gesture position if does not violate any positioning rules', (WidgetTester tester) async {
final Key fakeTextFieldKey = UniqueKey(); final Key fakeTextFieldKey = UniqueKey();
final Key outerKey = UniqueKey(); final Key outerKey = UniqueKey();
...@@ -87,6 +88,7 @@ void main() { ...@@ -87,6 +88,7 @@ void main() {
globalGesturePosition: fakeTextFieldRect.center, globalGesturePosition: fakeTextFieldRect.center,
), ),
); );
addTearDown(magnifier.dispose);
await showCupertinoMagnifier(context, tester, magnifier); await showCupertinoMagnifier(context, tester, magnifier);
...@@ -98,7 +100,7 @@ void main() { ...@@ -98,7 +100,7 @@ void main() {
); );
}); });
testWidgets('should never horizontally be outside of Screen Padding', (WidgetTester tester) async { testWidgetsWithLeakTracking('should never horizontally be outside of Screen Padding', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const MaterialApp( const MaterialApp(
color: Color.fromARGB(7, 0, 129, 90), color: Color.fromARGB(7, 0, 129, 90),
...@@ -108,19 +110,21 @@ void main() { ...@@ -108,19 +110,21 @@ void main() {
final BuildContext context = tester.firstElement(find.byType(Placeholder)); final BuildContext context = tester.firstElement(find.byType(Placeholder));
final ValueNotifier<MagnifierInfo> magnifierInfo = ValueNotifier<MagnifierInfo>(
MagnifierInfo(
currentLineBoundaries: reasonableTextField,
fieldBounds: reasonableTextField,
caretRect: reasonableTextField,
// The tap position is far out of the right side of the app.
globalGesturePosition:
Offset(MediaQuery.sizeOf(context).width + 100, 0),
),
);
addTearDown(magnifierInfo.dispose);
await showCupertinoMagnifier( await showCupertinoMagnifier(
context, context,
tester, tester,
ValueNotifier<MagnifierInfo>( magnifierInfo,
MagnifierInfo(
currentLineBoundaries: reasonableTextField,
fieldBounds: reasonableTextField,
caretRect: reasonableTextField,
// The tap position is far out of the right side of the app.
globalGesturePosition:
Offset(MediaQuery.sizeOf(context).width + 100, 0),
),
),
); );
// Should be less than the right edge, since we have padding. // Should be less than the right edge, since we have padding.
...@@ -128,7 +132,7 @@ void main() { ...@@ -128,7 +132,7 @@ void main() {
lessThan(MediaQuery.sizeOf(context).width)); lessThan(MediaQuery.sizeOf(context).width));
}); });
testWidgets('should have some vertical drag', (WidgetTester tester) async { testWidgetsWithLeakTracking('should have some vertical drag', (WidgetTester tester) async {
final double dragPositionBelowTextField = reasonableTextField.center.dy + 30; final double dragPositionBelowTextField = reasonableTextField.center.dy + 30;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -141,20 +145,23 @@ void main() { ...@@ -141,20 +145,23 @@ void main() {
final BuildContext context = final BuildContext context =
tester.firstElement(find.byType(Placeholder)); tester.firstElement(find.byType(Placeholder));
final ValueNotifier<MagnifierInfo> magnifierInfo =
ValueNotifier<MagnifierInfo>(
MagnifierInfo(
currentLineBoundaries: reasonableTextField,
fieldBounds: reasonableTextField,
caretRect: reasonableTextField,
// The tap position is dragBelow units below the text field.
globalGesturePosition: Offset(
MediaQuery.sizeOf(context).width / 2,
dragPositionBelowTextField),
),
);
addTearDown(magnifierInfo.dispose);
await showCupertinoMagnifier( await showCupertinoMagnifier(
context, context,
tester, tester,
ValueNotifier<MagnifierInfo>( magnifierInfo,
MagnifierInfo(
currentLineBoundaries: reasonableTextField,
fieldBounds: reasonableTextField,
caretRect: reasonableTextField,
// The tap position is dragBelow units below the text field.
globalGesturePosition: Offset(
MediaQuery.sizeOf(context).width / 2,
dragPositionBelowTextField),
),
),
); );
// The magnifier Y should be greater than the text field, since we "dragged" it down. // The magnifier Y should be greater than the text field, since we "dragged" it down.
...@@ -166,7 +173,7 @@ void main() { ...@@ -166,7 +173,7 @@ void main() {
}); });
group('status', () { group('status', () {
testWidgets('should hide if gesture is far below the text field', (WidgetTester tester) async { testWidgetsWithLeakTracking('should hide if gesture is far below the text field', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const MaterialApp( const MaterialApp(
color: Color.fromARGB(7, 0, 129, 90), color: Color.fromARGB(7, 0, 129, 90),
...@@ -177,7 +184,7 @@ void main() { ...@@ -177,7 +184,7 @@ void main() {
final BuildContext context = final BuildContext context =
tester.firstElement(find.byType(Placeholder)); tester.firstElement(find.byType(Placeholder));
final ValueNotifier<MagnifierInfo> magnifierinfo = final ValueNotifier<MagnifierInfo> magnifierInfo =
ValueNotifier<MagnifierInfo>( ValueNotifier<MagnifierInfo>(
MagnifierInfo( MagnifierInfo(
currentLineBoundaries: reasonableTextField, currentLineBoundaries: reasonableTextField,
...@@ -188,16 +195,17 @@ void main() { ...@@ -188,16 +195,17 @@ void main() {
MediaQuery.sizeOf(context).width / 2, reasonableTextField.top), MediaQuery.sizeOf(context).width / 2, reasonableTextField.top),
), ),
); );
addTearDown(magnifierInfo.dispose);
// Show the magnifier initially, so that we get it in a not hidden state. // Show the magnifier initially, so that we get it in a not hidden state.
await showCupertinoMagnifier(context, tester, magnifierinfo); await showCupertinoMagnifier(context, tester, magnifierInfo);
// Move the gesture to one that should hide it. // Move the gesture to one that should hide it.
magnifierinfo.value = MagnifierInfo( magnifierInfo.value = MagnifierInfo(
currentLineBoundaries: reasonableTextField, currentLineBoundaries: reasonableTextField,
fieldBounds: reasonableTextField, fieldBounds: reasonableTextField,
caretRect: reasonableTextField, caretRect: reasonableTextField,
globalGesturePosition: magnifierinfo.value.globalGesturePosition + const Offset(0, 100), globalGesturePosition: magnifierInfo.value.globalGesturePosition + const Offset(0, 100),
); );
await tester.pumpAndSettle(); await tester.pumpAndSettle();
...@@ -205,7 +213,7 @@ void main() { ...@@ -205,7 +213,7 @@ void main() {
expect(magnifierController.overlayEntry, isNotNull); expect(magnifierController.overlayEntry, isNotNull);
}); });
testWidgets('should re-show if gesture moves back up', testWidgetsWithLeakTracking('should re-show if gesture moves back up',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const MaterialApp( const MaterialApp(
...@@ -227,6 +235,7 @@ void main() { ...@@ -227,6 +235,7 @@ void main() {
globalGesturePosition: Offset(MediaQuery.sizeOf(context).width / 2, reasonableTextField.top), globalGesturePosition: Offset(MediaQuery.sizeOf(context).width / 2, reasonableTextField.top),
), ),
); );
addTearDown(magnifierInfo.dispose);
// Show the magnifier initially, so that we get it in a not hidden state. // Show the magnifier initially, so that we get it in a not hidden state.
await showCupertinoMagnifier(context, tester, magnifierInfo); await showCupertinoMagnifier(context, tester, magnifierInfo);
......
...@@ -11,6 +11,7 @@ import 'package:flutter/cupertino.dart'; ...@@ -11,6 +11,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/scheduler.dart'; import 'package:flutter/scheduler.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';
Future<void> startTransitionBetween( Future<void> startTransitionBetween(
WidgetTester tester, { WidgetTester tester, {
...@@ -131,7 +132,7 @@ void checkOpacity(WidgetTester tester, Finder finder, double opacity) { ...@@ -131,7 +132,7 @@ void checkOpacity(WidgetTester tester, Finder finder, double opacity) {
} }
void main() { void main() {
testWidgets('Bottom middle moves between middle and back label', (WidgetTester tester) async { testWidgetsWithLeakTracking('Bottom middle moves between middle and back label', (WidgetTester tester) async {
await startTransitionBetween(tester, fromTitle: 'Page 1'); await startTransitionBetween(tester, fromTitle: 'Page 1');
// Be mid-transition. // Be mid-transition.
...@@ -159,7 +160,7 @@ void main() { ...@@ -159,7 +160,7 @@ void main() {
); );
}); });
testWidgets('Bottom middle moves between middle and back label RTL', (WidgetTester tester) async { testWidgetsWithLeakTracking('Bottom middle moves between middle and back label RTL', (WidgetTester tester) async {
await startTransitionBetween( await startTransitionBetween(
tester, tester,
fromTitle: 'Page 1', fromTitle: 'Page 1',
...@@ -186,7 +187,7 @@ void main() { ...@@ -186,7 +187,7 @@ void main() {
); );
}); });
testWidgets('Bottom middle never changes size during the animation', (WidgetTester tester) async { testWidgetsWithLeakTracking('Bottom middle never changes size during the animation', (WidgetTester tester) async {
await tester.binding.setSurfaceSize(const Size(1080.0 / 2.75, 600)); await tester.binding.setSurfaceSize(const Size(1080.0 / 2.75, 600));
addTearDown(() async { addTearDown(() async {
await tester.binding.setSurfaceSize(const Size(800.0, 600.0)); await tester.binding.setSurfaceSize(const Size(800.0, 600.0));
...@@ -207,7 +208,7 @@ void main() { ...@@ -207,7 +208,7 @@ void main() {
} }
}); });
testWidgets('Bottom middle and top back label transitions their font', (WidgetTester tester) async { testWidgetsWithLeakTracking('Bottom middle and top back label transitions their font', (WidgetTester tester) async {
await startTransitionBetween(tester, fromTitle: 'Page 1'); await startTransitionBetween(tester, fromTitle: 'Page 1');
// Be mid-transition. // Be mid-transition.
...@@ -251,7 +252,7 @@ void main() { ...@@ -251,7 +252,7 @@ void main() {
checkOpacity(tester, flying(tester, find.text('Page 1')).last, 0.5292819738388062); checkOpacity(tester, flying(tester, find.text('Page 1')).last, 0.5292819738388062);
}); });
testWidgets('Font transitions respect themes', (WidgetTester tester) async { testWidgetsWithLeakTracking('Font transitions respect themes', (WidgetTester tester) async {
await startTransitionBetween( await startTransitionBetween(
tester, tester,
fromTitle: 'Page 1', fromTitle: 'Page 1',
...@@ -299,7 +300,7 @@ void main() { ...@@ -299,7 +300,7 @@ void main() {
checkOpacity(tester, flying(tester, find.text('Page 1')).last, 0.5292819738388062); checkOpacity(tester, flying(tester, find.text('Page 1')).last, 0.5292819738388062);
}); });
testWidgets('Fullscreen dialogs do not create heroes', (WidgetTester tester) async { testWidgetsWithLeakTracking('Fullscreen dialogs do not create heroes', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const CupertinoApp( const CupertinoApp(
home: Placeholder(), home: Placeholder(),
...@@ -333,7 +334,7 @@ void main() { ...@@ -333,7 +334,7 @@ void main() {
expect(() => flying(tester, find.text('Page 2')), throwsAssertionError); expect(() => flying(tester, find.text('Page 2')), throwsAssertionError);
}); });
testWidgets('Turning off transition works', (WidgetTester tester) async { testWidgetsWithLeakTracking('Turning off transition works', (WidgetTester tester) async {
await startTransitionBetween( await startTransitionBetween(
tester, tester,
from: const CupertinoNavigationBar( from: const CupertinoNavigationBar(
...@@ -357,7 +358,7 @@ void main() { ...@@ -357,7 +358,7 @@ void main() {
expect(() => flying(tester, find.text('Page 2')), throwsAssertionError); expect(() => flying(tester, find.text('Page 2')), throwsAssertionError);
}); });
testWidgets('Popping mid-transition is symmetrical', (WidgetTester tester) async { testWidgetsWithLeakTracking('Popping mid-transition is symmetrical', (WidgetTester tester) async {
await startTransitionBetween(tester, fromTitle: 'Page 1'); await startTransitionBetween(tester, fromTitle: 'Page 1');
// Be mid-transition. // Be mid-transition.
...@@ -405,7 +406,7 @@ void main() { ...@@ -405,7 +406,7 @@ void main() {
checkColorAndPositionAt50ms(); checkColorAndPositionAt50ms();
}); });
testWidgets('Popping mid-transition is symmetrical RTL', (WidgetTester tester) async { testWidgetsWithLeakTracking('Popping mid-transition is symmetrical RTL', (WidgetTester tester) async {
await startTransitionBetween( await startTransitionBetween(
tester, tester,
fromTitle: 'Page 1', fromTitle: 'Page 1',
...@@ -456,7 +457,7 @@ void main() { ...@@ -456,7 +457,7 @@ void main() {
checkColorAndPositionAt50ms(); checkColorAndPositionAt50ms();
}); });
testWidgets('There should be no global keys in the hero flight', (WidgetTester tester) async { testWidgetsWithLeakTracking('There should be no global keys in the hero flight', (WidgetTester tester) async {
await startTransitionBetween(tester, fromTitle: 'Page 1'); await startTransitionBetween(tester, fromTitle: 'Page 1');
// Be mid-transition. // Be mid-transition.
...@@ -471,7 +472,7 @@ void main() { ...@@ -471,7 +472,7 @@ void main() {
); );
}); });
testWidgets('DartPerformanceMode is latency mid-animation', (WidgetTester tester) async { testWidgetsWithLeakTracking('DartPerformanceMode is latency mid-animation', (WidgetTester tester) async {
DartPerformanceMode? mode; DartPerformanceMode? mode;
// before the animation starts, no requests are active. // before the animation starts, no requests are active.
...@@ -491,7 +492,7 @@ void main() { ...@@ -491,7 +492,7 @@ void main() {
expect(mode, isNull); expect(mode, isNull);
}); });
testWidgets('Multiple nav bars tags do not conflict if in different navigators', (WidgetTester tester) async { testWidgetsWithLeakTracking('Multiple nav bars tags do not conflict if in different navigators', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: CupertinoTabScaffold( home: CupertinoTabScaffold(
...@@ -566,7 +567,7 @@ void main() { ...@@ -566,7 +567,7 @@ void main() {
expect(find.text('Tab 1 Page 2', skipOffstage: false), findsNothing); expect(find.text('Tab 1 Page 2', skipOffstage: false), findsNothing);
}); });
testWidgets('Transition box grows to large title size', (WidgetTester tester) async { testWidgetsWithLeakTracking('Transition box grows to large title size', (WidgetTester tester) async {
await startTransitionBetween( await startTransitionBetween(
tester, tester,
fromTitle: 'Page 1', fromTitle: 'Page 1',
...@@ -590,7 +591,7 @@ void main() { ...@@ -590,7 +591,7 @@ void main() {
checkBackgroundBoxHeight(tester, 84.33018499612808); checkBackgroundBoxHeight(tester, 84.33018499612808);
}); });
testWidgets('Large transition box shrinks to standard nav bar size', (WidgetTester tester) async { testWidgetsWithLeakTracking('Large transition box shrinks to standard nav bar size', (WidgetTester tester) async {
await startTransitionBetween( await startTransitionBetween(
tester, tester,
from: const CupertinoSliverNavigationBar(), from: const CupertinoSliverNavigationBar(),
...@@ -614,7 +615,7 @@ void main() { ...@@ -614,7 +615,7 @@ void main() {
checkBackgroundBoxHeight(tester, 55.66981500387192); checkBackgroundBoxHeight(tester, 55.66981500387192);
}); });
testWidgets('Hero flight removed at the end of page transition', (WidgetTester tester) async { testWidgetsWithLeakTracking('Hero flight removed at the end of page transition', (WidgetTester tester) async {
await startTransitionBetween(tester, fromTitle: 'Page 1'); await startTransitionBetween(tester, fromTitle: 'Page 1');
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
...@@ -629,7 +630,7 @@ void main() { ...@@ -629,7 +630,7 @@ void main() {
expect(() => flying(tester, find.text('Page 1')), throwsAssertionError); expect(() => flying(tester, find.text('Page 1')), throwsAssertionError);
}); });
testWidgets('Exact widget is reused to build inside the transition', (WidgetTester tester) async { testWidgetsWithLeakTracking('Exact widget is reused to build inside the transition', (WidgetTester tester) async {
const Widget userMiddle = Placeholder(); const Widget userMiddle = Placeholder();
await startTransitionBetween( await startTransitionBetween(
tester, tester,
...@@ -645,7 +646,7 @@ void main() { ...@@ -645,7 +646,7 @@ void main() {
expect(flying(tester, find.byWidget(userMiddle)), findsOneWidget); expect(flying(tester, find.byWidget(userMiddle)), findsOneWidget);
}); });
testWidgets('Middle is not shown if alwaysShowMiddle is false and the nav bar is expanded', (WidgetTester tester) async { testWidgetsWithLeakTracking('Middle is not shown if alwaysShowMiddle is false and the nav bar is expanded', (WidgetTester tester) async {
const Widget userMiddle = Placeholder(); const Widget userMiddle = Placeholder();
await startTransitionBetween( await startTransitionBetween(
tester, tester,
...@@ -662,9 +663,10 @@ void main() { ...@@ -662,9 +663,10 @@ void main() {
expect(flying(tester, find.byWidget(userMiddle)), findsNothing); expect(flying(tester, find.byWidget(userMiddle)), findsNothing);
}); });
testWidgets('Middle is shown if alwaysShowMiddle is false but the nav bar is collapsed', (WidgetTester tester) async { testWidgetsWithLeakTracking('Middle is shown if alwaysShowMiddle is false but the nav bar is collapsed', (WidgetTester tester) async {
const Widget userMiddle = Placeholder(); const Widget userMiddle = Placeholder();
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -710,7 +712,7 @@ void main() { ...@@ -710,7 +712,7 @@ void main() {
expect(flying(tester, find.byWidget(userMiddle)), findsOneWidget); expect(flying(tester, find.byWidget(userMiddle)), findsOneWidget);
}); });
testWidgets('First appearance of back chevron fades in from the right', (WidgetTester tester) async { testWidgetsWithLeakTracking('First appearance of back chevron fades in from the right', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: scaffoldForNavBar(null), home: scaffoldForNavBar(null),
...@@ -749,7 +751,7 @@ void main() { ...@@ -749,7 +751,7 @@ void main() {
)); ));
}); });
testWidgets('First appearance of back chevron fades in from the left in RTL', (WidgetTester tester) async { testWidgetsWithLeakTracking('First appearance of back chevron fades in from the left in RTL', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
builder: (BuildContext context, Widget? navigator) { builder: (BuildContext context, Widget? navigator) {
...@@ -801,7 +803,7 @@ void main() { ...@@ -801,7 +803,7 @@ void main() {
); );
}); });
testWidgets('Back chevron fades out and in when both pages have it', (WidgetTester tester) async { testWidgetsWithLeakTracking('Back chevron fades out and in when both pages have it', (WidgetTester tester) async {
await startTransitionBetween(tester, fromTitle: 'Page 1'); await startTransitionBetween(tester, fromTitle: 'Page 1');
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
...@@ -827,7 +829,7 @@ void main() { ...@@ -827,7 +829,7 @@ void main() {
expect(tester.getTopLeft(backChevrons.last), const Offset(14.0, 7.0)); expect(tester.getTopLeft(backChevrons.last), const Offset(14.0, 7.0));
}); });
testWidgets('Bottom middle just fades if top page has a custom leading', (WidgetTester tester) async { testWidgetsWithLeakTracking('Bottom middle just fades if top page has a custom leading', (WidgetTester tester) async {
await startTransitionBetween( await startTransitionBetween(
tester, tester,
fromTitle: 'Page 1', fromTitle: 'Page 1',
...@@ -858,7 +860,7 @@ void main() { ...@@ -858,7 +860,7 @@ void main() {
); );
}); });
testWidgets('Bottom leading fades in place', (WidgetTester tester) async { testWidgetsWithLeakTracking('Bottom leading fades in place', (WidgetTester tester) async {
await startTransitionBetween( await startTransitionBetween(
tester, tester,
from: const CupertinoSliverNavigationBar(leading: Text('custom')), from: const CupertinoSliverNavigationBar(leading: Text('custom')),
...@@ -884,7 +886,7 @@ void main() { ...@@ -884,7 +886,7 @@ void main() {
); );
}); });
testWidgets('Bottom trailing fades in place', (WidgetTester tester) async { testWidgetsWithLeakTracking('Bottom trailing fades in place', (WidgetTester tester) async {
await startTransitionBetween( await startTransitionBetween(
tester, tester,
from: const CupertinoSliverNavigationBar(trailing: Text('custom')), from: const CupertinoSliverNavigationBar(trailing: Text('custom')),
...@@ -916,7 +918,7 @@ void main() { ...@@ -916,7 +918,7 @@ void main() {
); );
}); });
testWidgets('Bottom back label fades and slides to the left', (WidgetTester tester) async { testWidgetsWithLeakTracking('Bottom back label fades and slides to the left', (WidgetTester tester) async {
await startTransitionBetween( await startTransitionBetween(
tester, tester,
fromTitle: 'Page 1', fromTitle: 'Page 1',
...@@ -958,7 +960,7 @@ void main() { ...@@ -958,7 +960,7 @@ void main() {
); );
}); });
testWidgets('Bottom back label fades and slides to the right in RTL', (WidgetTester tester) async { testWidgetsWithLeakTracking('Bottom back label fades and slides to the right in RTL', (WidgetTester tester) async {
await startTransitionBetween( await startTransitionBetween(
tester, tester,
fromTitle: 'Page 1', fromTitle: 'Page 1',
...@@ -1002,7 +1004,7 @@ void main() { ...@@ -1002,7 +1004,7 @@ void main() {
); );
}); });
testWidgets('Bottom large title moves to top back label', (WidgetTester tester) async { testWidgetsWithLeakTracking('Bottom large title moves to top back label', (WidgetTester tester) async {
await startTransitionBetween( await startTransitionBetween(
tester, tester,
from: const CupertinoSliverNavigationBar(), from: const CupertinoSliverNavigationBar(),
...@@ -1054,7 +1056,7 @@ void main() { ...@@ -1054,7 +1056,7 @@ void main() {
); );
}); });
testWidgets('Long title turns into the word back mid transition', (WidgetTester tester) async { testWidgetsWithLeakTracking('Long title turns into the word back mid transition', (WidgetTester tester) async {
await startTransitionBetween( await startTransitionBetween(
tester, tester,
from: const CupertinoSliverNavigationBar(), from: const CupertinoSliverNavigationBar(),
...@@ -1104,7 +1106,7 @@ void main() { ...@@ -1104,7 +1106,7 @@ void main() {
); );
}); });
testWidgets('Bottom large title and top back label transitions their font', (WidgetTester tester) async { testWidgetsWithLeakTracking('Bottom large title and top back label transitions their font', (WidgetTester tester) async {
await startTransitionBetween( await startTransitionBetween(
tester, tester,
from: const CupertinoSliverNavigationBar(), from: const CupertinoSliverNavigationBar(),
...@@ -1143,7 +1145,7 @@ void main() { ...@@ -1143,7 +1145,7 @@ void main() {
expect(topBackLabel.text.style!.letterSpacing, moreOrLessEquals(-0.2259759941697121)); expect(topBackLabel.text.style!.letterSpacing, moreOrLessEquals(-0.2259759941697121));
}); });
testWidgets('Top middle fades in and slides in from the right', (WidgetTester tester) async { testWidgetsWithLeakTracking('Top middle fades in and slides in from the right', (WidgetTester tester) async {
await startTransitionBetween( await startTransitionBetween(
tester, tester,
toTitle: 'Page 2', toTitle: 'Page 2',
...@@ -1174,7 +1176,7 @@ void main() { ...@@ -1174,7 +1176,7 @@ void main() {
); );
}); });
testWidgets('Top middle never changes size during the animation', (WidgetTester tester) async { testWidgetsWithLeakTracking('Top middle never changes size during the animation', (WidgetTester tester) async {
await tester.binding.setSurfaceSize(const Size(1080.0 / 2.75, 600)); await tester.binding.setSurfaceSize(const Size(1080.0 / 2.75, 600));
addTearDown(() async { addTearDown(() async {
await tester.binding.setSurfaceSize(const Size(800.0, 600.0)); await tester.binding.setSurfaceSize(const Size(800.0, 600.0));
...@@ -1198,7 +1200,7 @@ void main() { ...@@ -1198,7 +1200,7 @@ void main() {
} }
}); });
testWidgets('Top middle fades in and slides in from the left in RTL', (WidgetTester tester) async { testWidgetsWithLeakTracking('Top middle fades in and slides in from the left in RTL', (WidgetTester tester) async {
await startTransitionBetween( await startTransitionBetween(
tester, tester,
toTitle: 'Page 2', toTitle: 'Page 2',
...@@ -1230,7 +1232,7 @@ void main() { ...@@ -1230,7 +1232,7 @@ void main() {
); );
}); });
testWidgets('Top large title fades in and slides in from the right', (WidgetTester tester) async { testWidgetsWithLeakTracking('Top large title fades in and slides in from the right', (WidgetTester tester) async {
await startTransitionBetween( await startTransitionBetween(
tester, tester,
to: const CupertinoSliverNavigationBar(), to: const CupertinoSliverNavigationBar(),
...@@ -1256,7 +1258,7 @@ void main() { ...@@ -1256,7 +1258,7 @@ void main() {
); );
}); });
testWidgets('Top large title fades in and slides in from the left in RTL', (WidgetTester tester) async { testWidgetsWithLeakTracking('Top large title fades in and slides in from the left in RTL', (WidgetTester tester) async {
await startTransitionBetween( await startTransitionBetween(
tester, tester,
to: const CupertinoSliverNavigationBar(), to: const CupertinoSliverNavigationBar(),
...@@ -1283,7 +1285,7 @@ void main() { ...@@ -1283,7 +1285,7 @@ void main() {
); );
}); });
testWidgets('Components are not unnecessarily rebuilt during transitions', (WidgetTester tester) async { testWidgetsWithLeakTracking('Components are not unnecessarily rebuilt during transitions', (WidgetTester tester) async {
int bottomBuildTimes = 0; int bottomBuildTimes = 0;
int topBuildTimes = 0; int topBuildTimes = 0;
await startTransitionBetween( await startTransitionBetween(
...@@ -1328,7 +1330,7 @@ void main() { ...@@ -1328,7 +1330,7 @@ void main() {
expect(topBuildTimes, 3); expect(topBuildTimes, 3);
}); });
testWidgets('Back swipe gesture transitions', (WidgetTester tester) async { testWidgetsWithLeakTracking('Back swipe gesture transitions', (WidgetTester tester) async {
await startTransitionBetween( await startTransitionBetween(
tester, tester,
fromTitle: 'Page 1', fromTitle: 'Page 1',
...@@ -1391,7 +1393,7 @@ void main() { ...@@ -1391,7 +1393,7 @@ void main() {
expect(find.text('Page 1'), findsOneWidget); expect(find.text('Page 1'), findsOneWidget);
}); });
testWidgets('textScaleFactor is set to 1.0 on transition', (WidgetTester tester) async { testWidgetsWithLeakTracking('textScaleFactor is set to 1.0 on transition', (WidgetTester tester) async {
await startTransitionBetween(tester, fromTitle: 'Page 1', textScale: 99); await startTransitionBetween(tester, fromTitle: 'Page 1', textScale: 99);
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
...@@ -1399,7 +1401,7 @@ void main() { ...@@ -1399,7 +1401,7 @@ void main() {
expect(tester.firstWidget<RichText>(flying(tester, find.byType(RichText))).textScaleFactor, 1); expect(tester.firstWidget<RichText>(flying(tester, find.byType(RichText))).textScaleFactor, 1);
}); });
testWidgets('Back swipe gesture cancels properly with transition', (WidgetTester tester) async { testWidgetsWithLeakTracking('Back swipe gesture cancels properly with transition', (WidgetTester tester) async {
await startTransitionBetween( await startTransitionBetween(
tester, tester,
fromTitle: 'Page 1', fromTitle: 'Page 1',
......
...@@ -7,11 +7,12 @@ import 'package:flutter/foundation.dart'; ...@@ -7,11 +7,12 @@ import 'package:flutter/foundation.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';
void main() { void main() {
testWidgets('Radio control test', (WidgetTester tester) async { testWidgetsWithLeakTracking('Radio control test', (WidgetTester tester) async {
final Key key = UniqueKey(); final Key key = UniqueKey();
final List<int?> log = <int?>[]; final List<int?> log = <int?>[];
...@@ -63,7 +64,7 @@ void main() { ...@@ -63,7 +64,7 @@ void main() {
expect(log, isEmpty); expect(log, isEmpty);
}); });
testWidgets('Radio can be toggled when toggleable is set', (WidgetTester tester) async { testWidgetsWithLeakTracking('Radio 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?>[];
...@@ -118,7 +119,7 @@ void main() { ...@@ -118,7 +119,7 @@ void main() {
expect(log, equals(<int>[1])); expect(log, equals(<int>[1]));
}); });
testWidgets('Radio selected semantics - platform adaptive', (WidgetTester tester) async { testWidgetsWithLeakTracking('Radio selected semantics - platform adaptive', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(CupertinoApp( await tester.pumpWidget(CupertinoApp(
...@@ -153,7 +154,7 @@ void main() { ...@@ -153,7 +154,7 @@ void main() {
semantics.dispose(); semantics.dispose();
}, variant: TargetPlatformVariant.all()); }, variant: TargetPlatformVariant.all());
testWidgets('Radio semantics', (WidgetTester tester) async { testWidgetsWithLeakTracking('Radio semantics', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(CupertinoApp( await tester.pumpWidget(CupertinoApp(
...@@ -241,7 +242,7 @@ void main() { ...@@ -241,7 +242,7 @@ void main() {
semantics.dispose(); semantics.dispose();
}); });
testWidgets('has semantic events', (WidgetTester tester) async { testWidgetsWithLeakTracking('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;
...@@ -278,13 +279,14 @@ void main() { ...@@ -278,13 +279,14 @@ void main() {
tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(SystemChannels.accessibility, null); tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler<dynamic>(SystemChannels.accessibility, null);
}); });
testWidgets('Radio can be controlled by keyboard shortcuts', (WidgetTester tester) async { testWidgetsWithLeakTracking('Radio can be controlled by keyboard shortcuts', (WidgetTester tester) async {
tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional; tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
int? groupValue = 1; int? groupValue = 1;
const Key radioKey0 = Key('radio0'); const Key radioKey0 = Key('radio0');
const Key radioKey1 = Key('radio1'); const Key radioKey1 = Key('radio1');
const Key radioKey2 = Key('radio2'); const Key radioKey2 = Key('radio2');
final FocusNode focusNode2 = FocusNode(debugLabel: 'radio2'); final FocusNode focusNode2 = FocusNode(debugLabel: 'radio2');
addTearDown(focusNode2.dispose);
Widget buildApp({bool enabled = true}) { Widget buildApp({bool enabled = true}) {
return CupertinoApp( return CupertinoApp(
home: Center( home: Center(
...@@ -350,7 +352,7 @@ void main() { ...@@ -350,7 +352,7 @@ void main() {
expect(groupValue, equals(2)); expect(groupValue, equals(2));
}); });
testWidgets('Show a checkmark when useCheckmarkStyle is true', (WidgetTester tester) async { testWidgetsWithLeakTracking('Show a checkmark when useCheckmarkStyle is true', (WidgetTester tester) async {
await tester.pumpWidget(CupertinoApp( await tester.pumpWidget(CupertinoApp(
home: Center( home: Center(
child: CupertinoRadio<int>( child: CupertinoRadio<int>(
...@@ -405,7 +407,7 @@ void main() { ...@@ -405,7 +407,7 @@ void main() {
); );
}); });
testWidgets('Do not crash when widget disappears while pointer is down', (WidgetTester tester) async { testWidgetsWithLeakTracking('Do not crash when widget disappears while pointer is down', (WidgetTester tester) async {
final Key key = UniqueKey(); final Key key = UniqueKey();
Widget buildRadio(bool show) { Widget buildRadio(bool show) {
......
...@@ -8,6 +8,7 @@ import 'package:flutter/cupertino.dart'; ...@@ -8,6 +8,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.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';
const CupertinoDynamicColor _kScrollbarColor = CupertinoDynamicColor.withBrightness( const CupertinoDynamicColor _kScrollbarColor = CupertinoDynamicColor.withBrightness(
color: Color(0x59000000), color: Color(0x59000000),
...@@ -20,7 +21,7 @@ void main() { ...@@ -20,7 +21,7 @@ void main() {
const Duration kScrollbarResizeDuration = Duration(milliseconds: 100); const Duration kScrollbarResizeDuration = Duration(milliseconds: 100);
const Duration kLongPressDuration = Duration(milliseconds: 100); const Duration kLongPressDuration = Duration(milliseconds: 100);
testWidgets('Scrollbar never goes away until finger lift', (WidgetTester tester) async { testWidgetsWithLeakTracking('Scrollbar never goes away until finger lift', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const Directionality( const Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -58,7 +59,7 @@ void main() { ...@@ -58,7 +59,7 @@ void main() {
)); ));
}); });
testWidgets('Scrollbar dark mode', (WidgetTester tester) async { testWidgetsWithLeakTracking('Scrollbar dark mode', (WidgetTester tester) async {
Brightness brightness = Brightness.light; Brightness brightness = Brightness.light;
late StateSetter setState; late StateSetter setState;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -95,8 +96,9 @@ void main() { ...@@ -95,8 +96,9 @@ void main() {
)); ));
}); });
testWidgets('Scrollbar thumb can be dragged with long press', (WidgetTester tester) async { testWidgetsWithLeakTracking('Scrollbar thumb can be dragged with long press', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -167,8 +169,9 @@ void main() { ...@@ -167,8 +169,9 @@ void main() {
await tester.pump(kScrollbarFadeDuration); await tester.pump(kScrollbarFadeDuration);
}); });
testWidgets('Scrollbar thumb can be dragged with long press - reverse', (WidgetTester tester) async { testWidgetsWithLeakTracking('Scrollbar thumb can be dragged with long press - reverse', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -242,7 +245,7 @@ void main() { ...@@ -242,7 +245,7 @@ void main() {
await tester.pump(kScrollbarFadeDuration); await tester.pump(kScrollbarFadeDuration);
}); });
testWidgets('Scrollbar changes thickness and radius when dragged', (WidgetTester tester) async { testWidgetsWithLeakTracking('Scrollbar changes thickness and radius when dragged', (WidgetTester tester) async {
const double thickness = 20; const double thickness = 20;
const double thicknessWhileDragging = 40; const double thicknessWhileDragging = 40;
const double radius = 10; const double radius = 10;
...@@ -253,6 +256,7 @@ void main() { ...@@ -253,6 +256,7 @@ void main() {
final Size screenSize = tester.view.physicalSize / tester.view.devicePixelRatio; final Size screenSize = tester.view.physicalSize / tester.view.devicePixelRatio;
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -339,7 +343,7 @@ void main() { ...@@ -339,7 +343,7 @@ void main() {
await tester.pump(kScrollbarFadeDuration); await tester.pump(kScrollbarFadeDuration);
}); });
testWidgets('When thumbVisibility is true, must pass a controller or find PrimaryScrollController', (WidgetTester tester) async { testWidgetsWithLeakTracking('When thumbVisibility is true, must pass a controller or find PrimaryScrollController', (WidgetTester tester) async {
Widget viewWithScroll() { Widget viewWithScroll() {
return const Directionality( return const Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -364,8 +368,9 @@ void main() { ...@@ -364,8 +368,9 @@ void main() {
}, },
); );
testWidgets('When thumbVisibility is true, must pass a controller or find PrimaryScrollController that is attached to a scroll view', (WidgetTester tester) async { testWidgetsWithLeakTracking('When thumbVisibility is true, must pass a controller or find PrimaryScrollController that is attached to a scroll view', (WidgetTester tester) async {
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
Widget viewWithScroll() { Widget viewWithScroll() {
return Directionality( return Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -398,7 +403,7 @@ void main() { ...@@ -398,7 +403,7 @@ void main() {
}, },
); );
testWidgets('When thumbVisibility is true, must pass a controller or find PrimaryScrollController', (WidgetTester tester) async { testWidgetsWithLeakTracking('When thumbVisibility is true, must pass a controller or find PrimaryScrollController', (WidgetTester tester) async {
Widget viewWithScroll() { Widget viewWithScroll() {
return const Directionality( return const Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -423,8 +428,9 @@ void main() { ...@@ -423,8 +428,9 @@ void main() {
}, },
); );
testWidgets('When thumbVisibility is true, must pass a controller or find PrimaryScrollController that is attached to a scroll view', (WidgetTester tester) async { testWidgetsWithLeakTracking('When thumbVisibility is true, must pass a controller or find PrimaryScrollController that is attached to a scroll view', (WidgetTester tester) async {
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
Widget viewWithScroll() { Widget viewWithScroll() {
return Directionality( return Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -457,8 +463,9 @@ void main() { ...@@ -457,8 +463,9 @@ void main() {
}, },
); );
testWidgets('On first render with thumbVisibility: true, the thumb shows with PrimaryScrollController', (WidgetTester tester) async { testWidgetsWithLeakTracking('On first render with thumbVisibility: true, the thumb shows with PrimaryScrollController', (WidgetTester tester) async {
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
Widget viewWithScroll() { Widget viewWithScroll() {
return Directionality( return Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -491,8 +498,9 @@ void main() { ...@@ -491,8 +498,9 @@ void main() {
}, },
); );
testWidgets('On first render with thumbVisibility: true, the thumb shows', (WidgetTester tester) async { testWidgetsWithLeakTracking('On first render with thumbVisibility: true, the thumb shows', (WidgetTester tester) async {
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
Widget viewWithScroll() { Widget viewWithScroll() {
return Directionality( return Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -524,8 +532,9 @@ void main() { ...@@ -524,8 +532,9 @@ void main() {
expect(find.byType(CupertinoScrollbar), paints..rrect()); expect(find.byType(CupertinoScrollbar), paints..rrect());
}); });
testWidgets('On first render with thumbVisibility: true, the thumb shows with PrimaryScrollController', (WidgetTester tester) async { testWidgetsWithLeakTracking('On first render with thumbVisibility: true, the thumb shows with PrimaryScrollController', (WidgetTester tester) async {
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
Widget viewWithScroll() { Widget viewWithScroll() {
return Directionality( return Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -558,8 +567,9 @@ void main() { ...@@ -558,8 +567,9 @@ void main() {
}, },
); );
testWidgets('On first render with thumbVisibility: true, the thumb shows', (WidgetTester tester) async { testWidgetsWithLeakTracking('On first render with thumbVisibility: true, the thumb shows', (WidgetTester tester) async {
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
Widget viewWithScroll() { Widget viewWithScroll() {
return Directionality( return Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -591,8 +601,9 @@ void main() { ...@@ -591,8 +601,9 @@ void main() {
expect(find.byType(CupertinoScrollbar), paints..rrect()); expect(find.byType(CupertinoScrollbar), paints..rrect());
}); });
testWidgets('On first render with thumbVisibility: false, the thumb is hidden', (WidgetTester tester) async { testWidgetsWithLeakTracking('On first render with thumbVisibility: false, the thumb is hidden', (WidgetTester tester) async {
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
Widget viewWithScroll() { Widget viewWithScroll() {
return Directionality( return Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -619,8 +630,9 @@ void main() { ...@@ -619,8 +630,9 @@ void main() {
expect(find.byType(CupertinoScrollbar), isNot(paints..rect())); expect(find.byType(CupertinoScrollbar), isNot(paints..rect()));
}); });
testWidgets('With thumbVisibility: true, fling a scroll. While it is still scrolling, set thumbVisibility: false. The thumb should not fade out until the scrolling stops.', (WidgetTester tester) async { testWidgetsWithLeakTracking('With thumbVisibility: true, fling a scroll. While it is still scrolling, set thumbVisibility: false. The thumb should not fade out until the scrolling stops.', (WidgetTester tester) async {
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
bool thumbVisibility = true; bool thumbVisibility = true;
Widget viewWithScroll() { Widget viewWithScroll() {
return StatefulBuilder( return StatefulBuilder(
...@@ -676,10 +688,11 @@ void main() { ...@@ -676,10 +688,11 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'With thumbVisibility: false, set thumbVisibility: true. The thumb should be always shown directly', 'With thumbVisibility: false, set thumbVisibility: true. The thumb should be always shown directly',
(WidgetTester tester) async { (WidgetTester tester) async {
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
bool thumbVisibility = false; bool thumbVisibility = false;
Widget viewWithScroll() { Widget viewWithScroll() {
return StatefulBuilder( return StatefulBuilder(
...@@ -730,11 +743,12 @@ void main() { ...@@ -730,11 +743,12 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'With thumbVisibility: false, fling a scroll. While it is still scrolling, set thumbVisibility: true. ' 'With thumbVisibility: false, fling a scroll. While it is still scrolling, set thumbVisibility: true. '
'The thumb should not fade even after the scrolling stops', 'The thumb should not fade even after the scrolling stops',
(WidgetTester tester) async { (WidgetTester tester) async {
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
bool thumbVisibility = false; bool thumbVisibility = false;
Widget viewWithScroll() { Widget viewWithScroll() {
return StatefulBuilder( return StatefulBuilder(
...@@ -797,11 +811,12 @@ void main() { ...@@ -797,11 +811,12 @@ void main() {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'Toggling thumbVisibility while not scrolling fades the thumb in/out. ' 'Toggling thumbVisibility while not scrolling fades the thumb in/out. '
'This works even when you have never scrolled at all yet', 'This works even when you have never scrolled at all yet',
(WidgetTester tester) async { (WidgetTester tester) async {
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
bool thumbVisibility = true; bool thumbVisibility = true;
Widget viewWithScroll() { Widget viewWithScroll() {
return StatefulBuilder( return StatefulBuilder(
...@@ -852,8 +867,9 @@ void main() { ...@@ -852,8 +867,9 @@ void main() {
}, },
); );
testWidgets('Scrollbar thumb can be dragged with long press - horizontal axis', (WidgetTester tester) async { testWidgetsWithLeakTracking('Scrollbar thumb can be dragged with long press - horizontal axis', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -926,8 +942,9 @@ void main() { ...@@ -926,8 +942,9 @@ void main() {
await tester.pump(kScrollbarFadeDuration); await tester.pump(kScrollbarFadeDuration);
}); });
testWidgets('Scrollbar thumb can be dragged with long press - horizontal axis, reverse', (WidgetTester tester) async { testWidgetsWithLeakTracking('Scrollbar thumb can be dragged with long press - horizontal axis, reverse', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -1001,8 +1018,9 @@ void main() { ...@@ -1001,8 +1018,9 @@ void main() {
await tester.pump(kScrollbarFadeDuration); await tester.pump(kScrollbarFadeDuration);
}); });
testWidgets('Tapping the track area pages the Scroll View', (WidgetTester tester) async { testWidgetsWithLeakTracking('Tapping the track area pages the Scroll View', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -1060,8 +1078,9 @@ void main() { ...@@ -1060,8 +1078,9 @@ void main() {
); );
}); });
testWidgets('Throw if interactive with the bar when no position attached', (WidgetTester tester) async { testWidgetsWithLeakTracking('Throw if interactive with the bar when no position attached', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
...@@ -1104,9 +1123,11 @@ void main() { ...@@ -1104,9 +1123,11 @@ void main() {
FlutterError.onError = handler; FlutterError.onError = handler;
}); });
testWidgets('Interactive scrollbars should have a valid scroll controller', (WidgetTester tester) async { testWidgetsWithLeakTracking('Interactive scrollbars should have a valid scroll controller', (WidgetTester tester) async {
final ScrollController primaryScrollController = ScrollController(); final ScrollController primaryScrollController = ScrollController();
addTearDown(primaryScrollController.dispose);
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
...@@ -1145,9 +1166,10 @@ void main() { ...@@ -1145,9 +1166,10 @@ void main() {
); );
}); });
testWidgets('Simultaneous dragging and pointer scrolling does not cause a crash', (WidgetTester tester) async { testWidgetsWithLeakTracking('Simultaneous dragging and pointer scrolling does not cause a crash', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/70105 // Regression test for https://github.com/flutter/flutter/issues/70105
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: PrimaryScrollController( home: PrimaryScrollController(
...@@ -1256,8 +1278,9 @@ void main() { ...@@ -1256,8 +1278,9 @@ void main() {
); );
}); });
testWidgets('CupertinoScrollbar scrollOrientation works correctly', (WidgetTester tester) async { testWidgetsWithLeakTracking('CupertinoScrollbar scrollOrientation works correctly', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
......
...@@ -9,6 +9,7 @@ import 'package:flutter/foundation.dart'; ...@@ -9,6 +9,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.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';
...@@ -93,7 +94,7 @@ void main() { ...@@ -93,7 +94,7 @@ void main() {
groupValue = 0; groupValue = 0;
}); });
testWidgets('Need at least 2 children', (WidgetTester tester) async { testWidgetsWithLeakTracking('Need at least 2 children', (WidgetTester tester) async {
groupValue = null; groupValue = null;
await expectLater( await expectLater(
() => tester.pumpWidget( () => tester.pumpWidget(
...@@ -146,7 +147,7 @@ void main() { ...@@ -146,7 +147,7 @@ void main() {
); );
}); });
testWidgets('Padding works', (WidgetTester tester) async { testWidgetsWithLeakTracking('Padding works', (WidgetTester tester) async {
const Key key = Key('Container'); const Key key = Key('Container');
const Map<int, Widget> children = <int, Widget>{ const Map<int, Widget> children = <int, Widget>{
...@@ -223,7 +224,7 @@ void main() { ...@@ -223,7 +224,7 @@ void main() {
await verifyPadding(padding: const EdgeInsets.fromLTRB(1, 3, 5, 7)); await verifyPadding(padding: const EdgeInsets.fromLTRB(1, 3, 5, 7));
}); });
testWidgets('Tap changes toggle state', (WidgetTester tester) async { testWidgetsWithLeakTracking('Tap changes toggle state', (WidgetTester tester) async {
const Map<int, Widget> children = <int, Widget>{ const Map<int, Widget> children = <int, Widget>{
0: Text('Child 1'), 0: Text('Child 1'),
1: Text('Child 2'), 1: Text('Child 2'),
...@@ -255,7 +256,7 @@ void main() { ...@@ -255,7 +256,7 @@ void main() {
expect(groupValue, 1); expect(groupValue, 1);
}); });
testWidgets( testWidgetsWithLeakTracking(
'Segmented controls respect theme', 'Segmented controls respect theme',
(WidgetTester tester) async { (WidgetTester tester) async {
const Map<int, Widget> children = <int, Widget>{ const Map<int, Widget> children = <int, Widget>{
...@@ -293,7 +294,7 @@ void main() { ...@@ -293,7 +294,7 @@ void main() {
}, },
); );
testWidgets('SegmentedControl dark mode', (WidgetTester tester) async { testWidgetsWithLeakTracking('SegmentedControl dark mode', (WidgetTester tester) async {
const Map<int, Widget> children = <int, Widget>{ const Map<int, Widget> children = <int, Widget>{
0: Text('Child 1'), 0: Text('Child 1'),
1: Icon(IconData(1)), 1: Icon(IconData(1)),
...@@ -345,7 +346,7 @@ void main() { ...@@ -345,7 +346,7 @@ void main() {
expect(decorationDark.color!.value, CupertinoColors.systemRed.darkColor.value); expect(decorationDark.color!.value, CupertinoColors.systemRed.darkColor.value);
}); });
testWidgets( testWidgetsWithLeakTracking(
'Children can be non-Text or Icon widgets (in this case, ' 'Children can be non-Text or Icon widgets (in this case, '
'a Container or Placeholder widget)', 'a Container or Placeholder widget)',
(WidgetTester tester) async { (WidgetTester tester) async {
...@@ -369,13 +370,13 @@ void main() { ...@@ -369,13 +370,13 @@ void main() {
}, },
); );
testWidgets('Passed in value is child initially selected', (WidgetTester tester) async { testWidgetsWithLeakTracking('Passed in value is child initially selected', (WidgetTester tester) async {
await tester.pumpWidget(setupSimpleSegmentedControl()); await tester.pumpWidget(setupSimpleSegmentedControl());
expect(getHighlightedIndex(tester), 0); expect(getHighlightedIndex(tester), 0);
}); });
testWidgets('Null input for value results in no child initially selected', (WidgetTester tester) async { testWidgetsWithLeakTracking('Null input for value results in no child initially selected', (WidgetTester tester) async {
const Map<int, Widget> children = <int, Widget>{ const Map<int, Widget> children = <int, Widget>{
0: Text('Child 1'), 0: Text('Child 1'),
1: Text('Child 2'), 1: Text('Child 2'),
...@@ -401,7 +402,7 @@ void main() { ...@@ -401,7 +402,7 @@ void main() {
expect(getHighlightedIndex(tester), null); expect(getHighlightedIndex(tester), null);
}); });
testWidgets('Long press not-selected child interactions', (WidgetTester tester) async { testWidgetsWithLeakTracking('Long press not-selected child interactions', (WidgetTester tester) async {
const Map<int, Widget> children = <int, Widget>{ const Map<int, Widget> children = <int, Widget>{
0: Text('Child 1'), 0: Text('Child 1'),
1: Text('Child 2'), 1: Text('Child 2'),
...@@ -465,7 +466,7 @@ void main() { ...@@ -465,7 +466,7 @@ void main() {
expect(getChildOpacityByName('Child 2'), 0.2); expect(getChildOpacityByName('Child 2'), 0.2);
}); });
testWidgets('Long press does not change the opacity of currently-selected child', (WidgetTester tester) async { testWidgetsWithLeakTracking('Long press does not change the opacity of currently-selected child', (WidgetTester tester) async {
double getChildOpacityByName(String childName) { double getChildOpacityByName(String childName) {
return tester.renderObject<RenderAnimatedOpacity>( return tester.renderObject<RenderAnimatedOpacity>(
find.ancestor(matching: find.byType(AnimatedOpacity), of: find.text(childName)), find.ancestor(matching: find.byType(AnimatedOpacity), of: find.text(childName)),
...@@ -482,7 +483,7 @@ void main() { ...@@ -482,7 +483,7 @@ void main() {
expect(getChildOpacityByName('Child 1'), 1); expect(getChildOpacityByName('Child 1'), 1);
}); });
testWidgets('Height of segmented control is determined by tallest widget', (WidgetTester tester) async { testWidgetsWithLeakTracking('Height of segmented control is determined by tallest widget', (WidgetTester tester) async {
final Map<int, Widget> children = <int, Widget>{ final Map<int, Widget> children = <int, Widget>{
0: Container(constraints: const BoxConstraints.tightFor(height: 100.0)), 0: Container(constraints: const BoxConstraints.tightFor(height: 100.0)),
1: Container(constraints: const BoxConstraints.tightFor(height: 400.0)), 1: Container(constraints: const BoxConstraints.tightFor(height: 400.0)),
...@@ -512,7 +513,7 @@ void main() { ...@@ -512,7 +513,7 @@ void main() {
); );
}); });
testWidgets('Width of each segmented control segment is determined by widest widget', (WidgetTester tester) async { testWidgetsWithLeakTracking('Width of each segmented control segment is determined by widest widget', (WidgetTester tester) async {
final Map<int, Widget> children = <int, Widget>{ final Map<int, Widget> children = <int, Widget>{
0: Container(constraints: const BoxConstraints.tightFor(width: 50.0)), 0: Container(constraints: const BoxConstraints.tightFor(width: 50.0)),
1: Container(constraints: const BoxConstraints.tightFor(width: 100.0)), 1: Container(constraints: const BoxConstraints.tightFor(width: 100.0)),
...@@ -543,7 +544,7 @@ void main() { ...@@ -543,7 +544,7 @@ void main() {
expect(childWidth, 200.0 + 9.25 * 2); expect(childWidth, 200.0 + 9.25 * 2);
}); });
testWidgets('Width is finite in unbounded space', (WidgetTester tester) async { testWidgetsWithLeakTracking('Width is finite in unbounded space', (WidgetTester tester) async {
const Map<int, Widget> children = <int, Widget>{ const Map<int, Widget> children = <int, Widget>{
0: SizedBox(width: 50), 0: SizedBox(width: 50),
1: SizedBox(width: 70), 1: SizedBox(width: 70),
...@@ -576,7 +577,7 @@ void main() { ...@@ -576,7 +577,7 @@ void main() {
); );
}); });
testWidgets('Directionality test - RTL should reverse order of widgets', (WidgetTester tester) async { testWidgetsWithLeakTracking('Directionality test - RTL should reverse order of widgets', (WidgetTester tester) async {
const Map<int, Widget> children = <int, Widget>{ const Map<int, Widget> children = <int, Widget>{
0: Text('Child 1'), 0: Text('Child 1'),
1: Text('Child 2'), 1: Text('Child 2'),
...@@ -603,7 +604,7 @@ void main() { ...@@ -603,7 +604,7 @@ void main() {
expect(tester.getTopRight(find.text('Child 1')).dx > tester.getTopRight(find.text('Child 2')).dx, isTrue); expect(tester.getTopRight(find.text('Child 1')).dx > tester.getTopRight(find.text('Child 2')).dx, isTrue);
}); });
testWidgets('Correct initial selection and toggling behavior - RTL', (WidgetTester tester) async { testWidgetsWithLeakTracking('Correct initial selection and toggling behavior - RTL', (WidgetTester tester) async {
const Map<int, Widget> children = <int, Widget>{ const Map<int, Widget> children = <int, Widget>{
0: Text('Child 1'), 0: Text('Child 1'),
1: Text('Child 2'), 1: Text('Child 2'),
...@@ -640,7 +641,7 @@ void main() { ...@@ -640,7 +641,7 @@ void main() {
expect(getHighlightedIndex(tester), 0); expect(getHighlightedIndex(tester), 0);
}); });
testWidgets('Segmented control semantics', (WidgetTester tester) async { testWidgetsWithLeakTracking('Segmented control semantics', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
const Map<int, Widget> children = <int, Widget>{ const Map<int, Widget> children = <int, Widget>{
0: Text('Child 1'), 0: Text('Child 1'),
...@@ -733,7 +734,7 @@ void main() { ...@@ -733,7 +734,7 @@ void main() {
semantics.dispose(); semantics.dispose();
}); });
testWidgets('Non-centered taps work on smaller widgets', (WidgetTester tester) async { testWidgetsWithLeakTracking('Non-centered taps work on smaller widgets', (WidgetTester tester) async {
final Map<int, Widget> children = <int, Widget>{}; final Map<int, Widget> children = <int, Widget>{};
children[0] = const Text('Child 1'); children[0] = const Text('Child 1');
children[1] = const SizedBox(); children[1] = const SizedBox();
...@@ -761,7 +762,7 @@ void main() { ...@@ -761,7 +762,7 @@ void main() {
expect(groupValue, 1); expect(groupValue, 1);
}); });
testWidgets('Hit-tests report accurate local position in segments', (WidgetTester tester) async { testWidgetsWithLeakTracking('Hit-tests report accurate local position in segments', (WidgetTester tester) async {
final Map<int, Widget> children = <int, Widget>{}; final Map<int, Widget> children = <int, Widget>{};
late TapDownDetails tapDownDetails; late TapDownDetails tapDownDetails;
children[0] = GestureDetector( children[0] = GestureDetector(
...@@ -793,7 +794,7 @@ void main() { ...@@ -793,7 +794,7 @@ void main() {
expect(tapDownDetails.globalPosition, segment0GlobalOffset + const Offset(7, 11)); expect(tapDownDetails.globalPosition, segment0GlobalOffset + const Offset(7, 11));
}); });
testWidgets('Thumb animation is correct when the selected segment changes', (WidgetTester tester) async { testWidgetsWithLeakTracking('Thumb animation is correct when the selected segment changes', (WidgetTester tester) async {
await tester.pumpWidget(setupSimpleSegmentedControl()); await tester.pumpWidget(setupSimpleSegmentedControl());
final Rect initialRect = currentUnscaledThumbRect(tester, useGlobalCoordinate: true); final Rect initialRect = currentUnscaledThumbRect(tester, useGlobalCoordinate: true);
...@@ -874,7 +875,7 @@ void main() { ...@@ -874,7 +875,7 @@ void main() {
expect(currentThumbScale(tester), moreOrLessEquals(1, epsilon: 0.01)); expect(currentThumbScale(tester), moreOrLessEquals(1, epsilon: 0.01));
}); });
testWidgets( testWidgetsWithLeakTracking(
'Thumb does not go out of bounds in animation', 'Thumb does not go out of bounds in animation',
(WidgetTester tester) async { (WidgetTester tester) async {
const Map<int, Widget> children = <int, Widget>{ const Map<int, Widget> children = <int, Widget>{
...@@ -931,7 +932,7 @@ void main() { ...@@ -931,7 +932,7 @@ void main() {
}, },
); );
testWidgets('Transition is triggered while a transition is already occurring', (WidgetTester tester) async { testWidgetsWithLeakTracking('Transition is triggered while a transition is already occurring', (WidgetTester tester) async {
const Map<int, Widget> children = <int, Widget>{ const Map<int, Widget> children = <int, Widget>{
0: Text('A'), 0: Text('A'),
1: Text('B'), 1: Text('B'),
...@@ -981,7 +982,7 @@ void main() { ...@@ -981,7 +982,7 @@ void main() {
); );
}); });
testWidgets('Insert segment while animation is running', (WidgetTester tester) async { testWidgetsWithLeakTracking('Insert segment while animation is running', (WidgetTester tester) async {
final Map<int, Widget> children = SplayTreeMap<int, Widget>((int a, int b) => a - b); final Map<int, Widget> children = SplayTreeMap<int, Widget>((int a, int b) => a - b);
children[0] = const Text('A'); children[0] = const Text('A');
...@@ -1027,7 +1028,7 @@ void main() { ...@@ -1027,7 +1028,7 @@ void main() {
); );
}); });
testWidgets('change selection programmatically when dragging', (WidgetTester tester) async { testWidgetsWithLeakTracking('change selection programmatically when dragging', (WidgetTester tester) async {
const Map<int, Widget> children = <int, Widget>{ const Map<int, Widget> children = <int, Widget>{
0: Text('A'), 0: Text('A'),
1: Text('B'), 1: Text('B'),
...@@ -1086,7 +1087,7 @@ void main() { ...@@ -1086,7 +1087,7 @@ void main() {
expect(callbackCalled, isFalse); expect(callbackCalled, isFalse);
}); });
testWidgets('Disallow new gesture when dragging', (WidgetTester tester) async { testWidgetsWithLeakTracking('Disallow new gesture when dragging', (WidgetTester tester) async {
const Map<int, Widget> children = <int, Widget>{ const Map<int, Widget> children = <int, Widget>{
0: Text('A'), 0: Text('A'),
1: Text('B'), 1: Text('B'),
...@@ -1141,7 +1142,7 @@ void main() { ...@@ -1141,7 +1142,7 @@ void main() {
expect(callbackCalled, isFalse); expect(callbackCalled, isFalse);
}); });
testWidgets('gesture outlives the widget', (WidgetTester tester) async { testWidgetsWithLeakTracking('gesture outlives the widget', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/63338. // Regression test for https://github.com/flutter/flutter/issues/63338.
const Map<int, Widget> children = <int, Widget>{ const Map<int, Widget> children = <int, Widget>{
0: Text('A'), 0: Text('A'),
...@@ -1179,7 +1180,7 @@ void main() { ...@@ -1179,7 +1180,7 @@ void main() {
expect(tester.takeException(), isNull); expect(tester.takeException(), isNull);
}); });
testWidgets('computeDryLayout is pure', (WidgetTester tester) async { testWidgetsWithLeakTracking('computeDryLayout is pure', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/73362. // Regression test for https://github.com/flutter/flutter/issues/73362.
const Map<int, Widget> children = <int, Widget>{ const Map<int, Widget> children = <int, Widget>{
0: Text('A'), 0: Text('A'),
...@@ -1213,7 +1214,7 @@ void main() { ...@@ -1213,7 +1214,7 @@ void main() {
expect(tester.takeException(), isNull); expect(tester.takeException(), isNull);
}); });
testWidgets('Has consistent size, independent of groupValue', (WidgetTester tester) async { testWidgetsWithLeakTracking('Has consistent size, independent of groupValue', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/62063. // Regression test for https://github.com/flutter/flutter/issues/62063.
const Map<int, Widget> children = <int, Widget>{ const Map<int, Widget> children = <int, Widget>{
0: Text('A'), 0: Text('A'),
...@@ -1247,12 +1248,13 @@ void main() { ...@@ -1247,12 +1248,13 @@ void main() {
} }
}); });
testWidgets('ScrollView + SlidingSegmentedControl interaction', (WidgetTester tester) async { testWidgetsWithLeakTracking('ScrollView + SlidingSegmentedControl interaction', (WidgetTester tester) async {
const Map<int, Widget> children = <int, Widget>{ const Map<int, Widget> children = <int, Widget>{
0: Text('Child 1'), 0: Text('Child 1'),
1: Text('Child 2'), 1: Text('Child 2'),
}; };
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
...@@ -1333,7 +1335,7 @@ void main() { ...@@ -1333,7 +1335,7 @@ void main() {
expect(groupValue, 1); expect(groupValue, 1);
}); });
testWidgets('Hovering over Cupertino sliding segmented control updates cursor to clickable on Web', (WidgetTester tester) async { testWidgetsWithLeakTracking('Hovering over Cupertino sliding segmented control updates cursor to clickable on Web', (WidgetTester tester) async {
const Map<int, Widget> children = <int, Widget>{ const Map<int, Widget> children = <int, Widget>{
0: Text('A'), 0: Text('A'),
1: Text('BB'), 1: Text('BB'),
......
...@@ -7,11 +7,12 @@ import 'package:flutter/foundation.dart'; ...@@ -7,11 +7,12 @@ import 'package:flutter/foundation.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() {
TestWidgetsFlutterBinding.ensureInitialized(); TestWidgetsFlutterBinding.ensureInitialized();
testWidgets('more than three suggestions throws an error', (WidgetTester tester) async { testWidgetsWithLeakTracking('more than three suggestions throws an error', (WidgetTester tester) async {
Future<void> pumpToolbar(List<String> suggestions) async { Future<void> pumpToolbar(List<String> suggestions) async {
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
...@@ -61,10 +62,14 @@ void main() { ...@@ -61,10 +62,14 @@ void main() {
expect(labels, isNot(contains('yeller'))); expect(labels, isNot(contains('yeller')));
}); });
testWidgets('buildButtonItems builds a disabled "No Replacements Found" button when no suggestions', (WidgetTester tester) async { testWidgetsWithLeakTracking('buildButtonItems builds a disabled "No Replacements Found" button when no suggestions', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget( await tester.pumpWidget(
CupertinoApp( CupertinoApp(
home: _FakeEditableText(), home: _FakeEditableText(focusNode, controller),
), ),
); );
final _FakeEditableTextState editableTextState = final _FakeEditableTextState editableTextState =
...@@ -80,9 +85,11 @@ void main() { ...@@ -80,9 +85,11 @@ void main() {
} }
class _FakeEditableText extends EditableText { class _FakeEditableText extends EditableText {
_FakeEditableText() : super( /// The parameters focusNode and controller are needed here so the can be
controller: TextEditingController(), /// safely disposed after the test is completed.
focusNode: FocusNode(), _FakeEditableText(FocusNode focusNode, TextEditingController controller) : super(
controller: controller,
focusNode: focusNode,
backgroundCursorColor: CupertinoColors.white, backgroundCursorColor: CupertinoColors.white,
cursorColor: CupertinoColors.white, cursorColor: CupertinoColors.white,
style: const TextStyle(), style: const TextStyle(),
......
...@@ -14,9 +14,10 @@ import 'package:flutter/material.dart'; ...@@ -14,9 +14,10 @@ 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() {
testWidgets('Switch can toggle on tap', (WidgetTester tester) async { testWidgetsWithLeakTracking('Switch can toggle on tap', (WidgetTester tester) async {
final Key switchKey = UniqueKey(); final Key switchKey = UniqueKey();
bool value = false; bool value = false;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -46,7 +47,7 @@ void main() { ...@@ -46,7 +47,7 @@ void main() {
expect(value, isTrue); expect(value, isTrue);
}); });
testWidgets('CupertinoSwitch can be toggled by keyboard shortcuts', (WidgetTester tester) async { testWidgetsWithLeakTracking('CupertinoSwitch can be toggled by keyboard shortcuts', (WidgetTester tester) async {
bool value = true; bool value = true;
Widget buildApp({bool enabled = true}) { Widget buildApp({bool enabled = true}) {
return CupertinoApp( return CupertinoApp(
...@@ -79,7 +80,7 @@ void main() { ...@@ -79,7 +80,7 @@ void main() {
expect(value, isTrue); expect(value, isTrue);
}); });
testWidgets('Switch emits light haptic vibration on tap', (WidgetTester tester) async { testWidgetsWithLeakTracking('Switch emits light haptic vibration on tap', (WidgetTester tester) async {
final Key switchKey = UniqueKey(); final Key switchKey = UniqueKey();
bool value = false; bool value = false;
...@@ -119,7 +120,7 @@ void main() { ...@@ -119,7 +120,7 @@ void main() {
expect(log.single, isMethodCall('HapticFeedback.vibrate', arguments: 'HapticFeedbackType.lightImpact')); expect(log.single, isMethodCall('HapticFeedback.vibrate', arguments: 'HapticFeedbackType.lightImpact'));
}, variant: TargetPlatformVariant.only(TargetPlatform.iOS)); }, variant: TargetPlatformVariant.only(TargetPlatform.iOS));
testWidgets('Using other widgets that rebuild the switch will not cause vibrations', (WidgetTester tester) async { testWidgetsWithLeakTracking('Using other widgets that rebuild the switch will not cause vibrations', (WidgetTester tester) async {
final Key switchKey = UniqueKey(); final Key switchKey = UniqueKey();
final Key switchKey2 = UniqueKey(); final Key switchKey2 = UniqueKey();
bool value = false; bool value = false;
...@@ -190,7 +191,7 @@ void main() { ...@@ -190,7 +191,7 @@ void main() {
expect(log[3], isMethodCall('HapticFeedback.vibrate', arguments: 'HapticFeedbackType.lightImpact')); expect(log[3], isMethodCall('HapticFeedback.vibrate', arguments: 'HapticFeedbackType.lightImpact'));
}, variant: TargetPlatformVariant.only(TargetPlatform.iOS)); }, variant: TargetPlatformVariant.only(TargetPlatform.iOS));
testWidgets('Haptic vibration triggers on drag', (WidgetTester tester) async { testWidgetsWithLeakTracking('Haptic vibration triggers on drag', (WidgetTester tester) async {
bool value = false; bool value = false;
final List<MethodCall> log = <MethodCall>[]; final List<MethodCall> log = <MethodCall>[];
...@@ -228,7 +229,7 @@ void main() { ...@@ -228,7 +229,7 @@ void main() {
expect(log[0], isMethodCall('HapticFeedback.vibrate', arguments: 'HapticFeedbackType.lightImpact')); expect(log[0], isMethodCall('HapticFeedback.vibrate', arguments: 'HapticFeedbackType.lightImpact'));
}, variant: TargetPlatformVariant.only(TargetPlatform.iOS)); }, variant: TargetPlatformVariant.only(TargetPlatform.iOS));
testWidgets('No haptic vibration triggers from a programmatic value change', (WidgetTester tester) async { testWidgetsWithLeakTracking('No haptic vibration triggers from a programmatic value change', (WidgetTester tester) async {
final Key switchKey = UniqueKey(); final Key switchKey = UniqueKey();
bool value = false; bool value = false;
...@@ -280,7 +281,7 @@ void main() { ...@@ -280,7 +281,7 @@ void main() {
expect(log, hasLength(0)); expect(log, hasLength(0));
}, variant: TargetPlatformVariant.only(TargetPlatform.iOS)); }, variant: TargetPlatformVariant.only(TargetPlatform.iOS));
testWidgets('Switch can drag (LTR)', (WidgetTester tester) async { testWidgetsWithLeakTracking('Switch can drag (LTR)', (WidgetTester tester) async {
bool value = false; bool value = false;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -324,7 +325,7 @@ void main() { ...@@ -324,7 +325,7 @@ void main() {
expect(value, isFalse); expect(value, isFalse);
}); });
testWidgets('Switch can drag with dragStartBehavior', (WidgetTester tester) async { testWidgetsWithLeakTracking('Switch can drag with dragStartBehavior', (WidgetTester tester) async {
bool value = false; bool value = false;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -410,7 +411,7 @@ void main() { ...@@ -410,7 +411,7 @@ void main() {
await tester.pump(); await tester.pump();
}); });
testWidgets('Switch can drag (RTL)', (WidgetTester tester) async { testWidgetsWithLeakTracking('Switch can drag (RTL)', (WidgetTester tester) async {
bool value = false; bool value = false;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -455,7 +456,7 @@ void main() { ...@@ -455,7 +456,7 @@ void main() {
expect(value, isFalse); expect(value, isFalse);
}); });
testWidgets('can veto switch dragging result', (WidgetTester tester) async { testWidgetsWithLeakTracking('can veto switch dragging result', (WidgetTester tester) async {
bool value = false; bool value = false;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -527,7 +528,7 @@ void main() { ...@@ -527,7 +528,7 @@ void main() {
expect(position.value, 1.0); expect(position.value, 1.0);
}); });
testWidgets('Switch is translucent when disabled', (WidgetTester tester) async { testWidgetsWithLeakTracking('Switch is translucent when disabled', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const Directionality( const Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -545,7 +546,7 @@ void main() { ...@@ -545,7 +546,7 @@ void main() {
expect(tester.widget<Opacity>(find.byType(Opacity).first).opacity, 0.5); expect(tester.widget<Opacity>(find.byType(Opacity).first).opacity, 0.5);
}); });
testWidgets('Switch is using track color when set', (WidgetTester tester) async { testWidgetsWithLeakTracking('Switch is using track color when set', (WidgetTester tester) async {
const Color trackColor = Color(0xFF00FF00); const Color trackColor = Color(0xFF00FF00);
await tester.pumpWidget( await tester.pumpWidget(
...@@ -567,7 +568,7 @@ void main() { ...@@ -567,7 +568,7 @@ void main() {
expect(find.byType(CupertinoSwitch), paints..rrect(color: trackColor)); expect(find.byType(CupertinoSwitch), paints..rrect(color: trackColor));
}); });
testWidgets('Switch is using default thumb color', (WidgetTester tester) async { testWidgetsWithLeakTracking('Switch is using default thumb color', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const Directionality( const Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -593,7 +594,7 @@ void main() { ...@@ -593,7 +594,7 @@ void main() {
); );
}); });
testWidgets('Switch is using thumb color when set', (WidgetTester tester) async { testWidgetsWithLeakTracking('Switch is using thumb color when set', (WidgetTester tester) async {
const Color thumbColor = Color(0xFF000000); const Color thumbColor = Color(0xFF000000);
await tester.pumpWidget( await tester.pumpWidget(
const Directionality( const Directionality(
...@@ -621,7 +622,7 @@ void main() { ...@@ -621,7 +622,7 @@ void main() {
); );
}); });
testWidgets('Switch is opaque when enabled', (WidgetTester tester) async { testWidgetsWithLeakTracking('Switch is opaque when enabled', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -639,7 +640,7 @@ void main() { ...@@ -639,7 +640,7 @@ void main() {
expect(tester.widget<Opacity>(find.byType(Opacity).first).opacity, 1.0); expect(tester.widget<Opacity>(find.byType(Opacity).first).opacity, 1.0);
}); });
testWidgets('Switch turns translucent after becoming disabled', (WidgetTester tester) async { testWidgetsWithLeakTracking('Switch turns translucent after becoming disabled', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -670,7 +671,7 @@ void main() { ...@@ -670,7 +671,7 @@ void main() {
expect(tester.widget<Opacity>(find.byType(Opacity).first).opacity, 0.5); expect(tester.widget<Opacity>(find.byType(Opacity).first).opacity, 0.5);
}); });
testWidgets('Switch turns opaque after becoming enabled', (WidgetTester tester) async { testWidgetsWithLeakTracking('Switch turns opaque after becoming enabled', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const Directionality( const Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -701,7 +702,7 @@ void main() { ...@@ -701,7 +702,7 @@ void main() {
expect(tester.widget<Opacity>(find.byType(Opacity).first).opacity, 1.0); expect(tester.widget<Opacity>(find.byType(Opacity).first).opacity, 1.0);
}); });
testWidgets('Switch renders correctly before, during, and after being tapped', (WidgetTester tester) async { testWidgetsWithLeakTracking('Switch renders correctly before, during, and after being tapped', (WidgetTester tester) async {
final Key switchKey = UniqueKey(); final Key switchKey = UniqueKey();
bool value = false; bool value = false;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -779,7 +780,7 @@ void main() { ...@@ -779,7 +780,7 @@ void main() {
style: PaintingStyle.stroke, style: PaintingStyle.stroke,
); );
testWidgets('Switch renders switch labels correctly before, during, and after being tapped', (WidgetTester tester) async { testWidgetsWithLeakTracking('Switch renders switch labels correctly before, during, and after being tapped', (WidgetTester tester) async {
final Key switchKey = UniqueKey(); final Key switchKey = UniqueKey();
bool value = false; bool value = false;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -829,7 +830,7 @@ void main() { ...@@ -829,7 +830,7 @@ void main() {
expect(switchRenderObject, offLabelPaintPattern(alpha: 0)); expect(switchRenderObject, offLabelPaintPattern(alpha: 0));
}); });
testWidgets('Switch renders switch labels correctly before, during, and after being tapped in high contrast', (WidgetTester tester) async { testWidgetsWithLeakTracking('Switch renders switch labels correctly before, during, and after being tapped in high contrast', (WidgetTester tester) async {
final Key switchKey = UniqueKey(); final Key switchKey = UniqueKey();
bool value = false; bool value = false;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -882,7 +883,7 @@ void main() { ...@@ -882,7 +883,7 @@ void main() {
expect(switchRenderObject, offLabelPaintPattern(highContrast: true, alpha: 0)); expect(switchRenderObject, offLabelPaintPattern(highContrast: true, alpha: 0));
}); });
testWidgets('Switch renders switch labels correctly before, during, and after being tapped with direction rtl', (WidgetTester tester) async { testWidgetsWithLeakTracking('Switch renders switch labels correctly before, during, and after being tapped with direction rtl', (WidgetTester tester) async {
final Key switchKey = UniqueKey(); final Key switchKey = UniqueKey();
bool value = false; bool value = false;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -932,7 +933,7 @@ void main() { ...@@ -932,7 +933,7 @@ void main() {
expect(switchRenderObject, offLabelPaintPattern(isRtl: true, alpha: 0)); expect(switchRenderObject, offLabelPaintPattern(isRtl: true, alpha: 0));
}); });
testWidgets('Switch renders correctly in dark mode', (WidgetTester tester) async { testWidgetsWithLeakTracking('Switch renders correctly in dark mode', (WidgetTester tester) async {
final Key switchKey = UniqueKey(); final Key switchKey = UniqueKey();
bool value = false; bool value = false;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -977,7 +978,7 @@ void main() { ...@@ -977,7 +978,7 @@ void main() {
); );
}); });
testWidgets('Switch can apply the ambient theme and be opted out', (WidgetTester tester) async { testWidgetsWithLeakTracking('Switch can apply the ambient theme and be opted out', (WidgetTester tester) async {
final Key switchKey = UniqueKey(); final Key switchKey = UniqueKey();
bool value = false; bool value = false;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -1037,7 +1038,7 @@ void main() { ...@@ -1037,7 +1038,7 @@ void main() {
); );
}); });
testWidgets('Hovering over Cupertino switch updates cursor to clickable on Web', (WidgetTester tester) async { testWidgetsWithLeakTracking('Hovering over Cupertino switch updates cursor to clickable on Web', (WidgetTester tester) async {
const bool value = false; const bool value = false;
// Disabled CupertinoSwitch does not update cursor on Web. // Disabled CupertinoSwitch does not update cursor on Web.
await tester.pumpWidget( await tester.pumpWidget(
...@@ -1093,8 +1094,9 @@ void main() { ...@@ -1093,8 +1094,9 @@ void main() {
); );
}); });
testWidgets('CupertinoSwitch is focusable and has correct focus color', (WidgetTester tester) async { testWidgetsWithLeakTracking('CupertinoSwitch is focusable and has correct focus color', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(debugLabel: 'CupertinoSwitch'); final FocusNode focusNode = FocusNode(debugLabel: 'CupertinoSwitch');
addTearDown(focusNode.dispose);
tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional; tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
bool value = true; bool value = true;
const Color focusColor = Color(0xffff0000); const Color focusColor = Color(0xffff0000);
...@@ -1174,8 +1176,9 @@ void main() { ...@@ -1174,8 +1176,9 @@ void main() {
); );
}); });
testWidgets('CupertinoSwitch.onFocusChange callback', (WidgetTester tester) async { testWidgetsWithLeakTracking('CupertinoSwitch.onFocusChange callback', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(debugLabel: 'CupertinoSwitch'); final FocusNode focusNode = FocusNode(debugLabel: 'CupertinoSwitch');
addTearDown(focusNode.dispose);
bool focused = false; bool focused = false;
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment