Unverified Commit 98ebab58 authored by Kostia Sokolovskyi's avatar Kostia Sokolovskyi Committed by GitHub

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

parent c3db0209
......@@ -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,
......
......@@ -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;
......
......@@ -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(
......
......@@ -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;
......
......@@ -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,8 +1077,10 @@ void main() {
});
test('PrimaryScrollController.automaticallyInheritOnPlatforms defaults to all mobile platforms', (){
final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
final PrimaryScrollController primaryScrollController = PrimaryScrollController(
controller: ScrollController(),
controller: controller,
child: const SizedBox(),
);
expect(
......@@ -987,13 +1089,14 @@ void main() {
);
});
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(
......
......@@ -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,
......
......@@ -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(
......
......@@ -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(
......
......@@ -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(
......
......@@ -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(
......
......@@ -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,
......
......@@ -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>[];
......
......@@ -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),
......
......@@ -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(
......
......@@ -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,
......
......@@ -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() {
),
),
);
});
tearDown(() {
scrollController.dispose();
});
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);
......@@ -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
......
......@@ -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(
......
......@@ -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(
......
......@@ -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,
......
......@@ -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(
......
......@@ -8,6 +8,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';
......@@ -37,12 +38,15 @@ void main() {
});
group('SelectableRegion', () {
testWidgets('mouse selection single click sends correct events', (WidgetTester tester) async {
testWidgetsWithLeakTracking('mouse selection single click sends correct events', (WidgetTester tester) async {
final UniqueKey spy = UniqueKey();
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: SelectionSpy(key: spy),
),
......@@ -75,12 +79,15 @@ void main() {
await gesture.up();
}, skip: kIsWeb); // https://github.com/flutter/flutter/issues/102410.
testWidgets('mouse double click sends select-word event', (WidgetTester tester) async {
testWidgetsWithLeakTracking('mouse double click sends select-word event', (WidgetTester tester) async {
final UniqueKey spy = UniqueKey();
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: SelectionSpy(key: spy),
),
......@@ -103,8 +110,11 @@ void main() {
expect(selectionEvent.globalPosition, const Offset(200.0, 200.0));
});
testWidgets('Does not crash when using Navigator pages', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Does not crash when using Navigator pages', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/119776
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: Navigator(
......@@ -114,7 +124,7 @@ void main() {
children: <Widget>[
const Text('How are you?'),
SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const SelectAllWidget(child: SizedBox(width: 100, height: 100)),
),
......@@ -134,15 +144,18 @@ void main() {
expect(tester.takeException(), isNull);
});
testWidgets('can draw handles when they are at rect boundaries', (WidgetTester tester) async {
testWidgetsWithLeakTracking('can draw handles when they are at rect boundaries', (WidgetTester tester) async {
final UniqueKey spy = UniqueKey();
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: Column(
children: <Widget>[
const Text('How are you?'),
SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: SelectAllWidget(key: spy, child: const SizedBox(width: 100, height: 100)),
),
......@@ -164,12 +177,15 @@ void main() {
expect(renderSpy.endHandle, isNotNull);
});
testWidgets('touch does not accept drag', (WidgetTester tester) async {
testWidgetsWithLeakTracking('touch does not accept drag', (WidgetTester tester) async {
final UniqueKey spy = UniqueKey();
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: SelectionSpy(key: spy),
),
......@@ -187,12 +203,15 @@ void main() {
);
});
testWidgets('does not merge semantics node of the children', (WidgetTester tester) async {
testWidgetsWithLeakTracking('does not merge semantics node of the children', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: Scaffold(
body: Center(
......@@ -262,12 +281,15 @@ void main() {
semantics.dispose();
});
testWidgets('mouse selection always cancels previous selection', (WidgetTester tester) async {
testWidgetsWithLeakTracking('mouse selection always cancels previous selection', (WidgetTester tester) async {
final UniqueKey spy = UniqueKey();
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: SelectionSpy(key: spy),
),
......@@ -283,12 +305,15 @@ void main() {
expect(renderSelectionSpy.events[0], isA<ClearSelectionEvent>());
}, skip: kIsWeb); // https://github.com/flutter/flutter/issues/102410.
testWidgets('touch long press sends select-word event', (WidgetTester tester) async {
testWidgetsWithLeakTracking('touch long press sends select-word event', (WidgetTester tester) async {
final UniqueKey spy = UniqueKey();
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: SelectionSpy(key: spy),
),
......@@ -308,12 +333,15 @@ void main() {
expect(selectionEvent.globalPosition, const Offset(200.0, 200.0));
});
testWidgets('touch long press and drag sends correct events', (WidgetTester tester) async {
testWidgetsWithLeakTracking('touch long press and drag sends correct events', (WidgetTester tester) async {
final UniqueKey spy = UniqueKey();
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: SelectionSpy(key: spy),
),
......@@ -341,14 +369,17 @@ void main() {
expect(edgeEvent.granularity, TextGranularity.word);
});
testWidgets(
testWidgetsWithLeakTracking(
'touch long press cancel does not send ClearSelectionEvent',
(WidgetTester tester) async {
final UniqueKey spy = UniqueKey();
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: SelectionSpy(key: spy),
),
......@@ -373,11 +404,14 @@ void main() {
},
);
testWidgets(
testWidgetsWithLeakTracking(
'scrolling after the selection does not send ClearSelectionEvent',
(WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/128765
final UniqueKey spy = UniqueKey();
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SizedBox(
......@@ -386,7 +420,7 @@ void main() {
child: SizedBox(
height: 2000,
child: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: SelectionSpy(key: spy),
),
......@@ -417,12 +451,15 @@ void main() {
},
);
testWidgets('mouse long press does not send select-word event', (WidgetTester tester) async {
testWidgetsWithLeakTracking('mouse long press does not send select-word event', (WidgetTester tester) async {
final UniqueKey spy = UniqueKey();
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: SelectionSpy(key: spy),
),
......@@ -443,7 +480,7 @@ void main() {
});
});
testWidgets('dragging handle or selecting word triggers haptic feedback on Android', (WidgetTester tester) async {
testWidgetsWithLeakTracking('dragging handle or selecting word triggers haptic feedback on Android', (WidgetTester tester) async {
final List<MethodCall> log = <MethodCall>[];
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
log.add(methodCall);
......@@ -452,11 +489,13 @@ void main() {
addTearDown(() {
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, mockClipboard.handleMethodCall);
});
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Text('How are you?'),
),
......@@ -504,11 +543,14 @@ void main() {
}, variant: TargetPlatformVariant.all());
group('SelectionArea integration', () {
testWidgets('mouse can select single text', (WidgetTester tester) async {
testWidgetsWithLeakTracking('mouse can select single text', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Center(
child: Text('How are you'),
......@@ -548,11 +590,14 @@ void main() {
await gesture.up();
});
testWidgets('mouse can select word-by-word on double click drag', (WidgetTester tester) async {
testWidgetsWithLeakTracking('mouse can select word-by-word on double click drag', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Center(
child: Text('How are you'),
......@@ -617,11 +662,14 @@ void main() {
await gesture.up();
}, skip: kIsWeb); // https://github.com/flutter/flutter/issues/125582.
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 {
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Column(
children: <Widget>[
......@@ -663,11 +711,14 @@ void main() {
await gesture.up();
}, skip: kIsWeb); // https://github.com/flutter/flutter/issues/125582.
testWidgets('mouse can select multiple widgets on double click drag and return to origin word', (WidgetTester tester) async {
testWidgetsWithLeakTracking('mouse can select multiple widgets on double click drag and return to origin word', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Column(
children: <Widget>[
......@@ -721,11 +772,14 @@ void main() {
await gesture.up();
}, skip: kIsWeb); // https://github.com/flutter/flutter/issues/125582.
testWidgets('mouse can reverse selection across multiple widgets on double click drag', (WidgetTester tester) async {
testWidgetsWithLeakTracking('mouse can reverse selection across multiple widgets on double click drag', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Column(
children: <Widget>[
......@@ -766,11 +820,14 @@ void main() {
await gesture.up();
}, skip: kIsWeb); // https://github.com/flutter/flutter/issues/125582.
testWidgets('mouse can select multiple widgets', (WidgetTester tester) async {
testWidgetsWithLeakTracking('mouse can select multiple widgets', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Column(
children: <Widget>[
......@@ -806,11 +863,14 @@ void main() {
await gesture.up();
});
testWidgets('mouse can work with disabled container', (WidgetTester tester) async {
testWidgetsWithLeakTracking('mouse can work with disabled container', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Column(
children: <Widget>[
......@@ -847,11 +907,14 @@ void main() {
await gesture.up();
});
testWidgets('mouse can reverse selection', (WidgetTester tester) async {
testWidgetsWithLeakTracking('mouse can reverse selection', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Column(
children: <Widget>[
......@@ -886,15 +949,18 @@ void main() {
await gesture.up();
});
testWidgets(
testWidgetsWithLeakTracking(
'single tap on the previous selection toggles the toolbar on iOS',
(WidgetTester tester) async {
Set<ContextMenuButtonType> buttonTypes = <ContextMenuButtonType>{};
final UniqueKey toolbarKey = UniqueKey();
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionHandleControls,
contextMenuBuilder: (
BuildContext context,
......@@ -958,15 +1024,18 @@ void main() {
skip: kIsWeb, // [intended] Web uses its native context menu.
);
testWidgets(
testWidgetsWithLeakTracking(
'right-click mouse can select word at position on Apple platforms',
(WidgetTester tester) async {
Set<ContextMenuButtonType> buttonTypes = <ContextMenuButtonType>{};
final UniqueKey toolbarKey = UniqueKey();
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionHandleControls,
contextMenuBuilder: (
BuildContext context,
......@@ -1032,15 +1101,18 @@ void main() {
skip: kIsWeb, // [intended] Web uses its native context menu.
);
testWidgets(
testWidgetsWithLeakTracking(
'right-click mouse at the same position as previous right-click toggles the context menu on macOS',
(WidgetTester tester) async {
Set<ContextMenuButtonType> buttonTypes = <ContextMenuButtonType>{};
final UniqueKey toolbarKey = UniqueKey();
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionHandleControls,
contextMenuBuilder: (
BuildContext context,
......@@ -1130,15 +1202,18 @@ void main() {
skip: kIsWeb, // [intended] Web uses its native context menu.
);
testWidgets(
testWidgetsWithLeakTracking(
'right-click mouse shows the context menu at position on Android, Fucshia, and Windows',
(WidgetTester tester) async {
Set<ContextMenuButtonType> buttonTypes = <ContextMenuButtonType>{};
final UniqueKey toolbarKey = UniqueKey();
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionHandleControls,
contextMenuBuilder: (
BuildContext context,
......@@ -1238,15 +1313,18 @@ void main() {
skip: kIsWeb, // [intended] Web uses its native context menu.
);
testWidgets(
testWidgetsWithLeakTracking(
'right-click mouse toggles the context menu on Linux',
(WidgetTester tester) async {
Set<ContextMenuButtonType> buttonTypes = <ContextMenuButtonType>{};
final UniqueKey toolbarKey = UniqueKey();
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionHandleControls,
contextMenuBuilder: (
BuildContext context,
......@@ -1355,11 +1433,14 @@ void main() {
skip: kIsWeb, // [intended] Web uses its native context menu.
);
testWidgets('can copy a selection made with the mouse', (WidgetTester tester) async {
testWidgetsWithLeakTracking('can copy a selection made with the mouse', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Column(
children: <Widget>[
......@@ -1388,12 +1469,16 @@ void main() {
expect(clipboardData['text'], 'w are you?Good, and you?Fine, ');
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.windows, TargetPlatform.linux, TargetPlatform.fuchsia }));
testWidgets(
testWidgetsWithLeakTracking(
'does not override TextField keyboard shortcuts if the TextField is focused - non apple',
(WidgetTester tester) async {
final TextEditingController controller = TextEditingController(text: 'I am fine, thank you.');
addTearDown(controller.dispose);
final FocusNode selectableRegionFocus = FocusNode();
addTearDown(selectableRegionFocus.dispose);
final FocusNode textFieldFocus = FocusNode();
addTearDown(textFieldFocus.dispose);
await tester.pumpWidget(
MaterialApp(
home: Material(
......@@ -1441,12 +1526,16 @@ void main() {
skip: kIsWeb, // [intended] the web handles this on its own.
);
testWidgets(
testWidgetsWithLeakTracking(
'does not override TextField keyboard shortcuts if the TextField is focused - apple',
(WidgetTester tester) async {
final TextEditingController controller = TextEditingController(text: 'I am fine, thank you.');
addTearDown(controller.dispose);
final FocusNode selectableRegionFocus = FocusNode();
addTearDown(selectableRegionFocus.dispose);
final FocusNode textFieldFocus = FocusNode();
addTearDown(textFieldFocus.dispose);
await tester.pumpWidget(
MaterialApp(
home: Material(
......@@ -1494,8 +1583,10 @@ void main() {
skip: kIsWeb, // [intended] the web handles this on its own.
);
testWidgets('select all', (WidgetTester tester) async {
testWidgetsWithLeakTracking('select all', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
......@@ -1525,13 +1616,16 @@ void main() {
expect(paragraph1.selections[0], const TextSelection(baseOffset: 0, extentOffset: 12));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.windows, TargetPlatform.linux, TargetPlatform.fuchsia }));
testWidgets(
testWidgetsWithLeakTracking(
'mouse selection can handle widget span', (WidgetTester tester) async {
final UniqueKey outerText = UniqueKey();
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: Center(
child: Text.rich(
......@@ -1564,14 +1658,17 @@ void main() {
skip: isBrowser, // https://github.com/flutter/flutter/issues/61020
);
testWidgets(
testWidgetsWithLeakTracking(
'can select word when a selectables rect is completely inside of another selectables rect', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/127076.
final UniqueKey outerText = UniqueKey();
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: Scaffold(
body: Center(
......@@ -1612,14 +1709,17 @@ void main() {
skip: isBrowser, // https://github.com/flutter/flutter/issues/61020
);
testWidgets(
testWidgetsWithLeakTracking(
'widget span is ignored if it does not contain text - non Apple',
(WidgetTester tester) async {
final UniqueKey outerText = UniqueKey();
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: Center(
child: Text.rich(
......@@ -1652,14 +1752,17 @@ void main() {
skip: isBrowser, // https://github.com/flutter/flutter/issues/61020
);
testWidgets(
testWidgetsWithLeakTracking(
'widget span is ignored if it does not contain text - Apple',
(WidgetTester tester) async {
final UniqueKey outerText = UniqueKey();
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: Center(
child: Text.rich(
......@@ -1692,11 +1795,14 @@ void main() {
skip: isBrowser, // https://github.com/flutter/flutter/issues/61020
);
testWidgets('mouse can select across bidi text', (WidgetTester tester) async {
testWidgetsWithLeakTracking('mouse can select across bidi text', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Column(
children: <Widget>[
......@@ -1733,11 +1839,14 @@ void main() {
await gesture.up();
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/61020
testWidgets('long press and drag touch moves selection word by word', (WidgetTester tester) async {
testWidgetsWithLeakTracking('long press and drag touch moves selection word by word', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Column(
children: <Widget>[
......@@ -1764,15 +1873,18 @@ void main() {
await gesture.up();
});
testWidgets('can drag end handle when not covering entire screen', (WidgetTester tester) async {
testWidgetsWithLeakTracking('can drag end handle when not covering entire screen', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/104620.
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: Column(
children: <Widget>[
const Text('How are you?'),
SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Text('Good, and you?'),
),
......@@ -1801,15 +1913,18 @@ void main() {
await gesture.up();
});
testWidgets('can drag start handle when not covering entire screen', (WidgetTester tester) async {
testWidgetsWithLeakTracking('can drag start handle when not covering entire screen', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/104620.
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: Column(
children: <Widget>[
const Text('How are you?'),
SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Text('Good, and you?'),
),
......@@ -1837,11 +1952,14 @@ void main() {
await gesture.up();
});
testWidgets('can drag start selection handle', (WidgetTester tester) async {
testWidgetsWithLeakTracking('can drag start selection handle', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Column(
children: <Widget>[
......@@ -1879,11 +1997,14 @@ void main() {
await gesture.up();
});
testWidgets('can drag start selection handle across end selection handle', (WidgetTester tester) async {
testWidgetsWithLeakTracking('can drag start selection handle across end selection handle', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Column(
children: <Widget>[
......@@ -1916,11 +2037,14 @@ void main() {
await gesture.up();
});
testWidgets('can drag end selection handle across start selection handle', (WidgetTester tester) async {
testWidgetsWithLeakTracking('can drag end selection handle across start selection handle', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Column(
children: <Widget>[
......@@ -1953,11 +2077,14 @@ void main() {
await gesture.up();
});
testWidgets('can select all from toolbar', (WidgetTester tester) async {
testWidgetsWithLeakTracking('can select all from toolbar', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Column(
children: <Widget>[
......@@ -1989,11 +2116,14 @@ void main() {
expect(paragraph1.selections[0], const TextSelection(baseOffset: 0, extentOffset: 12));
}, skip: kIsWeb); // [intended] Web uses its native context menu.
testWidgets('can copy from toolbar', (WidgetTester tester) async {
testWidgetsWithLeakTracking('can copy from toolbar', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Column(
children: <Widget>[
......@@ -2029,11 +2159,14 @@ void main() {
expect(clipboardData['text'], 'thank');
}, skip: kIsWeb); // [intended] Web uses its native context menu.
testWidgets('can use keyboard to granularly extend selection - character', (WidgetTester tester) async {
testWidgetsWithLeakTracking('can use keyboard to granularly extend selection - character', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Column(
children: <Widget>[
......@@ -2089,11 +2222,14 @@ void main() {
}
}, variant: TargetPlatformVariant.all());
testWidgets('can use keyboard to granularly extend selection - word', (WidgetTester tester) async {
testWidgetsWithLeakTracking('can use keyboard to granularly extend selection - word', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Column(
children: <Widget>[
......@@ -2197,11 +2333,14 @@ void main() {
expect(paragraph2.selections.length, 0);
}, variant: TargetPlatformVariant.all());
testWidgets('can use keyboard to granularly extend selection - line', (WidgetTester tester) async {
testWidgetsWithLeakTracking('can use keyboard to granularly extend selection - line', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Column(
children: <Widget>[
......@@ -2286,11 +2425,14 @@ void main() {
expect(paragraph1.selections[0].end, 2);
}, variant: TargetPlatformVariant.all());
testWidgets('can use keyboard to granularly extend selection - document', (WidgetTester tester) async {
testWidgetsWithLeakTracking('can use keyboard to granularly extend selection - document', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Column(
children: <Widget>[
......@@ -2362,11 +2504,14 @@ void main() {
expect(paragraph3.selections.length, 0);
}, variant: TargetPlatformVariant.all());
testWidgets('can use keyboard to directionally extend selection', (WidgetTester tester) async {
testWidgetsWithLeakTracking('can use keyboard to directionally extend selection', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Column(
children: <Widget>[
......@@ -2459,9 +2604,11 @@ void main() {
late ValueNotifier<MagnifierInfo> magnifierInfo;
final Widget fakeMagnifier = Container(key: UniqueKey());
testWidgets('Can drag handles to show, unshow, and update magnifier',
testWidgetsWithLeakTracking('Can drag handles to show, unshow, and update magnifier',
(WidgetTester tester) async {
const String text = 'Monkeys and rabbits in my soup';
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
......@@ -2475,7 +2622,7 @@ void main() {
return fakeMagnifier;
},
),
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Text(text),
),
......@@ -2525,13 +2672,15 @@ void main() {
});
});
testWidgets('toolbar is hidden on mobile when orientation changes', (WidgetTester tester) async {
testWidgetsWithLeakTracking('toolbar is hidden on mobile when orientation changes', (WidgetTester tester) async {
addTearDown(tester.view.reset);
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Text('How are you?'),
),
......@@ -2567,12 +2716,15 @@ void main() {
variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.android }),
);
testWidgets('the selection behavior when clicking `Copy` item in mobile platforms', (WidgetTester tester) async {
testWidgetsWithLeakTracking('the selection behavior when clicking `Copy` item in mobile platforms', (WidgetTester tester) async {
List<ContextMenuButtonItem> buttonItems = <ContextMenuButtonItem>[];
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionHandleControls,
contextMenuBuilder: (
BuildContext context,
......@@ -2621,12 +2773,15 @@ void main() {
skip: kIsWeb, // [intended]
);
testWidgets('the handles do not disappear when clicking `Select all` item in mobile platforms', (WidgetTester tester) async {
testWidgetsWithLeakTracking('the handles do not disappear when clicking `Select all` item in mobile platforms', (WidgetTester tester) async {
List<ContextMenuButtonItem> buttonItems = <ContextMenuButtonItem>[];
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionHandleControls,
contextMenuBuilder: (
BuildContext context,
......@@ -2674,12 +2829,15 @@ void main() {
variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.android, TargetPlatform.fuchsia }),
);
testWidgets('builds the correct button items', (WidgetTester tester) async {
testWidgetsWithLeakTracking('builds the correct button items', (WidgetTester tester) async {
Set<ContextMenuButtonType> buttonTypes = <ContextMenuButtonType>{};
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionHandleControls,
contextMenuBuilder: (
BuildContext context,
......@@ -2713,14 +2871,16 @@ void main() {
skip: kIsWeb, // [intended]
);
testWidgets('onSelectionChange is called when the selection changes through gestures', (WidgetTester tester) async {
testWidgetsWithLeakTracking('onSelectionChange is called when the selection changes through gestures', (WidgetTester tester) async {
SelectedContent? content;
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
onSelectionChanged: (SelectedContent? selectedContent) => content = selectedContent,
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Center(
child: Text('How are you'),
......@@ -2845,14 +3005,16 @@ void main() {
await tester.pumpAndSettle();
});
testWidgets('onSelectionChange is called when the selection changes through keyboard actions', (WidgetTester tester) async {
testWidgetsWithLeakTracking('onSelectionChange is called when the selection changes through keyboard actions', (WidgetTester tester) async {
SelectedContent? content;
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
onSelectionChanged: (SelectedContent? selectedContent) => content = selectedContent,
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Column(
children: <Widget>[
......@@ -3003,12 +3165,15 @@ void main() {
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.contextMenu, null);
});
testWidgets('web can show flutter context menu when the browser context menu is disabled', (WidgetTester tester) async {
testWidgetsWithLeakTracking('web can show flutter context menu when the browser context menu is disabled', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
onSelectionChanged: (SelectedContent? selectedContent) {},
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: const Center(
child: Text('How are you'),
......@@ -3034,14 +3199,17 @@ void main() {
);
});
testWidgets('Multiple selectables on a single line should be in screen order', (WidgetTester tester) async {
testWidgetsWithLeakTracking('Multiple selectables on a single line should be in screen order', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/127942.
final UniqueKey outerText = UniqueKey();
const TextStyle textStyle = TextStyle(fontSize: 10);
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
focusNode: focusNode,
selectionControls: materialTextSelectionControls,
child: Scaffold(
body: Center(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment