Cover more test/widgets tests with leak tracking #8 (#135045)

This commit is contained in:
Kostia Sokolovskyi 2023-09-20 16:34:41 +02:00 committed by GitHub
parent c3db020993
commit 98ebab58ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 869 additions and 420 deletions

View File

@ -4,9 +4,10 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() {
testWidgets('Scroll flings twice in a row does not crash', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scroll flings twice in a row does not crash', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,

View File

@ -5,9 +5,10 @@
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() {
testWidgets('ScrollMetricsNotification test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ScrollMetricsNotification test', (WidgetTester tester) async {
final List<Notification> events = <Notification>[];
Widget buildFrame(double height) {
return NotificationListener<Notification>(
@ -62,7 +63,7 @@ void main() {
expect(events.length, 0);
});
testWidgets('Scroll notification basics', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scroll notification basics', (WidgetTester tester) async {
late ScrollNotification notification;
await tester.pumpWidget(NotificationListener<ScrollNotification>(
@ -103,7 +104,7 @@ void main() {
expect(end.dragDetails!.velocity, equals(Velocity.zero));
});
testWidgets('Scroll notification depth', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scroll notification depth', (WidgetTester tester) async {
final List<Type> depth0Types = <Type>[];
final List<Type> depth1Types = <Type>[];
final List<int> depth0Values = <int>[];
@ -158,7 +159,7 @@ void main() {
expect(depth1Values, equals(<int>[1, 1, 1, 1, 1]));
});
testWidgets('ScrollNotifications bubble past Scaffold Material', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ScrollNotifications bubble past Scaffold Material', (WidgetTester tester) async {
final List<Type> notificationTypes = <Type>[];
await tester.pumpWidget(
@ -206,7 +207,7 @@ void main() {
expect(notificationTypes, equals(types));
});
testWidgets('ScrollNotificationObserver', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ScrollNotificationObserver', (WidgetTester tester) async {
late ScrollNotificationObserverState observer;
ScrollNotification? notification;

View File

@ -5,6 +5,7 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
class TestScrollPhysics extends ScrollPhysics {
const TestScrollPhysics({
@ -339,7 +340,7 @@ FlutterError
}
});
testWidgets('PageScrollPhysics work with NestedScrollView', (WidgetTester tester) async {
testWidgetsWithLeakTracking('PageScrollPhysics work with NestedScrollView', (WidgetTester tester) async {
// Regression test for: https://github.com/flutter/flutter/issues/47850
await tester.pumpWidget(Material(
child: Directionality(

View File

@ -4,6 +4,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
ScrollController _controller = ScrollController(
initialScrollOffset: 110.0,
@ -140,7 +141,7 @@ Future<void> performTest(WidgetTester tester, bool maintainState) async {
}
void main() {
testWidgets("ScrollPosition jumpTo() doesn't call notifyListeners twice", (WidgetTester tester) async {
testWidgetsWithLeakTracking("ScrollPosition jumpTo() doesn't call notifyListeners twice", (WidgetTester tester) async {
int count = 0;
await tester.pumpWidget(MaterialApp(
home: ListView.builder(
@ -159,15 +160,22 @@ void main() {
expect(count, 1);
});
testWidgets('whether we remember our scroll position', (WidgetTester tester) async {
testWidgetsWithLeakTracking('whether we remember our scroll position', (WidgetTester tester) async {
await performTest(tester, true);
await performTest(tester, false);
});
testWidgets('scroll alignment is honored by ensureVisible', (WidgetTester tester) async {
testWidgetsWithLeakTracking('scroll alignment is honored by ensureVisible', (WidgetTester tester) async {
final List<int> items = List<int>.generate(11, (int index) => index).toList();
final List<FocusNode> nodes = List<FocusNode>.generate(11, (int index) => FocusNode(debugLabel: 'Item ${index + 1}')).toList();
addTearDown(() {
for (final FocusNode node in nodes) {
node.dispose();
}
});
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(
MaterialApp(
home: ListView(
@ -226,7 +234,7 @@ void main() {
expect(controller.position.pixels, equals(0.0));
});
testWidgets('jumpTo recommends deferred loading', (WidgetTester tester) async {
testWidgetsWithLeakTracking('jumpTo recommends deferred loading', (WidgetTester tester) async {
int loadedWithDeferral = 0;
int buildCount = 0;
const double height = 500;

View File

@ -6,6 +6,7 @@ import 'package:flutter/gestures.dart' show DragStartBehavior;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show LogicalKeyboardKey;
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import 'states.dart';
@ -68,7 +69,7 @@ Widget primaryScrollControllerBoilerplate({ required Widget child, required Scro
}
void main() {
testWidgets('ListView control test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ListView control test', (WidgetTester tester) async {
final List<String> log = <String>[];
await tester.pumpWidget(
@ -110,8 +111,13 @@ void main() {
log.clear();
});
testWidgets('ListView dismiss keyboard onDrag test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ListView dismiss keyboard onDrag test', (WidgetTester tester) async {
final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());
addTearDown(() {
for (final FocusNode node in focusNodes) {
node.dispose();
}
});
await tester.pumpWidget(textFieldBoilerplate(
child: ListView(
@ -143,7 +149,7 @@ void main() {
expect(textField.focusNode!.hasFocus, isFalse);
});
testWidgets('GridView.builder supports null items', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView.builder supports null items', (WidgetTester tester) async {
await tester.pumpWidget(textFieldBoilerplate(
child: GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
@ -163,7 +169,7 @@ void main() {
expect(find.text('item'), findsNWidgets(5));
});
testWidgets('ListView.builder supports null items', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ListView.builder supports null items', (WidgetTester tester) async {
await tester.pumpWidget(textFieldBoilerplate(
child: ListView.builder(
itemCount: 42,
@ -180,11 +186,14 @@ void main() {
expect(find.text('item'), findsNWidgets(5));
});
testWidgets('PageView supports null items in itemBuilder', (WidgetTester tester) async {
testWidgetsWithLeakTracking('PageView supports null items in itemBuilder', (WidgetTester tester) async {
final PageController controller = PageController(viewportFraction: 1 / 5);
addTearDown(controller.dispose);
await tester.pumpWidget(textFieldBoilerplate(
child: PageView.builder(
itemCount: 5,
controller: PageController(viewportFraction: 1/5),
controller: controller,
itemBuilder: (BuildContext context, int index) {
if (index == 2) {
return null;
@ -198,7 +207,7 @@ void main() {
expect(find.text('item'), findsNWidgets(2));
});
testWidgets('ListView.separated supports null items in itemBuilder', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ListView.separated supports null items in itemBuilder', (WidgetTester tester) async {
await tester.pumpWidget(textFieldBoilerplate(
child: ListView.separated(
itemCount: 42,
@ -219,8 +228,13 @@ void main() {
expect(find.text('separator'), findsNWidgets(5));
});
testWidgets('ListView.builder dismiss keyboard onDrag test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ListView.builder dismiss keyboard onDrag test', (WidgetTester tester) async {
final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());
addTearDown(() {
for (final FocusNode node in focusNodes) {
node.dispose();
}
});
await tester.pumpWidget(textFieldBoilerplate(
child: ListView.builder(
@ -253,8 +267,13 @@ void main() {
expect(textField.focusNode!.hasFocus, isFalse);
});
testWidgets('ListView.custom dismiss keyboard onDrag test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ListView.custom dismiss keyboard onDrag test', (WidgetTester tester) async {
final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());
addTearDown(() {
for (final FocusNode node in focusNodes) {
node.dispose();
}
});
await tester.pumpWidget(textFieldBoilerplate(
child: ListView.custom(
@ -289,8 +308,13 @@ void main() {
expect(textField.focusNode!.hasFocus, isFalse);
});
testWidgets('ListView.separated dismiss keyboard onDrag test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ListView.separated dismiss keyboard onDrag test', (WidgetTester tester) async {
final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());
addTearDown(() {
for (final FocusNode node in focusNodes) {
node.dispose();
}
});
await tester.pumpWidget(textFieldBoilerplate(
child: ListView.separated(
@ -324,8 +348,13 @@ void main() {
expect(textField.focusNode!.hasFocus, isFalse);
});
testWidgets('GridView dismiss keyboard onDrag test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView dismiss keyboard onDrag test', (WidgetTester tester) async {
final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());
addTearDown(() {
for (final FocusNode node in focusNodes) {
node.dispose();
}
});
await tester.pumpWidget(textFieldBoilerplate(
child: GridView(
@ -358,8 +387,13 @@ void main() {
expect(textField.focusNode!.hasFocus, isFalse);
});
testWidgets('GridView.builder dismiss keyboard onDrag test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView.builder dismiss keyboard onDrag test', (WidgetTester tester) async {
final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());
addTearDown(() {
for (final FocusNode node in focusNodes) {
node.dispose();
}
});
await tester.pumpWidget(textFieldBoilerplate(
child: GridView.builder(
@ -393,8 +427,13 @@ void main() {
expect(textField.focusNode!.hasFocus, isFalse);
});
testWidgets('GridView.count dismiss keyboard onDrag test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView.count dismiss keyboard onDrag test', (WidgetTester tester) async {
final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());
addTearDown(() {
for (final FocusNode node in focusNodes) {
node.dispose();
}
});
await tester.pumpWidget(textFieldBoilerplate(
child: GridView.count(
@ -427,8 +466,13 @@ void main() {
expect(textField.focusNode!.hasFocus, isFalse);
});
testWidgets('GridView.extent dismiss keyboard onDrag test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView.extent dismiss keyboard onDrag test', (WidgetTester tester) async {
final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());
addTearDown(() {
for (final FocusNode node in focusNodes) {
node.dispose();
}
});
await tester.pumpWidget(textFieldBoilerplate(
child: GridView.extent(
@ -461,8 +505,13 @@ void main() {
expect(textField.focusNode!.hasFocus, isFalse);
});
testWidgets('GridView.custom dismiss keyboard onDrag test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView.custom dismiss keyboard onDrag test', (WidgetTester tester) async {
final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());
addTearDown(() {
for (final FocusNode node in focusNodes) {
node.dispose();
}
});
await tester.pumpWidget(textFieldBoilerplate(
child: GridView.custom(
@ -498,8 +547,13 @@ void main() {
expect(textField.focusNode!.hasFocus, isFalse);
});
testWidgets('ListView dismiss keyboard manual test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ListView dismiss keyboard manual test', (WidgetTester tester) async {
final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());
addTearDown(() {
for (final FocusNode node in focusNodes) {
node.dispose();
}
});
await tester.pumpWidget(textFieldBoilerplate(
child: ListView(
@ -530,8 +584,13 @@ void main() {
expect(textField.focusNode!.hasFocus, isTrue);
});
testWidgets('ListView.builder dismiss keyboard manual test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ListView.builder dismiss keyboard manual test', (WidgetTester tester) async {
final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());
addTearDown(() {
for (final FocusNode node in focusNodes) {
node.dispose();
}
});
await tester.pumpWidget(textFieldBoilerplate(
child: ListView.builder(
@ -563,8 +622,13 @@ void main() {
expect(textField.focusNode!.hasFocus, isTrue);
});
testWidgets('ListView.custom dismiss keyboard manual test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ListView.custom dismiss keyboard manual test', (WidgetTester tester) async {
final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());
addTearDown(() {
for (final FocusNode node in focusNodes) {
node.dispose();
}
});
await tester.pumpWidget(textFieldBoilerplate(
child: ListView.custom(
@ -598,8 +662,13 @@ void main() {
expect(textField.focusNode!.hasFocus, isTrue);
});
testWidgets('ListView.separated dismiss keyboard manual test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ListView.separated dismiss keyboard manual test', (WidgetTester tester) async {
final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());
addTearDown(() {
for (final FocusNode node in focusNodes) {
node.dispose();
}
});
await tester.pumpWidget(textFieldBoilerplate(
child: ListView.separated(
@ -632,8 +701,13 @@ void main() {
expect(textField.focusNode!.hasFocus, isTrue);
});
testWidgets('GridView dismiss keyboard manual test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView dismiss keyboard manual test', (WidgetTester tester) async {
final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());
addTearDown(() {
for (final FocusNode node in focusNodes) {
node.dispose();
}
});
await tester.pumpWidget(textFieldBoilerplate(
child: GridView(
@ -665,8 +739,13 @@ void main() {
expect(textField.focusNode!.hasFocus, isTrue);
});
testWidgets('GridView.builder dismiss keyboard manual test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView.builder dismiss keyboard manual test', (WidgetTester tester) async {
final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());
addTearDown(() {
for (final FocusNode node in focusNodes) {
node.dispose();
}
});
await tester.pumpWidget(textFieldBoilerplate(
child: GridView.builder(
@ -699,8 +778,13 @@ void main() {
expect(textField.focusNode!.hasFocus, isTrue);
});
testWidgets('GridView.count dismiss keyboard manual test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView.count dismiss keyboard manual test', (WidgetTester tester) async {
final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());
addTearDown(() {
for (final FocusNode node in focusNodes) {
node.dispose();
}
});
await tester.pumpWidget(textFieldBoilerplate(
child: GridView.count(
@ -732,8 +816,13 @@ void main() {
expect(textField.focusNode!.hasFocus, isTrue);
});
testWidgets('GridView.extent dismiss keyboard manual test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView.extent dismiss keyboard manual test', (WidgetTester tester) async {
final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());
addTearDown(() {
for (final FocusNode node in focusNodes) {
node.dispose();
}
});
await tester.pumpWidget(textFieldBoilerplate(
child: GridView.extent(
@ -765,8 +854,13 @@ void main() {
expect(textField.focusNode!.hasFocus, isTrue);
});
testWidgets('GridView.custom dismiss keyboard manual test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView.custom dismiss keyboard manual test', (WidgetTester tester) async {
final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());
addTearDown(() {
for (final FocusNode node in focusNodes) {
node.dispose();
}
});
await tester.pumpWidget(textFieldBoilerplate(
child: GridView.custom(
@ -801,7 +895,7 @@ void main() {
expect(textField.focusNode!.hasFocus, isTrue);
});
testWidgets('ListView restart ballistic activity out of range', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ListView restart ballistic activity out of range', (WidgetTester tester) async {
Widget buildListView(int n) {
return Directionality(
textDirection: TextDirection.ltr,
@ -831,7 +925,7 @@ void main() {
expect(viewport.offset.pixels, equals(2400.0));
});
testWidgets('CustomScrollView control test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('CustomScrollView control test', (WidgetTester tester) async {
final List<String> log = <String>[];
await tester.pumpWidget(
@ -879,8 +973,13 @@ void main() {
log.clear();
});
testWidgets('CustomScrollView dismiss keyboard onDrag test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('CustomScrollView dismiss keyboard onDrag test', (WidgetTester tester) async {
final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());
addTearDown(() {
for (final FocusNode node in focusNodes) {
node.dispose();
}
});
await tester.pumpWidget(textFieldBoilerplate(
child: CustomScrollView(
@ -918,9 +1017,10 @@ void main() {
expect(textField.focusNode!.hasFocus, isFalse);
});
testWidgets('Can jumpTo during drag', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Can jumpTo during drag', (WidgetTester tester) async {
final List<Type> log = <Type>[];
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(
Directionality(
@ -977,23 +1077,26 @@ void main() {
});
test('PrimaryScrollController.automaticallyInheritOnPlatforms defaults to all mobile platforms', (){
final PrimaryScrollController primaryScrollController = PrimaryScrollController(
controller: ScrollController(),
child: const SizedBox(),
);
expect(
primaryScrollController.automaticallyInheritForPlatforms,
TargetPlatformVariant.mobile().values,
);
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
final PrimaryScrollController primaryScrollController = PrimaryScrollController(
controller: controller,
child: const SizedBox(),
);
expect(
primaryScrollController.automaticallyInheritForPlatforms,
TargetPlatformVariant.mobile().values,
);
});
testWidgets('Vertical CustomScrollViews are not primary by default', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Vertical CustomScrollViews are not primary by default', (WidgetTester tester) async {
const CustomScrollView view = CustomScrollView();
expect(view.primary, isNull);
});
testWidgets('Vertical CustomScrollViews use PrimaryScrollController by default on mobile', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Vertical CustomScrollViews use PrimaryScrollController by default on mobile', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(primaryScrollControllerBoilerplate(
child: const CustomScrollView(),
controller: controller,
@ -1001,8 +1104,9 @@ void main() {
expect(controller.hasClients, isTrue);
}, variant: TargetPlatformVariant.mobile());
testWidgets("Vertical CustomScrollViews don't use PrimaryScrollController by default on desktop", (WidgetTester tester) async {
testWidgetsWithLeakTracking("Vertical CustomScrollViews don't use PrimaryScrollController by default on desktop", (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(primaryScrollControllerBoilerplate(
child: const CustomScrollView(),
controller: controller,
@ -1010,13 +1114,14 @@ void main() {
expect(controller.hasClients, isFalse);
}, variant: TargetPlatformVariant.desktop());
testWidgets('Vertical ListViews are not primary by default', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Vertical ListViews are not primary by default', (WidgetTester tester) async {
final ListView view = ListView();
expect(view.primary, isNull);
});
testWidgets('Vertical ListViews use PrimaryScrollController by default on mobile', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Vertical ListViews use PrimaryScrollController by default on mobile', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(primaryScrollControllerBoilerplate(
child: ListView(),
controller: controller,
@ -1024,8 +1129,9 @@ void main() {
expect(controller.hasClients, isTrue);
}, variant: TargetPlatformVariant.mobile());
testWidgets("Vertical ListViews don't use PrimaryScrollController by default on desktop", (WidgetTester tester) async {
testWidgetsWithLeakTracking("Vertical ListViews don't use PrimaryScrollController by default on desktop", (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(primaryScrollControllerBoilerplate(
child: ListView(),
controller: controller,
@ -1033,13 +1139,14 @@ void main() {
expect(controller.hasClients, isFalse);
}, variant: TargetPlatformVariant.desktop());
testWidgets('Vertical GridViews are not primary by default', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Vertical GridViews are not primary by default', (WidgetTester tester) async {
final GridView view = GridView.count(crossAxisCount: 1);
expect(view.primary, isNull);
});
testWidgets('Vertical GridViews use PrimaryScrollController by default on mobile', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Vertical GridViews use PrimaryScrollController by default on mobile', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(primaryScrollControllerBoilerplate(
child: GridView.count(crossAxisCount: 1),
controller: controller,
@ -1047,8 +1154,9 @@ void main() {
expect(controller.hasClients, isTrue);
}, variant: TargetPlatformVariant.mobile());
testWidgets("Vertical GridViews don't use PrimaryScrollController by default on desktop", (WidgetTester tester) async {
testWidgetsWithLeakTracking("Vertical GridViews don't use PrimaryScrollController by default on desktop", (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(primaryScrollControllerBoilerplate(
child: GridView.count(crossAxisCount: 1),
controller: controller,
@ -1056,79 +1164,98 @@ void main() {
expect(controller.hasClients, isFalse);
}, variant: TargetPlatformVariant.desktop());
testWidgets('Horizontal CustomScrollViews are non-primary by default', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
testWidgetsWithLeakTracking('Horizontal CustomScrollViews are non-primary by default', (WidgetTester tester) async {
final ScrollController controller1 = ScrollController();
addTearDown(controller1.dispose);
final ScrollController controller2 = ScrollController();
addTearDown(controller2.dispose);
await tester.pumpWidget(primaryScrollControllerBoilerplate(
child: CustomScrollView(
scrollDirection: Axis.horizontal,
controller: ScrollController(),
controller: controller2,
),
controller: controller,
controller: controller1,
));
expect(controller.hasClients, isFalse);
expect(controller1.hasClients, isFalse);
});
testWidgets('Horizontal ListViews are non-primary by default', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
testWidgetsWithLeakTracking('Horizontal ListViews are non-primary by default', (WidgetTester tester) async {
final ScrollController controller1 = ScrollController();
addTearDown(controller1.dispose);
final ScrollController controller2 = ScrollController();
addTearDown(controller2.dispose);
await tester.pumpWidget(primaryScrollControllerBoilerplate(
child: ListView(
scrollDirection: Axis.horizontal,
controller: ScrollController(),
controller: controller2,
),
controller: controller,
controller: controller1,
));
expect(controller.hasClients, isFalse);
expect(controller1.hasClients, isFalse);
});
testWidgets('Horizontal GridViews are non-primary by default', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
testWidgetsWithLeakTracking('Horizontal GridViews are non-primary by default', (WidgetTester tester) async {
final ScrollController controller1 = ScrollController();
addTearDown(controller1.dispose);
final ScrollController controller2 = ScrollController();
addTearDown(controller2.dispose);
await tester.pumpWidget(primaryScrollControllerBoilerplate(
child: GridView.count(
scrollDirection: Axis.horizontal,
controller: ScrollController(),
controller: controller2,
crossAxisCount: 1,
),
controller: controller,
controller: controller1,
));
expect(controller.hasClients, isFalse);
expect(controller1.hasClients, isFalse);
});
testWidgets('CustomScrollViews with controllers are non-primary by default', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
testWidgetsWithLeakTracking('CustomScrollViews with controllers are non-primary by default', (WidgetTester tester) async {
final ScrollController controller1 = ScrollController();
addTearDown(controller1.dispose);
final ScrollController controller2 = ScrollController();
addTearDown(controller2.dispose);
await tester.pumpWidget(primaryScrollControllerBoilerplate(
child: CustomScrollView(
controller: ScrollController(),
controller: controller2,
),
controller: controller,
controller: controller1,
));
expect(controller.hasClients, isFalse);
expect(controller1.hasClients, isFalse);
});
testWidgets('ListViews with controllers are non-primary by default', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
testWidgetsWithLeakTracking('ListViews with controllers are non-primary by default', (WidgetTester tester) async {
final ScrollController controller1 = ScrollController();
addTearDown(controller1.dispose);
final ScrollController controller2 = ScrollController();
addTearDown(controller2.dispose);
await tester.pumpWidget(primaryScrollControllerBoilerplate(
child: ListView(
controller: ScrollController(),
controller: controller2,
),
controller: controller,
controller: controller1,
));
expect(controller.hasClients, isFalse);
expect(controller1.hasClients, isFalse);
});
testWidgets('GridViews with controllers are non-primary by default', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
testWidgetsWithLeakTracking('GridViews with controllers are non-primary by default', (WidgetTester tester) async {
final ScrollController controller1 = ScrollController();
addTearDown(controller1.dispose);
final ScrollController controller2 = ScrollController();
addTearDown(controller2.dispose);
await tester.pumpWidget(primaryScrollControllerBoilerplate(
child: GridView.count(
controller: ScrollController(),
controller: controller2,
crossAxisCount: 1,
),
controller: controller,
controller: controller1,
));
expect(controller.hasClients, isFalse);
expect(controller1.hasClients, isFalse);
});
testWidgets('CustomScrollView sets PrimaryScrollController when primary', (WidgetTester tester) async {
testWidgetsWithLeakTracking('CustomScrollView sets PrimaryScrollController when primary', (WidgetTester tester) async {
final ScrollController primaryScrollController = ScrollController();
addTearDown(primaryScrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -1142,8 +1269,9 @@ void main() {
expect(scrollable.controller, primaryScrollController);
});
testWidgets('ListView sets PrimaryScrollController when primary', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ListView sets PrimaryScrollController when primary', (WidgetTester tester) async {
final ScrollController primaryScrollController = ScrollController();
addTearDown(primaryScrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -1157,8 +1285,9 @@ void main() {
expect(scrollable.controller, primaryScrollController);
});
testWidgets('GridView sets PrimaryScrollController when primary', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView sets PrimaryScrollController when primary', (WidgetTester tester) async {
final ScrollController primaryScrollController = ScrollController();
addTearDown(primaryScrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -1172,9 +1301,10 @@ void main() {
expect(scrollable.controller, primaryScrollController);
});
testWidgets('Nested scrollables have a null PrimaryScrollController', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Nested scrollables have a null PrimaryScrollController', (WidgetTester tester) async {
const Key innerKey = Key('inner');
final ScrollController primaryScrollController = ScrollController();
addTearDown(primaryScrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -1202,27 +1332,27 @@ void main() {
expect(innerScrollable.controller, isNull);
});
testWidgets('Primary ListViews are always scrollable', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Primary ListViews are always scrollable', (WidgetTester tester) async {
final ListView view = ListView(primary: true);
expect(view.physics, isA<AlwaysScrollableScrollPhysics>());
});
testWidgets('Non-primary ListViews are not always scrollable', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Non-primary ListViews are not always scrollable', (WidgetTester tester) async {
final ListView view = ListView(primary: false);
expect(view.physics, isNot(isA<AlwaysScrollableScrollPhysics>()));
});
testWidgets('Defaulting-to-primary ListViews are always scrollable', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Defaulting-to-primary ListViews are always scrollable', (WidgetTester tester) async {
final ListView view = ListView();
expect(view.physics, isA<AlwaysScrollableScrollPhysics>());
});
testWidgets('Defaulting-to-not-primary ListViews are not always scrollable', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Defaulting-to-not-primary ListViews are not always scrollable', (WidgetTester tester) async {
final ListView view = ListView(scrollDirection: Axis.horizontal);
expect(view.physics, isNot(isA<AlwaysScrollableScrollPhysics>()));
});
testWidgets('primary:true leads to scrolling', (WidgetTester tester) async {
testWidgetsWithLeakTracking('primary:true leads to scrolling', (WidgetTester tester) async {
bool scrolled = false;
await tester.pumpWidget(
Directionality(
@ -1242,7 +1372,7 @@ void main() {
expect(scrolled, isTrue);
});
testWidgets('primary:false leads to no scrolling', (WidgetTester tester) async {
testWidgetsWithLeakTracking('primary:false leads to no scrolling', (WidgetTester tester) async {
bool scrolled = false;
await tester.pumpWidget(
Directionality(
@ -1262,7 +1392,7 @@ void main() {
expect(scrolled, isFalse);
});
testWidgets('physics:AlwaysScrollableScrollPhysics actually overrides primary:false default behavior', (WidgetTester tester) async {
testWidgetsWithLeakTracking('physics:AlwaysScrollableScrollPhysics actually overrides primary:false default behavior', (WidgetTester tester) async {
bool scrolled = false;
await tester.pumpWidget(
Directionality(
@ -1283,7 +1413,7 @@ void main() {
expect(scrolled, isTrue);
});
testWidgets('physics:ScrollPhysics actually overrides primary:true default behavior', (WidgetTester tester) async {
testWidgetsWithLeakTracking('physics:ScrollPhysics actually overrides primary:true default behavior', (WidgetTester tester) async {
bool scrolled = false;
await tester.pumpWidget(
Directionality(
@ -1304,7 +1434,7 @@ void main() {
expect(scrolled, isFalse);
});
testWidgets('separatorBuilder must return something', (WidgetTester tester) async {
testWidgetsWithLeakTracking('separatorBuilder must return something', (WidgetTester tester) async {
const List<String> listOfValues = <String>['ALPHA', 'BETA', 'GAMMA', 'DELTA'];
Widget buildFrame(Widget firstSeparator) {
@ -1332,7 +1462,7 @@ void main() {
expect(tester.takeException(), isNull);
});
testWidgets('when itemBuilder throws, creates Error Widget', (WidgetTester tester) async {
testWidgetsWithLeakTracking('when itemBuilder throws, creates Error Widget', (WidgetTester tester) async {
const List<String> listOfValues = <String>['ALPHA', 'BETA', 'GAMMA', 'DELTA'];
Widget buildFrame(bool throwOnFirstItem) {
@ -1363,7 +1493,7 @@ void main() {
expect(finder, findsOneWidget);
});
testWidgets('when separatorBuilder throws, creates ErrorWidget', (WidgetTester tester) async {
testWidgetsWithLeakTracking('when separatorBuilder throws, creates ErrorWidget', (WidgetTester tester) async {
const List<String> listOfValues = <String>['ALPHA', 'BETA', 'GAMMA', 'DELTA'];
const Key key = Key('list');
@ -1399,14 +1529,14 @@ void main() {
expect(finder, findsOneWidget);
});
testWidgets('ListView asserts on both non-null itemExtent and prototypeItem', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ListView asserts on both non-null itemExtent and prototypeItem', (WidgetTester tester) async {
expect(() => ListView(
itemExtent: 100,
prototypeItem: const SizedBox(),
), throwsAssertionError);
});
testWidgets('ListView.builder asserts on negative childCount', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ListView.builder asserts on negative childCount', (WidgetTester tester) async {
expect(() => ListView.builder(
itemBuilder: (BuildContext context, int index) {
return const SizedBox();
@ -1415,7 +1545,7 @@ void main() {
), throwsAssertionError);
});
testWidgets('ListView.builder asserts on negative semanticChildCount', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ListView.builder asserts on negative semanticChildCount', (WidgetTester tester) async {
expect(() => ListView.builder(
itemBuilder: (BuildContext context, int index) {
return const SizedBox();
@ -1425,7 +1555,7 @@ void main() {
), throwsAssertionError);
});
testWidgets('ListView.builder asserts on nonsensical childCount/semanticChildCount', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ListView.builder asserts on nonsensical childCount/semanticChildCount', (WidgetTester tester) async {
expect(() => ListView.builder(
itemBuilder: (BuildContext context, int index) {
return const SizedBox();
@ -1435,7 +1565,7 @@ void main() {
), throwsAssertionError);
});
testWidgets('ListView.builder asserts on both non-null itemExtent and prototypeItem', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ListView.builder asserts on both non-null itemExtent and prototypeItem', (WidgetTester tester) async {
expect(() => ListView.builder(
itemBuilder: (BuildContext context, int index) {
return const SizedBox();
@ -1445,7 +1575,7 @@ void main() {
), throwsAssertionError);
});
testWidgets('ListView.custom asserts on both non-null itemExtent and prototypeItem', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ListView.custom asserts on both non-null itemExtent and prototypeItem', (WidgetTester tester) async {
expect(() => ListView.custom(
childrenDelegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
@ -1457,7 +1587,7 @@ void main() {
), throwsAssertionError);
});
testWidgets('PrimaryScrollController provides fallback ScrollActions', (WidgetTester tester) async {
testWidgetsWithLeakTracking('PrimaryScrollController provides fallback ScrollActions', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
home: CustomScrollView(
@ -1501,7 +1631,7 @@ void main() {
);
});
testWidgets('Fallback ScrollActions handle too many positions with error message', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Fallback ScrollActions handle too many positions with error message', (WidgetTester tester) async {
Widget getScrollView() {
return SizedBox(
width: 400.0,
@ -1550,7 +1680,7 @@ void main() {
);
});
testWidgets('if itemExtent is non-null, children have same extent in the scroll direction', (WidgetTester tester) async {
testWidgetsWithLeakTracking('if itemExtent is non-null, children have same extent in the scroll direction', (WidgetTester tester) async {
final List<int> numbers = <int>[0,1,2];
await tester.pumpWidget(
@ -1588,7 +1718,7 @@ void main() {
expect(item2Height, 30.0);
});
testWidgets('if prototypeItem is non-null, children have same extent in the scroll direction', (WidgetTester tester) async {
testWidgetsWithLeakTracking('if prototypeItem is non-null, children have same extent in the scroll direction', (WidgetTester tester) async {
final List<int> numbers = <int>[0,1,2];
await tester.pumpWidget(

View File

@ -5,10 +5,12 @@
import 'package:flutter/scheduler.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() {
testWidgets('Does not animate if already at target position', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Does not animate if already at target position', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -27,8 +29,9 @@ void main() {
expect(controller.position.pixels, currentPosition);
});
testWidgets('Does not animate if already at target position within tolerance', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Does not animate if already at target position within tolerance', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -50,8 +53,9 @@ void main() {
expect(controller.position.pixels, targetPosition);
});
testWidgets('Animates if going to a position outside of tolerance', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Animates if going to a position outside of tolerance', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,

View File

@ -4,11 +4,12 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import 'test_widgets.dart';
void main() {
testWidgets('simultaneously dispose a widget and end the scroll animation', (WidgetTester tester) async {
testWidgetsWithLeakTracking('simultaneously dispose a widget and end the scroll animation', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -26,10 +27,11 @@ void main() {
await tester.pump(const Duration(hours: 5));
});
testWidgets('Disposing a (nested) Scrollable while holding in overscroll does not crash', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Disposing a (nested) Scrollable while holding in overscroll does not crash', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/27707.
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
final Key outerContainer = GlobalKey();
await tester.pumpWidget(

View File

@ -5,6 +5,7 @@
import 'package:flutter/gestures.dart' show DragStartBehavior;
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
const TextStyle testFont = TextStyle(
color: Color(0xFF00FF00),
@ -31,7 +32,7 @@ Future<void> pumpTest(WidgetTester tester, TargetPlatform platform) async {
const double dragOffset = 213.82;
void main() {
testWidgets('Flings on different platforms', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Flings on different platforms', (WidgetTester tester) async {
double getCurrentOffset() {
return tester.state<ScrollableState>(find.byType(Scrollable)).position.pixels;
}
@ -96,7 +97,7 @@ void main() {
expect(linuxResult, equals(androidResult));
});
testWidgets('fling and tap to stop', (WidgetTester tester) async {
testWidgetsWithLeakTracking('fling and tap to stop', (WidgetTester tester) async {
final List<String> log = <String>[];
await tester.pumpWidget(
Directionality(
@ -126,7 +127,7 @@ void main() {
expect(log, equals(<String>['tap 21', 'tap 35']));
});
testWidgets('fling and wait and tap', (WidgetTester tester) async {
testWidgetsWithLeakTracking('fling and wait and tap', (WidgetTester tester) async {
final List<String> log = <String>[];
await tester.pumpWidget(
Directionality(

View File

@ -4,9 +4,10 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() {
testWidgets('GridView default control', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView default control', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -20,7 +21,7 @@ void main() {
});
// Tests https://github.com/flutter/flutter/issues/5522
testWidgets('GridView displays correct children with nonzero padding', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView displays correct children with nonzero padding', (WidgetTester tester) async {
const EdgeInsets padding = EdgeInsets.fromLTRB(0.0, 100.0, 0.0, 0.0);
final Widget testWidget = Directionality(
@ -76,7 +77,7 @@ void main() {
expect(find.text('4'), findsNothing);
});
testWidgets('GridView.count() fixed itemExtent, scroll to end, append, scroll', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView.count() fixed itemExtent, scroll to end, append, scroll', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/9506
Widget buildFrame(int itemCount) {
return Directionality(

View File

@ -6,6 +6,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
final LogicalKeyboardKey modifierKey = defaultTargetPlatform == TargetPlatform.macOS
? LogicalKeyboardKey.metaLeft
@ -13,8 +14,9 @@ final LogicalKeyboardKey modifierKey = defaultTargetPlatform == TargetPlatform.m
void main() {
group('ScrollableDetails', (){
final ScrollController controller = ScrollController();
test('copyWith / == / hashCode', () {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
final ScrollableDetails details = ScrollableDetails(
direction: AxisDirection.down,
controller: controller,
@ -42,6 +44,8 @@ void main() {
});
test('toString', (){
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
const ScrollableDetails bareDetails = ScrollableDetails(
direction: AxisDirection.right,
);
@ -86,8 +90,9 @@ void main() {
});
});
testWidgets("Keyboard scrolling doesn't happen if scroll physics are set to NeverScrollableScrollPhysics", (WidgetTester tester) async {
testWidgetsWithLeakTracking("Keyboard scrolling doesn't happen if scroll physics are set to NeverScrollableScrollPhysics", (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(
MaterialApp(
theme: ThemeData(platform: TargetPlatform.fuchsia),
@ -152,8 +157,9 @@ void main() {
);
}, variant: KeySimulatorTransitModeVariant.all());
testWidgets('Vertical scrollables are scrolled when activated via keyboard.', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Vertical scrollables are scrolled when activated via keyboard.', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(
MaterialApp(
theme: ThemeData(platform: TargetPlatform.fuchsia),
@ -223,8 +229,9 @@ void main() {
);
}, variant: KeySimulatorTransitModeVariant.all());
testWidgets('Horizontal scrollables are scrolled when activated via keyboard.', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Horizontal scrollables are scrolled when activated via keyboard.', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(
MaterialApp(
theme: ThemeData(platform: TargetPlatform.fuchsia),
@ -283,8 +290,9 @@ void main() {
);
}, variant: KeySimulatorTransitModeVariant.all());
testWidgets('Horizontal scrollables are scrolled the correct direction in RTL locales.', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Horizontal scrollables are scrolled the correct direction in RTL locales.', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(
MaterialApp(
theme: ThemeData(platform: TargetPlatform.fuchsia),
@ -346,9 +354,11 @@ void main() {
);
}, variant: KeySimulatorTransitModeVariant.all());
testWidgets('Reversed vertical scrollables are scrolled when activated via keyboard.', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Reversed vertical scrollables are scrolled when activated via keyboard.', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
final FocusNode focusNode = FocusNode(debugLabel: 'SizedBox');
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
theme: ThemeData(platform: TargetPlatform.fuchsia),
@ -420,9 +430,11 @@ void main() {
);
}, variant: KeySimulatorTransitModeVariant.all());
testWidgets('Reversed horizontal scrollables are scrolled when activated via keyboard.', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Reversed horizontal scrollables are scrolled when activated via keyboard.', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
final FocusNode focusNode = FocusNode(debugLabel: 'SizedBox');
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
theme: ThemeData(platform: TargetPlatform.fuchsia),
@ -479,8 +491,9 @@ void main() {
await tester.pumpAndSettle();
}, variant: KeySimulatorTransitModeVariant.all());
testWidgets('Custom scrollables with a center sliver are scrolled when activated via keyboard.', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Custom scrollables with a center sliver are scrolled when activated via keyboard.', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
final List<String> items = List<String>.generate(20, (int index) => 'Item $index');
await tester.pumpWidget(
MaterialApp(
@ -550,7 +563,7 @@ void main() {
);
}, variant: KeySimulatorTransitModeVariant.all());
testWidgets('Can scroll using intents only', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Can scroll using intents only', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
home: ListView(

View File

@ -4,6 +4,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() {
test('Can dispose ScrollPosition when hasPixels is false', () {
@ -18,9 +19,10 @@ void main() {
position.dispose(); // Should not throw/assert.
});
testWidgets('scrollable in hidden overlay does not crash when unhidden', (WidgetTester tester) async {
testWidgetsWithLeakTracking('scrollable in hidden overlay does not crash when unhidden', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/44269.
final TabController controller = TabController(vsync: const TestVSync(), length: 1);
addTearDown(controller.dispose);
final OverlayEntry entry1 = OverlayEntry(
maintainState: true,

View File

@ -5,11 +5,12 @@
import 'package:flutter/gestures.dart' show DragStartBehavior;
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
const List<int> items = <int>[0, 1, 2, 3, 4, 5];
void main() {
testWidgets('Tap item after scroll - horizontal', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Tap item after scroll - horizontal', (WidgetTester tester) async {
final List<int> tapped = <int>[];
await tester.pumpWidget(
Directionality(
@ -51,7 +52,7 @@ void main() {
expect(tapped, equals(<int>[2]));
});
testWidgets('Tap item after scroll - vertical', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Tap item after scroll - vertical', (WidgetTester tester) async {
final List<int> tapped = <int>[];
await tester.pumpWidget(
Directionality(
@ -94,7 +95,7 @@ void main() {
expect(tapped, equals(<int>[1])); // the center of the third item is off-screen so it shouldn't get hit
});
testWidgets('Padding scroll anchor start', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Padding scroll anchor start', (WidgetTester tester) async {
final List<int> tapped = <int>[];
await tester.pumpWidget(
@ -126,7 +127,7 @@ void main() {
expect(tapped, equals(<int>[0, 1, 1]));
});
testWidgets('Padding scroll anchor end', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Padding scroll anchor end', (WidgetTester tester) async {
final List<int> tapped = <int>[];
await tester.pumpWidget(
@ -159,7 +160,7 @@ void main() {
expect(tapped, equals(<int>[0, 1, 1]));
});
testWidgets('Tap immediately following clamped overscroll', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Tap immediately following clamped overscroll', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/5709
final List<int> tapped = <int>[];

View File

@ -4,6 +4,7 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
class ScrollPositionListener extends StatefulWidget {
const ScrollPositionListener({ super.key, required this.child, required this.log});
@ -123,9 +124,10 @@ class TestChildState extends State<TestChild> {
}
void main() {
testWidgets('Scrollable.of() dependent rebuilds when Scrollable position changes', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scrollable.of() dependent rebuilds when Scrollable position changes', (WidgetTester tester) async {
late String logValue;
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
// Changing the SingleChildScrollView's physics causes the
// ScrollController's ScrollPosition to be rebuilt.
@ -163,7 +165,7 @@ void main() {
expect(logValue, 'listener 400.0');
});
testWidgets('Scrollable.of() is possible using ScrollNotification context', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scrollable.of() is possible using ScrollNotification context', (WidgetTester tester) async {
late ScrollNotification notification;
await tester.pumpWidget(NotificationListener<ScrollNotification>(
@ -183,9 +185,11 @@ void main() {
expect(Scrollable.of(notification.context!), equals(scrollableElement.state));
});
testWidgets('Static Scrollable methods can target a specific axis', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Static Scrollable methods can target a specific axis', (WidgetTester tester) async {
final TestScrollController horizontalController = TestScrollController(deferLoading: true);
addTearDown(horizontalController.dispose);
final TestScrollController verticalController = TestScrollController(deferLoading: false);
addTearDown(verticalController.dispose);
late final AxisDirection foundAxisDirection;
late final bool foundRecommendation;
@ -218,7 +222,7 @@ void main() {
expect(foundRecommendation, isTrue);
});
testWidgets('Axis targeting scrollables establishes the correct dependencies', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Axis targeting scrollables establishes the correct dependencies', (WidgetTester tester) async {
final GlobalKey<TestScrollableState> verticalKey = GlobalKey<TestScrollableState>();
final GlobalKey<TestChildState> childKey = GlobalKey<TestChildState>();
@ -237,12 +241,15 @@ void main() {
expect(verticalKey.currentState!.dependenciesChanged, 1);
expect(childKey.currentState!.dependenciesChanged, 1);
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
// Change the horizontal ScrollView, adding a controller
await tester.pumpWidget(Directionality(
textDirection: TextDirection.ltr,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
controller: ScrollController(),
controller: controller,
child: TestScrollable(
key: verticalKey,
child: TestChild(key: childKey),

View File

@ -5,9 +5,10 @@
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() {
testWidgets('CustomScrollView restoration', (WidgetTester tester) async {
testWidgetsWithLeakTracking('CustomScrollView restoration', (WidgetTester tester) async {
await tester.pumpWidget(
TestHarness(
child: CustomScrollView(
@ -33,7 +34,7 @@ void main() {
await restoreScrollAndVerify(tester);
});
testWidgets('ListView restoration', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ListView restoration', (WidgetTester tester) async {
await tester.pumpWidget(
TestHarness(
child: ListView(
@ -53,7 +54,7 @@ void main() {
await restoreScrollAndVerify(tester);
});
testWidgets('ListView.builder restoration', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ListView.builder restoration', (WidgetTester tester) async {
await tester.pumpWidget(
TestHarness(
child: ListView.builder(
@ -70,7 +71,7 @@ void main() {
await restoreScrollAndVerify(tester);
});
testWidgets('ListView.separated restoration', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ListView.separated restoration', (WidgetTester tester) async {
await tester.pumpWidget(
TestHarness(
child: ListView.separated(
@ -89,7 +90,7 @@ void main() {
await restoreScrollAndVerify(tester);
});
testWidgets('ListView.custom restoration', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ListView.custom restoration', (WidgetTester tester) async {
await tester.pumpWidget(
TestHarness(
child: ListView.custom(
@ -111,7 +112,7 @@ void main() {
await restoreScrollAndVerify(tester);
});
testWidgets('GridView restoration', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView restoration', (WidgetTester tester) async {
await tester.pumpWidget(
TestHarness(
child: GridView(
@ -132,7 +133,7 @@ void main() {
await restoreScrollAndVerify(tester);
});
testWidgets('GridView.builder restoration', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView.builder restoration', (WidgetTester tester) async {
await tester.pumpWidget(
TestHarness(
child: GridView.builder(
@ -150,7 +151,7 @@ void main() {
await restoreScrollAndVerify(tester);
});
testWidgets('GridView.custom restoration', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView.custom restoration', (WidgetTester tester) async {
await tester.pumpWidget(
TestHarness(
child: GridView.custom(
@ -173,7 +174,7 @@ void main() {
await restoreScrollAndVerify(tester);
});
testWidgets('GridView.count restoration', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView.count restoration', (WidgetTester tester) async {
await tester.pumpWidget(
TestHarness(
child: GridView.count(
@ -194,7 +195,7 @@ void main() {
await restoreScrollAndVerify(tester);
});
testWidgets('GridView.extent restoration', (WidgetTester tester) async {
testWidgetsWithLeakTracking('GridView.extent restoration', (WidgetTester tester) async {
await tester.pumpWidget(
TestHarness(
child: GridView.extent(
@ -215,7 +216,7 @@ void main() {
await restoreScrollAndVerify(tester);
});
testWidgets('SingleChildScrollView restoration', (WidgetTester tester) async {
testWidgetsWithLeakTracking('SingleChildScrollView restoration', (WidgetTester tester) async {
await tester.pumpWidget(
TestHarness(
child: SingleChildScrollView(
@ -262,7 +263,7 @@ void main() {
expect(tester.getTopLeft(find.text('Tile 1')), const Offset(0, -475));
});
testWidgets('PageView restoration', (WidgetTester tester) async {
testWidgetsWithLeakTracking('PageView restoration', (WidgetTester tester) async {
await tester.pumpWidget(
TestHarness(
child: PageView(
@ -278,7 +279,7 @@ void main() {
await pageViewScrollAndRestore(tester);
});
testWidgets('PageView.builder restoration', (WidgetTester tester) async {
testWidgetsWithLeakTracking('PageView.builder restoration', (WidgetTester tester) async {
await tester.pumpWidget(
TestHarness(
child: PageView.builder(
@ -294,7 +295,7 @@ void main() {
await pageViewScrollAndRestore(tester);
});
testWidgets('PageView.custom restoration', (WidgetTester tester) async {
testWidgetsWithLeakTracking('PageView.custom restoration', (WidgetTester tester) async {
await tester.pumpWidget(
TestHarness(
child: PageView.custom(
@ -315,7 +316,7 @@ void main() {
await pageViewScrollAndRestore(tester);
});
testWidgets('ListWheelScrollView restoration', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ListWheelScrollView restoration', (WidgetTester tester) async {
await tester.pumpWidget(
TestHarness(
child: ListWheelScrollView(
@ -332,7 +333,7 @@ void main() {
await restoreScrollAndVerify(tester, secondOffset: 542);
});
testWidgets('ListWheelScrollView.useDelegate restoration', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ListWheelScrollView.useDelegate restoration', (WidgetTester tester) async {
await tester.pumpWidget(
TestHarness(
child: ListWheelScrollView.useDelegate(
@ -354,7 +355,7 @@ void main() {
await restoreScrollAndVerify(tester, secondOffset: 542);
});
testWidgets('NestedScrollView restoration', (WidgetTester tester) async {
testWidgetsWithLeakTracking('NestedScrollView restoration', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
home: TestHarness(
@ -422,7 +423,7 @@ void main() {
expect(find.text('Tile 10'), findsOneWidget);
});
testWidgets('RestorationData is flushed even if no frame is scheduled', (WidgetTester tester) async {
testWidgetsWithLeakTracking('RestorationData is flushed even if no frame is scheduled', (WidgetTester tester) async {
await tester.pumpWidget(
TestHarness(
child: ListView(

View File

@ -9,6 +9,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import 'clipboard_utils.dart';
import 'keyboard_utils.dart';
@ -36,7 +37,7 @@ void main() {
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, null);
});
testWidgets('mouse can select multiple widgets', (WidgetTester tester) async {
testWidgetsWithLeakTracking('mouse can select multiple widgets', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: SelectionArea(
selectionControls: materialTextSelectionControls,
@ -74,7 +75,7 @@ void main() {
await gesture.up();
});
testWidgets('mouse can select multiple widgets - horizontal', (WidgetTester tester) async {
testWidgetsWithLeakTracking('mouse can select multiple widgets - horizontal', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: SelectionArea(
selectionControls: materialTextSelectionControls,
@ -107,7 +108,7 @@ void main() {
await gesture.up();
});
testWidgets('mouse can select multiple widgets on double-click drag', (WidgetTester tester) async {
testWidgetsWithLeakTracking('mouse can select multiple widgets on double-click drag', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: SelectionArea(
selectionControls: materialTextSelectionControls,
@ -151,7 +152,7 @@ void main() {
await gesture.up();
}, skip: kIsWeb); // https://github.com/flutter/flutter/issues/125582.
testWidgets('mouse can select multiple widgets on double-click drag - horizontal', (WidgetTester tester) async {
testWidgetsWithLeakTracking('mouse can select multiple widgets on double-click drag - horizontal', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: SelectionArea(
selectionControls: materialTextSelectionControls,
@ -190,8 +191,9 @@ void main() {
await gesture.up();
}, skip: kIsWeb); // https://github.com/flutter/flutter/issues/125582.
testWidgets('select to scroll forward', (WidgetTester tester) async {
testWidgetsWithLeakTracking('select to scroll forward', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(MaterialApp(
home: SelectionArea(
selectionControls: materialTextSelectionControls,
@ -239,8 +241,9 @@ void main() {
await gesture.up();
});
testWidgets('select to scroll works for small scrollable', (WidgetTester tester) async {
testWidgetsWithLeakTracking('select to scroll works for small scrollable', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: false),
home: SelectionArea(
@ -285,8 +288,9 @@ void main() {
expect(tester.takeException(), isNull);
});
testWidgets('select to scroll backward', (WidgetTester tester) async {
testWidgetsWithLeakTracking('select to scroll backward', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(MaterialApp(
home: SelectionArea(
selectionControls: materialTextSelectionControls,
@ -333,8 +337,9 @@ void main() {
expect(paragraph3.selections[0], const TextSelection(baseOffset: 6, extentOffset: 0));
});
testWidgets('select to scroll forward - horizontal', (WidgetTester tester) async {
testWidgetsWithLeakTracking('select to scroll forward - horizontal', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(MaterialApp(
home: SelectionArea(
selectionControls: materialTextSelectionControls,
@ -381,8 +386,9 @@ void main() {
await gesture.up();
});
testWidgets('select to scroll backward - horizontal', (WidgetTester tester) async {
testWidgetsWithLeakTracking('select to scroll backward - horizontal', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(MaterialApp(
home: SelectionArea(
selectionControls: materialTextSelectionControls,
@ -430,8 +436,9 @@ void main() {
await gesture.up();
});
testWidgets('preserve selection when out of view.', (WidgetTester tester) async {
testWidgetsWithLeakTracking('preserve selection when out of view.', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(MaterialApp(
home: SelectionArea(
selectionControls: materialTextSelectionControls,
@ -477,8 +484,9 @@ void main() {
expect(paragraph50.selections[0], const TextSelection(baseOffset: 2, extentOffset: 4));
});
testWidgets('can select all non-Apple', (WidgetTester tester) async {
testWidgetsWithLeakTracking('can select all non-Apple', (WidgetTester tester) async {
final FocusNode node = FocusNode();
addTearDown(node.dispose);
await tester.pumpWidget(MaterialApp(
home: SelectionArea(
focusNode: node,
@ -503,8 +511,9 @@ void main() {
expect(find.text('Item 13'), findsNothing);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.windows, TargetPlatform.linux, TargetPlatform.fuchsia }));
testWidgets('can select all - Apple', (WidgetTester tester) async {
testWidgetsWithLeakTracking('can select all - Apple', (WidgetTester tester) async {
final FocusNode node = FocusNode();
addTearDown(node.dispose);
await tester.pumpWidget(MaterialApp(
home: SelectionArea(
focusNode: node,
@ -529,8 +538,9 @@ void main() {
expect(find.text('Item 13'), findsNothing);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('select to scroll by dragging selection handles forward', (WidgetTester tester) async {
testWidgetsWithLeakTracking('select to scroll by dragging selection handles forward', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(MaterialApp(
home: SelectionArea(
selectionControls: materialTextSelectionControls,
@ -586,8 +596,9 @@ void main() {
await gesture.up();
});
testWidgets('select to scroll by dragging start selection handle stops scroll when released', (WidgetTester tester) async {
testWidgetsWithLeakTracking('select to scroll by dragging start selection handle stops scroll when released', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(MaterialApp(
home: SelectionArea(
selectionControls: materialTextSelectionControls,
@ -640,8 +651,9 @@ void main() {
expect(controller.offset, previousOffset);
});
testWidgets('select to scroll by dragging end selection handle stops scroll when released', (WidgetTester tester) async {
testWidgetsWithLeakTracking('select to scroll by dragging end selection handle stops scroll when released', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(MaterialApp(
home: SelectionArea(
selectionControls: materialTextSelectionControls,
@ -693,9 +705,11 @@ void main() {
expect(controller.offset, previousOffset);
});
testWidgets('keyboard selection should auto scroll - vertical', (WidgetTester tester) async {
testWidgetsWithLeakTracking('keyboard selection should auto scroll - vertical', (WidgetTester tester) async {
final FocusNode node = FocusNode();
addTearDown(node.dispose);
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(MaterialApp(
home: SelectionArea(
focusNode: node,
@ -756,9 +770,11 @@ void main() {
expect(controller.offset, 72.0);
}, variant: TargetPlatformVariant.all());
testWidgets('keyboard selection should auto scroll - vertical reversed', (WidgetTester tester) async {
testWidgetsWithLeakTracking('keyboard selection should auto scroll - vertical reversed', (WidgetTester tester) async {
final FocusNode node = FocusNode();
addTearDown(node.dispose);
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(MaterialApp(
home: SelectionArea(
focusNode: node,
@ -820,9 +836,11 @@ void main() {
expect(controller.offset, 72.0);
}, variant: TargetPlatformVariant.all());
testWidgets('keyboard selection should auto scroll - horizontal', (WidgetTester tester) async {
testWidgetsWithLeakTracking('keyboard selection should auto scroll - horizontal', (WidgetTester tester) async {
final FocusNode node = FocusNode();
addTearDown(node.dispose);
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(MaterialApp(
home: SelectionArea(
focusNode: node,
@ -866,9 +884,11 @@ void main() {
expect(controller.offset, 352.0);
}, variant: TargetPlatformVariant.all());
testWidgets('keyboard selection should auto scroll - horizontal reversed', (WidgetTester tester) async {
testWidgetsWithLeakTracking('keyboard selection should auto scroll - horizontal reversed', (WidgetTester tester) async {
final FocusNode node = FocusNode();
addTearDown(node.dispose);
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(MaterialApp(
home: SelectionArea(
focusNode: node,
@ -922,8 +942,9 @@ void main() {
}, variant: TargetPlatformVariant.all());
group('Complex cases', () {
testWidgets('selection starts outside of the scrollable', (WidgetTester tester) async {
testWidgetsWithLeakTracking('selection starts outside of the scrollable', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(MaterialApp(
home: SelectionArea(
selectionControls: materialTextSelectionControls,
@ -966,9 +987,11 @@ void main() {
expect(controller.offset, 1000.0);
});
testWidgets('nested scrollables keep selection alive', (WidgetTester tester) async {
testWidgetsWithLeakTracking('nested scrollables keep selection alive', (WidgetTester tester) async {
final ScrollController outerController = ScrollController();
addTearDown(outerController.dispose);
final ScrollController innerController = ScrollController();
addTearDown(innerController.dispose);
await tester.pumpWidget(MaterialApp(
home: SelectionArea(
selectionControls: materialTextSelectionControls,
@ -1030,9 +1053,11 @@ void main() {
expect(innerParagraph24.selections[0], const TextSelection(baseOffset: 0, extentOffset: 2));
});
testWidgets('can copy off screen selection - Apple', (WidgetTester tester) async {
testWidgetsWithLeakTracking('can copy off screen selection - Apple', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(MaterialApp(
home: SelectionArea(
focusNode: focusNode,
@ -1071,9 +1096,11 @@ void main() {
expect(clipboardData['text'], 'em 0It');
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('can copy off screen selection - non-Apple', (WidgetTester tester) async {
testWidgetsWithLeakTracking('can copy off screen selection - non-Apple', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(MaterialApp(
home: SelectionArea(
focusNode: focusNode,

View File

@ -6,6 +6,7 @@ import 'package:flutter/gestures.dart' show DragStartBehavior;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import 'semantics_tester.dart';
@ -16,7 +17,7 @@ void main() {
debugResetSemanticsIdCounter();
});
testWidgets('scrollable exposes the correct semantic actions', (WidgetTester tester) async {
testWidgetsWithLeakTracking('scrollable exposes the correct semantic actions', (WidgetTester tester) async {
semantics = SemanticsTester(tester);
await tester.pumpWidget(
Directionality(
@ -42,7 +43,7 @@ void main() {
semantics.dispose();
});
testWidgets('showOnScreen works in scrollable', (WidgetTester tester) async {
testWidgetsWithLeakTracking('showOnScreen works in scrollable', (WidgetTester tester) async {
semantics = SemanticsTester(tester); // enables semantics tree generation
const double kItemHeight = 40.0;
@ -57,6 +58,7 @@ void main() {
final ScrollController scrollController = ScrollController(
initialScrollOffset: kItemHeight / 2,
);
addTearDown(scrollController.dispose);
await tester.pumpWidget(
Directionality(
@ -80,7 +82,7 @@ void main() {
semantics.dispose();
});
testWidgets('showOnScreen works with pinned app bar and sliver list', (WidgetTester tester) async {
testWidgetsWithLeakTracking('showOnScreen works with pinned app bar and sliver list', (WidgetTester tester) async {
semantics = SemanticsTester(tester); // enables semantics tree generation
const double kItemHeight = 100.0;
@ -96,6 +98,7 @@ void main() {
final ScrollController scrollController = ScrollController(
initialScrollOffset: kItemHeight / 2,
);
addTearDown(scrollController.dispose);
await tester.pumpWidget(Directionality(
textDirection: TextDirection.ltr,
@ -142,7 +145,7 @@ void main() {
semantics.dispose();
});
testWidgets('showOnScreen works with pinned app bar and individual slivers', (WidgetTester tester) async {
testWidgetsWithLeakTracking('showOnScreen works with pinned app bar and individual slivers', (WidgetTester tester) async {
semantics = SemanticsTester(tester); // enables semantics tree generation
const double kItemHeight = 100.0;
@ -166,6 +169,7 @@ void main() {
final ScrollController scrollController = ScrollController(
initialScrollOffset: 2.5 * kItemHeight,
);
addTearDown(scrollController.dispose);
await tester.pumpWidget(Directionality(
textDirection: TextDirection.ltr,
@ -210,7 +214,7 @@ void main() {
semantics.dispose();
});
testWidgets('correct scrollProgress', (WidgetTester tester) async {
testWidgetsWithLeakTracking('correct scrollProgress', (WidgetTester tester) async {
semantics = SemanticsTester(tester);
await tester.pumpWidget(Directionality(
@ -253,7 +257,7 @@ void main() {
semantics.dispose();
});
testWidgets('correct scrollProgress for unbound', (WidgetTester tester) async {
testWidgetsWithLeakTracking('correct scrollProgress for unbound', (WidgetTester tester) async {
semantics = SemanticsTester(tester);
await tester.pumpWidget(Directionality(
@ -303,7 +307,7 @@ void main() {
semantics.dispose();
});
testWidgets('Semantics tree is populated mid-scroll', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Semantics tree is populated mid-scroll', (WidgetTester tester) async {
semantics = SemanticsTester(tester);
final List<Widget> children = List<Widget>.generate(80, (int i) => SizedBox(
@ -328,7 +332,7 @@ void main() {
semantics.dispose();
});
testWidgets('Can toggle semantics on, off, on without crash', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Can toggle semantics on, off, on without crash', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -434,7 +438,7 @@ void main() {
});
testWidgets('brings item above leading edge to leading edge', (WidgetTester tester) async {
testWidgetsWithLeakTracking('brings item above leading edge to leading edge', (WidgetTester tester) async {
semantics = SemanticsTester(tester); // enables semantics tree generation
await tester.pumpWidget(widgetUnderTest);
@ -450,7 +454,7 @@ void main() {
semantics.dispose();
});
testWidgets('brings item below trailing edge to trailing edge', (WidgetTester tester) async {
testWidgetsWithLeakTracking('brings item below trailing edge to trailing edge', (WidgetTester tester) async {
semantics = SemanticsTester(tester); // enables semantics tree generation
await tester.pumpWidget(widgetUnderTest);
@ -466,7 +470,7 @@ void main() {
semantics.dispose();
});
testWidgets('does not change position of items already fully on-screen', (WidgetTester tester) async {
testWidgetsWithLeakTracking('does not change position of items already fully on-screen', (WidgetTester tester) async {
semantics = SemanticsTester(tester); // enables semantics tree generation
await tester.pumpWidget(widgetUnderTest);
@ -536,10 +540,13 @@ void main() {
),
),
);
});
testWidgets('brings item above leading edge to leading edge', (WidgetTester tester) async {
tearDown(() {
scrollController.dispose();
});
testWidgetsWithLeakTracking('brings item above leading edge to leading edge', (WidgetTester tester) async {
semantics = SemanticsTester(tester); // enables semantics tree generation
await tester.pumpWidget(widgetUnderTest);
@ -555,7 +562,7 @@ void main() {
semantics.dispose();
});
testWidgets('brings item below trailing edge to trailing edge', (WidgetTester tester) async {
testWidgetsWithLeakTracking('brings item below trailing edge to trailing edge', (WidgetTester tester) async {
semantics = SemanticsTester(tester); // enables semantics tree generation
await tester.pumpWidget(widgetUnderTest);
@ -571,7 +578,7 @@ void main() {
semantics.dispose();
});
testWidgets('does not change position of items already fully on-screen', (WidgetTester tester) async {
testWidgetsWithLeakTracking('does not change position of items already fully on-screen', (WidgetTester tester) async {
semantics = SemanticsTester(tester); // enables semantics tree generation
await tester.pumpWidget(widgetUnderTest);
@ -589,7 +596,7 @@ void main() {
});
testWidgets('transform of inner node from useTwoPaneSemantics scrolls correctly with nested scrollables', (WidgetTester tester) async {
testWidgetsWithLeakTracking('transform of inner node from useTwoPaneSemantics scrolls correctly with nested scrollables', (WidgetTester tester) async {
semantics = SemanticsTester(tester); // enables semantics tree generation
// Context: https://github.com/flutter/flutter/issues/61631

View File

@ -5,13 +5,17 @@
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import 'semantics_tester.dart';
void main() {
testWidgets('Traversal Order of SliverList', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Traversal Order of SliverList', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
final ScrollController controller = ScrollController(initialScrollOffset: 3000.0);
addTearDown(controller.dispose);
final List<Widget> listChildren = List<Widget>.generate(30, (int i) {
return SizedBox(
height: 200.0,
@ -38,7 +42,7 @@ void main() {
child: MediaQuery(
data: const MediaQueryData(),
child: CustomScrollView(
controller: ScrollController(initialScrollOffset: 3000.0),
controller: controller,
semanticChildCount: 30,
slivers: <Widget>[
SliverList(
@ -182,9 +186,12 @@ void main() {
semantics.dispose();
});
testWidgets('Traversal Order of SliverFixedExtentList', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Traversal Order of SliverFixedExtentList', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
final ScrollController controller = ScrollController(initialScrollOffset: 3000.0);
addTearDown(controller.dispose);
final List<Widget> listChildren = List<Widget>.generate(30, (int i) {
return SizedBox(
height: 200.0,
@ -211,7 +218,7 @@ void main() {
child: MediaQuery(
data: const MediaQueryData(),
child: CustomScrollView(
controller: ScrollController(initialScrollOffset: 3000.0),
controller: controller,
slivers: <Widget>[
SliverFixedExtentList(
itemExtent: 200.0,
@ -321,9 +328,12 @@ void main() {
semantics.dispose();
});
testWidgets('Traversal Order of SliverGrid', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Traversal Order of SliverGrid', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
final ScrollController controller = ScrollController(initialScrollOffset: 1600.0);
addTearDown(controller.dispose);
final List<Widget> listChildren = List<Widget>.generate(30, (int i) {
return SizedBox(
height: 200.0,
@ -338,7 +348,7 @@ void main() {
child: MediaQuery(
data: const MediaQueryData(),
child: CustomScrollView(
controller: ScrollController(initialScrollOffset: 1600.0),
controller: controller,
slivers: <Widget>[
SliverGrid.count(
crossAxisCount: 2,
@ -449,9 +459,12 @@ void main() {
semantics.dispose();
});
testWidgets('Traversal Order of List of individual slivers', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Traversal Order of List of individual slivers', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
final ScrollController controller = ScrollController(initialScrollOffset: 3000.0);
addTearDown(controller.dispose);
final List<Widget> listChildren = List<Widget>.generate(30, (int i) {
return SliverToBoxAdapter(
child: SizedBox(
@ -480,7 +493,7 @@ void main() {
child: MediaQuery(
data: const MediaQueryData(),
child: CustomScrollView(
controller: ScrollController(initialScrollOffset: 3000.0),
controller: controller,
slivers: listChildren,
),
),
@ -585,9 +598,12 @@ void main() {
semantics.dispose();
});
testWidgets('Traversal Order of in a SingleChildScrollView', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Traversal Order of in a SingleChildScrollView', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
final ScrollController controller = ScrollController(initialScrollOffset: 3000.0);
addTearDown(controller.dispose);
final List<Widget> listChildren = List<Widget>.generate(30, (int i) {
return SizedBox(
height: 200.0,
@ -614,7 +630,7 @@ void main() {
child: MediaQuery(
data: const MediaQueryData(),
child: SingleChildScrollView(
controller: ScrollController(initialScrollOffset: 3000.0),
controller: controller,
child: Column(
children: listChildren,
),
@ -671,7 +687,7 @@ void main() {
semantics.dispose();
});
testWidgets('Traversal Order with center child', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Traversal Order with center child', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(Semantics(

View File

@ -10,6 +10,7 @@ import 'package:flutter/rendering.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import 'semantics_tester.dart';
@ -109,7 +110,7 @@ void resetScrollOffset(WidgetTester tester) {
}
void main() {
testWidgets('Flings on different platforms', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Flings on different platforms', (WidgetTester tester) async {
await pumpTest(tester, TargetPlatform.android);
await tester.fling(find.byType(Scrollable), const Offset(0.0, -dragOffset), 1000.0);
expect(getScrollOffset(tester), dragOffset);
@ -145,7 +146,7 @@ void main() {
expect(macOSResult, lessThan(iOSResult)); // iOS is slipperier than macOS
});
testWidgets('Holding scroll', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Holding scroll', (WidgetTester tester) async {
await pumpTest(tester, debugDefaultTargetPlatformOverride);
await tester.drag(find.byType(Scrollable), const Offset(0.0, 200.0), touchSlopY: 0.0);
expect(getScrollOffset(tester), -200.0);
@ -164,7 +165,7 @@ void main() {
expect(getScrollOffset(tester), 0.0);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('Repeated flings builds momentum', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Repeated flings builds momentum', (WidgetTester tester) async {
await pumpTest(tester, debugDefaultTargetPlatformOverride);
await tester.fling(find.byType(Scrollable), const Offset(0.0, -dragOffset), 1000.0);
await tester.pump(); // trigger fling
@ -177,7 +178,7 @@ void main() {
expect(getScrollVelocity(tester), greaterThan(1100.0));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('Repeated flings do not build momentum on Android', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Repeated flings do not build momentum on Android', (WidgetTester tester) async {
await pumpTest(tester, TargetPlatform.android);
await tester.fling(find.byType(Scrollable), const Offset(0.0, -dragOffset), 1000.0);
await tester.pump(); // trigger fling
@ -190,7 +191,7 @@ void main() {
expect(getScrollVelocity(tester), moreOrLessEquals(1000.0));
});
testWidgets('A slower final fling does not apply carried momentum', (WidgetTester tester) async {
testWidgetsWithLeakTracking('A slower final fling does not apply carried momentum', (WidgetTester tester) async {
await pumpTest(tester, debugDefaultTargetPlatformOverride);
await tester.fling(find.byType(Scrollable), const Offset(0.0, -dragOffset), 1000.0);
await tester.pump(); // trigger fling
@ -207,7 +208,7 @@ void main() {
expect(getScrollVelocity(tester), lessThan(200.0));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('No iOS/macOS momentum build with flings in opposite directions', (WidgetTester tester) async {
testWidgetsWithLeakTracking('No iOS/macOS momentum build with flings in opposite directions', (WidgetTester tester) async {
await pumpTest(tester, debugDefaultTargetPlatformOverride);
await tester.fling(find.byType(Scrollable), const Offset(0.0, -dragOffset), 1000.0);
await tester.pump(); // trigger fling
@ -220,7 +221,7 @@ void main() {
expect(getScrollVelocity(tester), -1000.0);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('No iOS/macOS momentum kept on hold gestures', (WidgetTester tester) async {
testWidgetsWithLeakTracking('No iOS/macOS momentum kept on hold gestures', (WidgetTester tester) async {
await pumpTest(tester, debugDefaultTargetPlatformOverride);
await tester.fling(find.byType(Scrollable), const Offset(0.0, -dragOffset), 1000.0);
await tester.pump(); // trigger fling
@ -233,7 +234,7 @@ void main() {
expect(getScrollVelocity(tester), 0.0);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('Drags creeping unaffected on Android', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Drags creeping unaffected on Android', (WidgetTester tester) async {
await pumpTest(tester, TargetPlatform.android);
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(Scrollable), warnIfMissed: true));
await gesture.moveBy(const Offset(0.0, -0.5));
@ -244,7 +245,7 @@ void main() {
expect(getScrollOffset(tester), 1.5);
});
testWidgets('Drags creeping must break threshold on iOS/macOS', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Drags creeping must break threshold on iOS/macOS', (WidgetTester tester) async {
await pumpTest(tester, debugDefaultTargetPlatformOverride);
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(Scrollable), warnIfMissed: true));
await gesture.moveBy(const Offset(0.0, -0.5));
@ -264,7 +265,7 @@ void main() {
expect(getScrollOffset(tester), 0.5);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('Big drag over threshold magnitude preserved on iOS/macOS', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Big drag over threshold magnitude preserved on iOS/macOS', (WidgetTester tester) async {
await pumpTest(tester, debugDefaultTargetPlatformOverride);
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(Scrollable), warnIfMissed: true));
await gesture.moveBy(const Offset(0.0, -30.0));
@ -272,7 +273,7 @@ void main() {
expect(getScrollOffset(tester), 30.0);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('Slow threshold breaks are attenuated on iOS/macOS', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Slow threshold breaks are attenuated on iOS/macOS', (WidgetTester tester) async {
await pumpTest(tester, debugDefaultTargetPlatformOverride);
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(Scrollable), warnIfMissed: true));
// This is a typical 'hesitant' iOS scroll start.
@ -283,7 +284,7 @@ void main() {
expect(getScrollOffset(tester), moreOrLessEquals(11.16666666666666673));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('Small continuing motion preserved on iOS/macOS', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Small continuing motion preserved on iOS/macOS', (WidgetTester tester) async {
await pumpTest(tester, debugDefaultTargetPlatformOverride);
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(Scrollable), warnIfMissed: true));
await gesture.moveBy(const Offset(0.0, -30.0)); // Break threshold.
@ -296,7 +297,7 @@ void main() {
expect(getScrollOffset(tester), 31.5);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('Motion stop resets threshold on iOS/macOS', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Motion stop resets threshold on iOS/macOS', (WidgetTester tester) async {
await pumpTest(tester, debugDefaultTargetPlatformOverride);
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(Scrollable), warnIfMissed: true));
await gesture.moveBy(const Offset(0.0, -30.0)); // Break threshold.
@ -319,7 +320,7 @@ void main() {
expect(getScrollOffset(tester), 32.5);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('Scroll pointer signals are handled on Fuchsia', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scroll pointer signals are handled on Fuchsia', (WidgetTester tester) async {
await pumpTest(tester, TargetPlatform.fuchsia);
final Offset scrollEventLocation = tester.getCenter(find.byType(Viewport));
final TestPointer testPointer = TestPointer(1, ui.PointerDeviceKind.mouse);
@ -332,7 +333,7 @@ void main() {
expect(getScrollOffset(tester), 0.0);
});
testWidgets('Scroll pointer signals are handled when there is competition', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scroll pointer signals are handled when there is competition', (WidgetTester tester) async {
// This is a regression test. When there are multiple scrollables listening
// to the same event, for example when scrollables are nested, there used
// to be exceptions at scrolling events.
@ -349,7 +350,7 @@ void main() {
expect(getScrollOffset(tester), 0.0);
});
testWidgets('Scroll pointer signals are ignored when scrolling is disabled', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scroll pointer signals are ignored when scrolling is disabled', (WidgetTester tester) async {
await pumpTest(tester, TargetPlatform.fuchsia, scrollable: false);
final Offset scrollEventLocation = tester.getCenter(find.byType(Viewport));
final TestPointer testPointer = TestPointer(1, ui.PointerDeviceKind.mouse);
@ -359,10 +360,12 @@ void main() {
expect(getScrollOffset(tester), 0.0);
});
testWidgets('Holding scroll and Scroll pointer signal will update ScrollDirection.forward / ScrollDirection.reverse', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Holding scroll and Scroll pointer signal will update ScrollDirection.forward / ScrollDirection.reverse', (WidgetTester tester) async {
ScrollDirection? lastUserScrollingDirection;
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await pumpTest(tester, TargetPlatform.fuchsia, controller: controller);
controller.addListener(() {
@ -393,7 +396,7 @@ void main() {
});
testWidgets('Scrolls in correct direction when scroll axis is reversed', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scrolls in correct direction when scroll axis is reversed', (WidgetTester tester) async {
await pumpTest(tester, TargetPlatform.fuchsia, reverse: true);
final Offset scrollEventLocation = tester.getCenter(find.byType(Viewport));
@ -405,7 +408,7 @@ void main() {
expect(getScrollOffset(tester), 20.0);
});
testWidgets('Scrolls horizontally when shift is pressed by default', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scrolls horizontally when shift is pressed by default', (WidgetTester tester) async {
await pumpTest(
tester,
debugDefaultTargetPlatformOverride,
@ -432,7 +435,7 @@ void main() {
expect(getScrollOffset(tester), 20.0);
}, variant: TargetPlatformVariant.all());
testWidgets('Scroll axis is not flipped for trackpad', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scroll axis is not flipped for trackpad', (WidgetTester tester) async {
await pumpTest(
tester,
debugDefaultTargetPlatformOverride,
@ -459,7 +462,7 @@ void main() {
expect(getScrollOffset(tester), 0.0);
}, variant: TargetPlatformVariant.all());
testWidgets('Scrolls horizontally when custom key is pressed', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scrolls horizontally when custom key is pressed', (WidgetTester tester) async {
await pumpTest(
tester,
debugDefaultTargetPlatformOverride,
@ -487,7 +490,7 @@ void main() {
expect(getScrollOffset(tester), 20.0);
}, variant: TargetPlatformVariant.all());
testWidgets('Still scrolls horizontally when other keys are pressed at the same time', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Still scrolls horizontally when other keys are pressed at the same time', (WidgetTester tester) async {
await pumpTest(
tester,
debugDefaultTargetPlatformOverride,
@ -536,7 +539,7 @@ void main() {
);
}
testWidgets('Hold does not disable user interaction', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Hold does not disable user interaction', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/66816.
await pumpTestWidget(tester, canDrag: true);
final RenderIgnorePointer renderIgnorePointer = tester.renderObject<RenderIgnorePointer>(
@ -555,7 +558,7 @@ void main() {
expect(renderIgnorePointer.ignoring, false);
});
testWidgets('Drag disables user interaction when recognized', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Drag disables user interaction when recognized', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/66816.
await pumpTestWidget(tester, canDrag: true);
final RenderIgnorePointer renderIgnorePointer = tester.renderObject<RenderIgnorePointer>(
@ -577,7 +580,7 @@ void main() {
expect(renderIgnorePointer.ignoring, false);
});
testWidgets('Ballistic disables user interaction until it stops', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Ballistic disables user interaction until it stops', (WidgetTester tester) async {
await pumpTestWidget(tester, canDrag: true);
final RenderIgnorePointer renderIgnorePointer = tester.renderObject<RenderIgnorePointer>(
find.descendant(of: find.byType(CustomScrollView), matching: find.byType(IgnorePointer)),
@ -595,11 +598,13 @@ void main() {
});
});
testWidgets('Can recommendDeferredLoadingForContext - animation', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Can recommendDeferredLoadingForContext - animation', (WidgetTester tester) async {
final List<String> widgetTracker = <String>[];
int cheapWidgets = 0;
int expensiveWidgets = 0;
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(Directionality(
textDirection: TextDirection.ltr,
child: ListView.builder(
@ -650,7 +655,7 @@ void main() {
expect(widgetTracker.skip(17).skip(25).skip(70).every((String type) => type == 'expensive'), true);
});
testWidgets('Can recommendDeferredLoadingForContext - ballistics', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Can recommendDeferredLoadingForContext - ballistics', (WidgetTester tester) async {
int cheapWidgets = 0;
int expensiveWidgets = 0;
await tester.pumpWidget(Directionality(
@ -687,7 +692,7 @@ void main() {
expect(cheapWidgets, 21);
});
testWidgets('Can recommendDeferredLoadingForContext - override heuristic', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Can recommendDeferredLoadingForContext - override heuristic', (WidgetTester tester) async {
int cheapWidgets = 0;
int expensiveWidgets = 0;
await tester.pumpWidget(Directionality(
@ -731,7 +736,7 @@ void main() {
expect(physics.count, 44 + 17);
});
testWidgets('Can recommendDeferredLoadingForContext - override heuristic and always return true', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Can recommendDeferredLoadingForContext - override heuristic and always return true', (WidgetTester tester) async {
int cheapWidgets = 0;
int expensiveWidgets = 0;
await tester.pumpWidget(Directionality(
@ -772,8 +777,9 @@ void main() {
expect(cheapWidgets, 61);
});
testWidgets('ensureVisible does not move PageViews', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ensureVisible does not move PageViews', (WidgetTester tester) async {
final PageController controller = PageController();
addTearDown(controller.dispose);
await tester.pumpWidget(
Directionality(
@ -855,7 +861,7 @@ void main() {
expect(targetMidLeftPage1, findsOneWidget);
});
testWidgets('ensureVisible does not move TabViews', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ensureVisible does not move TabViews', (WidgetTester tester) async {
final TickerProvider vsync = TestTickerProvider();
final TabController controller = TabController(
length: 3,
@ -942,10 +948,13 @@ void main() {
expect(targetMidLeftPage1, findsOneWidget);
});
testWidgets('PointerScroll on nested NeverScrollable ListView goes to outer Scrollable.', (WidgetTester tester) async {
testWidgetsWithLeakTracking('PointerScroll on nested NeverScrollable ListView goes to outer Scrollable.', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/70948
final ScrollController outerController = ScrollController();
addTearDown(outerController.dispose);
final ScrollController innerController = ScrollController();
addTearDown(innerController.dispose);
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: false),
home: Scaffold(
@ -999,8 +1008,10 @@ void main() {
});
// Regression test for https://github.com/flutter/flutter/issues/71949
testWidgets('Zero offset pointer scroll should not trigger an assertion.', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Zero offset pointer scroll should not trigger an assertion.', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
Widget build(double height) {
return MaterialApp(
home: Scaffold(
@ -1039,7 +1050,7 @@ void main() {
expect(tester.takeException(), null);
});
testWidgets('Accepts drag with unknown device kind by default', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Accepts drag with unknown device kind by default', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/90912.
await tester.pumpWidget(
const MaterialApp(
@ -1068,7 +1079,7 @@ void main() {
await tester.pump();
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS, TargetPlatform.android }));
testWidgets('Does not scroll with mouse pointer drag when behavior is configured to ignore them', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Does not scroll with mouse pointer drag when behavior is configured to ignore them', (WidgetTester tester) async {
await pumpTest(tester, debugDefaultTargetPlatformOverride, enableMouseDrag: false);
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(Scrollable), warnIfMissed: true), kind: ui.PointerDeviceKind.mouse);
@ -1088,7 +1099,7 @@ void main() {
await tester.pump();
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS, TargetPlatform.android }));
testWidgets("Support updating 'ScrollBehavior.dragDevices' at runtime", (WidgetTester tester) async {
testWidgetsWithLeakTracking("Support updating 'ScrollBehavior.dragDevices' at runtime", (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/111716
Widget buildFrame(Set<ui.PointerDeviceKind>? dragDevices) {
return MaterialApp(
@ -1122,7 +1133,7 @@ void main() {
expect(getScrollOffset(tester), 200.0);
});
testWidgets('Does scroll with mouse pointer drag when behavior is not configured to ignore them', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Does scroll with mouse pointer drag when behavior is not configured to ignore them', (WidgetTester tester) async {
await pumpTest(tester, debugDefaultTargetPlatformOverride);
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(Scrollable), warnIfMissed: true), kind: ui.PointerDeviceKind.mouse);
@ -1142,7 +1153,7 @@ void main() {
await tester.pump();
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS, TargetPlatform.android }));
testWidgets('Updated content dimensions correctly reflect in semantics', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Updated content dimensions correctly reflect in semantics', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/40419.
final SemanticsHandle handle = tester.ensureSemantics();
final UniqueKey listView = UniqueKey();
@ -1200,7 +1211,7 @@ void main() {
handle.dispose();
});
testWidgets('Two panel semantics is added to the sibling nodes of direct children', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Two panel semantics is added to the sibling nodes of direct children', (WidgetTester tester) async {
final SemanticsHandle handle = tester.ensureSemantics();
final UniqueKey key = UniqueKey();
await tester.pumpWidget(MaterialApp(
@ -1245,7 +1256,7 @@ void main() {
handle.dispose();
});
testWidgets('Scroll inertia cancel event', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scroll inertia cancel event', (WidgetTester tester) async {
await pumpTest(tester, null);
await tester.fling(find.byType(Scrollable), const Offset(0.0, -dragOffset), 1000.0);
expect(getScrollOffset(tester), dragOffset);
@ -1261,7 +1272,7 @@ void main() {
expect(getScrollOffset(tester), closeTo(344.0642, 0.0001));
});
testWidgets('Swapping viewports in a scrollable does not crash', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Swapping viewports in a scrollable does not crash', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
final GlobalKey key = GlobalKey();
final GlobalKey key1 = GlobalKey();
@ -1270,11 +1281,13 @@ void main() {
key: key,
viewportBuilder: (BuildContext context, ViewportOffset position) {
if (withViewPort) {
final ViewportOffset offset = ViewportOffset.zero();
addTearDown(() => offset.dispose());
return Viewport(
slivers: <Widget>[
SliverToBoxAdapter(child: Semantics(key: key1, container: true, child: const Text('text1')))
],
offset: ViewportOffset.zero(),
offset: offset,
);
}
return Semantics(key: key1, container: true, child: const Text('text1'));
@ -1306,7 +1319,7 @@ void main() {
semantics.dispose();
});
testWidgets('deltaToScrollOrigin getter', (WidgetTester tester) async {
testWidgetsWithLeakTracking('deltaToScrollOrigin getter', (WidgetTester tester) async {
await tester.pumpWidget(
const MaterialApp(
home: CustomScrollView(
@ -1327,7 +1340,7 @@ void main() {
expect(scrollable.deltaToScrollOrigin, const Offset(0.0, 200));
});
testWidgets('resolvedPhysics getter', (WidgetTester tester) async {
testWidgetsWithLeakTracking('resolvedPhysics getter', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
theme: ThemeData.light().copyWith(
@ -1357,7 +1370,7 @@ void main() {
);
});
testWidgets('dragDevices change updates widget', (WidgetTester tester) async {
testWidgetsWithLeakTracking('dragDevices change updates widget', (WidgetTester tester) async {
bool enable = false;
await tester.pumpWidget(
@ -1410,7 +1423,7 @@ void main() {
expect(getScrollOffset(tester), 200);
});
testWidgets('dragDevices change updates widget when oldWidget scrollBehavior is null', (WidgetTester tester) async {
testWidgetsWithLeakTracking('dragDevices change updates widget when oldWidget scrollBehavior is null', (WidgetTester tester) async {
ScrollBehavior? scrollBehavior;
await tester.pumpWidget(

View File

@ -8,6 +8,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/src/physics/utils.dart' show nearEqual;
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
const Color _kScrollbarColor = Color(0xFF123456);
const double _kThickness = 2.5;
@ -384,7 +385,7 @@ void main() {
scrollMetrics: metrics,
);
testWidgets('down', (WidgetTester tester) async {
testWidgetsWithLeakTracking('down', (WidgetTester tester) async {
painter.update(
metrics.copyWith(
viewportDimension: size.height,
@ -414,7 +415,7 @@ void main() {
expect(size.width - rect1.right, padding.right);
});
testWidgets('up', (WidgetTester tester) async {
testWidgetsWithLeakTracking('up', (WidgetTester tester) async {
painter.update(
metrics.copyWith(
viewportDimension: size.height,
@ -446,7 +447,7 @@ void main() {
expect(size.width - rect1.right, padding.right);
});
testWidgets('left', (WidgetTester tester) async {
testWidgetsWithLeakTracking('left', (WidgetTester tester) async {
painter.update(
metrics.copyWith(
viewportDimension: size.width,
@ -478,7 +479,7 @@ void main() {
expect(rect1.left, padding.left);
});
testWidgets('right', (WidgetTester tester) async {
testWidgetsWithLeakTracking('right', (WidgetTester tester) async {
painter.update(
metrics.copyWith(
viewportDimension: size.width,
@ -511,7 +512,7 @@ void main() {
});
});
testWidgets('thumb resizes gradually on overscroll', (WidgetTester tester) async {
testWidgetsWithLeakTracking('thumb resizes gradually on overscroll', (WidgetTester tester) async {
const EdgeInsets padding = EdgeInsets.fromLTRB(1, 2, 3, 4);
const Size size = Size(60, 300);
final double scrollExtent = size.height * 10;
@ -664,7 +665,7 @@ void main() {
expect(trackRRect.trRadius, const Radius.circular(2.0));
});
testWidgets('ScrollbarPainter asserts if no TextDirection has been provided', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ScrollbarPainter asserts if no TextDirection has been provided', (WidgetTester tester) async {
final ScrollbarPainter painter = ScrollbarPainter(
color: _kScrollbarColor,
fadeoutOpacityAnimation: kAlwaysCompleteAnimation,
@ -683,8 +684,9 @@ void main() {
}
});
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();
addTearDown(scrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -745,7 +747,7 @@ void main() {
);
});
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(
const Directionality(
textDirection: TextDirection.ltr,
@ -803,7 +805,7 @@ void main() {
);
});
testWidgets('Scrollbar does not fade away while hovering', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scrollbar does not fade away while hovering', (WidgetTester tester) async {
await tester.pumpWidget(
const Directionality(
textDirection: TextDirection.ltr,
@ -850,7 +852,7 @@ void main() {
);
});
testWidgets('Scrollbar will fade back in when hovering over known track area', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scrollbar will fade back in when hovering over known track area', (WidgetTester tester) async {
await tester.pumpWidget(
const Directionality(
textDirection: TextDirection.ltr,
@ -911,7 +913,7 @@ void main() {
);
});
testWidgets('Scrollbar will show on hover without needing to scroll first for metrics', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scrollbar will show on hover without needing to scroll first for metrics', (WidgetTester tester) async {
await tester.pumpWidget(
const Directionality(
textDirection: TextDirection.ltr,
@ -946,8 +948,9 @@ void main() {
);
});
testWidgets('Scrollbar thumb can be dragged', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scrollbar thumb can be dragged', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -1001,8 +1004,9 @@ void main() {
);
});
testWidgets('Scrollbar thumb cannot be dragged into overscroll if the physics do not allow', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scrollbar thumb cannot be dragged into overscroll if the physics do not allow', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -1053,8 +1057,9 @@ void main() {
);
});
testWidgets('Scrollbar thumb cannot be dragged into overscroll if the platform does not allow it', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scrollbar thumb cannot be dragged into overscroll if the platform does not allow it', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -1121,8 +1126,9 @@ void main() {
TargetPlatform.fuchsia,
}));
testWidgets('Scrollbar thumb can be dragged into overscroll if the platform allows it', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scrollbar thumb can be dragged into overscroll if the platform allows it', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -1188,7 +1194,7 @@ void main() {
}));
// Regression test for https://github.com/flutter/flutter/issues/66444
testWidgets("RawScrollbar doesn't show when scroll the inner scrollable widget", (WidgetTester tester) async {
testWidgetsWithLeakTracking("RawScrollbar doesn't show when scroll the inner scrollable widget", (WidgetTester tester) async {
final GlobalKey key1 = GlobalKey();
final GlobalKey key2 = GlobalKey();
final GlobalKey outerKey = GlobalKey();
@ -1250,8 +1256,9 @@ void main() {
);
});
testWidgets('Scrollbar hit test area adjusts for PointerDeviceKind', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scrollbar hit test area adjusts for PointerDeviceKind', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -1339,9 +1346,10 @@ void main() {
);
});
testWidgets('hit test', (WidgetTester tester) async {
testWidgetsWithLeakTracking('hit test', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/99324
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
bool onTap = false;
await tester.pumpWidget(
Directionality(
@ -1388,12 +1396,14 @@ void main() {
expect(onTap, true);
});
testWidgets('RawScrollbar.thumbVisibility asserts that a ScrollPosition is attached', (WidgetTester tester) async {
testWidgetsWithLeakTracking('RawScrollbar.thumbVisibility asserts that a ScrollPosition is attached', (WidgetTester tester) async {
final FlutterExceptionHandler? handler = FlutterError.onError;
FlutterErrorDetails? error;
FlutterError.onError = (FlutterErrorDetails details) {
error = details;
};
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(
Directionality(
@ -1402,7 +1412,7 @@ void main() {
data: const MediaQueryData(),
child: RawScrollbar(
thumbVisibility: true,
controller: ScrollController(),
controller: controller,
thumbColor: const Color(0x11111111),
child: const SingleChildScrollView(
child: SizedBox(
@ -1426,12 +1436,14 @@ void main() {
FlutterError.onError = handler;
});
testWidgets('RawScrollbar.thumbVisibility asserts that a ScrollPosition is attached', (WidgetTester tester) async {
testWidgetsWithLeakTracking('RawScrollbar.thumbVisibility asserts that a ScrollPosition is attached', (WidgetTester tester) async {
final FlutterExceptionHandler? handler = FlutterError.onError;
FlutterErrorDetails? error;
FlutterError.onError = (FlutterErrorDetails details) {
error = details;
};
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(
Directionality(
@ -1440,7 +1452,7 @@ void main() {
data: const MediaQueryData(),
child: RawScrollbar(
thumbVisibility: true,
controller: ScrollController(),
controller: controller,
thumbColor: const Color(0x11111111),
child: const SingleChildScrollView(
child: SizedBox(
@ -1464,9 +1476,11 @@ void main() {
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();
addTearDown(primaryScrollController.dispose);
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(
Directionality(
@ -1505,9 +1519,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
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -1679,8 +1694,9 @@ void main() {
);
});
testWidgets('Scrollbar thumb can be dragged in reverse', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scrollbar thumb can be dragged in reverse', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -1735,7 +1751,7 @@ void main() {
);
});
testWidgets('ScrollbarPainter asserts if scrollbarOrientation is used with wrong axisDirection', (WidgetTester tester) async {
testWidgetsWithLeakTracking('ScrollbarPainter asserts if scrollbarOrientation is used with wrong axisDirection', (WidgetTester tester) async {
final ScrollbarPainter painter = ScrollbarPainter(
color: _kScrollbarColor,
fadeoutOpacityAnimation: kAlwaysCompleteAnimation,
@ -1753,8 +1769,9 @@ void main() {
expect(() => painter.paint(testCanvas, size), throwsA(isA<AssertionError>()));
});
testWidgets('RawScrollbar mainAxisMargin property works properly', (WidgetTester tester) async {
testWidgetsWithLeakTracking('RawScrollbar mainAxisMargin property works properly', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -1783,8 +1800,9 @@ void main() {
);
});
testWidgets('shape property of RawScrollbar can draw a BeveledRectangleBorder', (WidgetTester tester) async {
testWidgetsWithLeakTracking('shape property of RawScrollbar can draw a BeveledRectangleBorder', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -1820,8 +1838,9 @@ void main() {
);
});
testWidgets('minThumbLength property of RawScrollbar is respected', (WidgetTester tester) async {
testWidgetsWithLeakTracking('minThumbLength property of RawScrollbar is respected', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -1846,8 +1865,9 @@ void main() {
..rect(rect: const Rect.fromLTRB(794.0, 0.0, 800.0, 21.0))); // thumb
});
testWidgets('shape property of RawScrollbar can draw a CircleBorder', (WidgetTester tester) async {
testWidgetsWithLeakTracking('shape property of RawScrollbar can draw a CircleBorder', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -1882,8 +1902,9 @@ void main() {
);
});
testWidgets('crossAxisMargin property of RawScrollbar is respected', (WidgetTester tester) async {
testWidgetsWithLeakTracking('crossAxisMargin property of RawScrollbar is respected', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -1907,8 +1928,9 @@ void main() {
..rect(rect: const Rect.fromLTRB(764.0, 0.0, 770.0, 360.0)));
});
testWidgets('shape property of RawScrollbar can draw a RoundedRectangleBorder', (WidgetTester tester) async {
testWidgetsWithLeakTracking('shape property of RawScrollbar can draw a RoundedRectangleBorder', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -1941,8 +1963,9 @@ void main() {
);
});
testWidgets('minOverscrollLength property of RawScrollbar is respected', (WidgetTester tester) async {
testWidgetsWithLeakTracking('minOverscrollLength property of RawScrollbar is respected', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -1973,8 +1996,9 @@ void main() {
..rect(rect: const Rect.fromLTRB(794.0, 0.0, 800.0, 8.0)));
});
testWidgets('not passing any shape or radius to RawScrollbar will draw the usual rectangular thumb', (WidgetTester tester) async {
testWidgetsWithLeakTracking('not passing any shape or radius to RawScrollbar will draw the usual rectangular thumb', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -1999,8 +2023,9 @@ void main() {
);
});
testWidgets('The bar can show or hide when the viewport size change', (WidgetTester tester) async {
testWidgetsWithLeakTracking('The bar can show or hide when the viewport size change', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
Widget buildFrame(double height) {
return Directionality(
textDirection: TextDirection.ltr,
@ -2030,10 +2055,11 @@ void main() {
expect(find.byType(RawScrollbar), isNot(paints..rect())); // Hide the bar.
});
testWidgets('The bar can show or hide when the view size change', (WidgetTester tester) async {
testWidgetsWithLeakTracking('The bar can show or hide when the view size change', (WidgetTester tester) async {
addTearDown(tester.view.reset);
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
Widget buildFrame() {
return Directionality(
textDirection: TextDirection.ltr,
@ -2072,10 +2098,12 @@ void main() {
expect(find.byType(RawScrollbar), isNot(paints..rect())); // Not shown.
});
testWidgets('Scrollbar will not flip axes based on notification is there is a scroll controller', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scrollbar will not flip axes based on notification is there is a scroll controller', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/87697
final ScrollController verticalScrollController = ScrollController();
addTearDown(verticalScrollController.dispose);
final ScrollController horizontalScrollController = ScrollController();
addTearDown(horizontalScrollController.dispose);
Widget buildFrame() {
return Directionality(
textDirection: TextDirection.ltr,
@ -2133,8 +2161,9 @@ void main() {
);
});
testWidgets('notificationPredicate depth test.', (WidgetTester tester) async {
testWidgetsWithLeakTracking('notificationPredicate depth test.', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
final List<int> depths = <int>[];
Widget buildFrame() {
return Directionality(
@ -2167,8 +2196,9 @@ void main() {
});
// Regression test for https://github.com/flutter/flutter/issues/92262
testWidgets('Do not crash when resize from scrollable to non-scrollable.', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Do not crash when resize from scrollable to non-scrollable.', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
Widget buildFrame(double height) {
return Directionality(
textDirection: TextDirection.ltr,
@ -2203,10 +2233,11 @@ void main() {
await tester.pumpAndSettle();
});
testWidgets('Scrollbar thumb can be dragged when the scrollable widget has a negative minScrollExtent - desktop', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scrollbar thumb can be dragged when the scrollable widget has a negative minScrollExtent - desktop', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/95840
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
final UniqueKey uniqueKey = UniqueKey();
await tester.pumpWidget(
Directionality(
@ -2285,10 +2316,11 @@ void main() {
);
}, variant: TargetPlatformVariant.desktop());
testWidgets('Scrollbar thumb can be dragged when the scrollable widget has a negative minScrollExtent - mobile', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scrollbar thumb can be dragged when the scrollable widget has a negative minScrollExtent - mobile', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/95840
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
final UniqueKey uniqueKey = UniqueKey();
await tester.pumpWidget(
Directionality(
@ -2421,8 +2453,9 @@ void main() {
expect(painter.shouldRepaint(createPainter(scrollbarOrientation: ScrollbarOrientation.bottom)), true);
});
testWidgets('Scrollbar track can be drawn', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scrollbar track can be drawn', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -2464,8 +2497,9 @@ void main() {
);
});
testWidgets('RawScrollbar correctly assigns colors', (WidgetTester tester) async {
testWidgetsWithLeakTracking('RawScrollbar correctly assigns colors', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -2510,8 +2544,9 @@ void main() {
);
});
testWidgets('trackRadius and radius properties of RawScrollbar can draw RoundedRectangularRect', (WidgetTester tester) async {
testWidgetsWithLeakTracking('trackRadius and radius properties of RawScrollbar can draw RoundedRectangularRect', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -2549,8 +2584,9 @@ void main() {
);
});
testWidgets('Scrollbar asserts that a visible track has a visible thumb', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scrollbar asserts that a visible track has a visible thumb', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
Widget buildApp() {
return Directionality(
textDirection: TextDirection.ltr,
@ -2573,9 +2609,10 @@ void main() {
expect(() => tester.pumpWidget(buildApp()), throwsAssertionError);
});
testWidgets('Skip the ScrollPosition check if the bar was unmounted', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Skip the ScrollPosition check if the bar was unmounted', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/103939
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
Widget buildApp(bool buildBar) {
return Directionality(
textDirection: TextDirection.ltr,
@ -2611,9 +2648,10 @@ void main() {
// Go without throw.
});
testWidgets('Track offset respects MediaQuery padding', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Track offset respects MediaQuery padding', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/106834
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -2643,8 +2681,9 @@ void main() {
); // thumb
});
testWidgets('RawScrollbar.padding replaces MediaQueryData.padding', (WidgetTester tester) async {
testWidgetsWithLeakTracking('RawScrollbar.padding replaces MediaQueryData.padding', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -2675,8 +2714,9 @@ void main() {
); // thumb
});
testWidgets('Scrollbar respect the NeverScrollableScrollPhysics physics', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Scrollbar respect the NeverScrollableScrollPhysics physics', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -2717,9 +2757,10 @@ void main() {
expect(scrollController.offset, 0.0);
});
testWidgets('The thumb should follow the pointer when the scroll metrics changed during dragging', (WidgetTester tester) async {
testWidgetsWithLeakTracking('The thumb should follow the pointer when the scroll metrics changed during dragging', (WidgetTester tester) async {
// Regressing test for https://github.com/flutter/flutter/issues/112072
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -2787,9 +2828,10 @@ void main() {
);
});
testWidgets('The scrollable should not stutter when the scroll metrics shrink during dragging', (WidgetTester tester) async {
testWidgetsWithLeakTracking('The scrollable should not stutter when the scroll metrics shrink during dragging', (WidgetTester tester) async {
// Regressing test for https://github.com/flutter/flutter/issues/121574
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
@ -2851,9 +2893,10 @@ void main() {
expect(scrollController.offset, greaterThan(lastPosition));
});
testWidgets('The bar support mouse wheel event', (WidgetTester tester) async {
testWidgetsWithLeakTracking('The bar support mouse wheel event', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/pull/109659
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
Widget buildFrame() {
return Directionality(
textDirection: TextDirection.ltr,

View File

@ -9,6 +9,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import 'package:web/web.dart' as web;
extension on web.HTMLCollection {
@ -59,8 +60,9 @@ void main() {
expect(foundStyle, isTrue);
});
testWidgets('right click can trigger select word', (WidgetTester tester) async {
testWidgetsWithLeakTracking('right click can trigger select word', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
final UniqueKey spy = UniqueKey();
await tester.pumpWidget(
MaterialApp(

File diff suppressed because it is too large Load Diff