mirror of
https://github.com/flutter/flutter
synced 2024-10-03 23:14:12 +00:00
parent
fdde24195f
commit
95eae5f967
|
@ -435,7 +435,7 @@ void main() {
|
|||
);
|
||||
});
|
||||
|
||||
testWidgets('disposes animation and controller', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('disposes animation and controller', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
const Center(
|
||||
child: AnimatedSize(
|
||||
|
|
|
@ -1062,13 +1062,14 @@ void main() {
|
|||
element.createChild(0, after: null);
|
||||
});
|
||||
|
||||
testWidgets('GlobalKey - re-attach child to new parents, and the old parent is deactivated(unmounted)', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('GlobalKey - re-attach child to new parents, and the old parent is deactivated(unmounted)', (WidgetTester tester) async {
|
||||
// This is a regression test for https://github.com/flutter/flutter/issues/62055
|
||||
const Key key1 = GlobalObjectKey('key1');
|
||||
const Key key2 = GlobalObjectKey('key2');
|
||||
late StateSetter setState;
|
||||
int tabBarViewCnt = 2;
|
||||
TabController tabController = TabController(length: tabBarViewCnt, vsync: const TestVSync());
|
||||
addTearDown(tabController.dispose);
|
||||
|
||||
await tester.pumpWidget(Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
|
@ -1101,6 +1102,7 @@ void main() {
|
|||
setState(() {
|
||||
tabBarViewCnt = 1;
|
||||
tabController = TabController(length: tabBarViewCnt, vsync: const TestVSync());
|
||||
addTearDown(tabController.dispose);
|
||||
});
|
||||
|
||||
await tester.pump(const Duration(seconds: 1)); // finish the animation
|
||||
|
|
|
@ -15,6 +15,7 @@ import 'package:flutter/src/widgets/_html_element_view_web.dart'
|
|||
show debugOverridePlatformViewRegistry;
|
||||
import 'package:flutter/widgets.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;
|
||||
|
||||
final Object _mockHtmlElement = Object();
|
||||
|
@ -42,7 +43,7 @@ void main() {
|
|||
});
|
||||
|
||||
group('HtmlElementView', () {
|
||||
testWidgets('Create HTML view', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Create HTML view', (WidgetTester tester) async {
|
||||
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
||||
fakePlatformViewRegistry.registerViewFactory('webview', _mockViewFactory);
|
||||
|
||||
|
@ -64,7 +65,7 @@ void main() {
|
|||
);
|
||||
});
|
||||
|
||||
testWidgets('Create HTML view with PlatformViewCreatedCallback', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Create HTML view with PlatformViewCreatedCallback', (WidgetTester tester) async {
|
||||
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
||||
fakePlatformViewRegistry.registerViewFactory('webview', _mockViewFactory);
|
||||
|
||||
|
@ -97,7 +98,7 @@ void main() {
|
|||
);
|
||||
});
|
||||
|
||||
testWidgets('Create HTML view with creation params', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Create HTML view with creation params', (WidgetTester tester) async {
|
||||
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
||||
fakePlatformViewRegistry.registerViewFactory('webview', _mockViewFactory);
|
||||
await tester.pumpWidget(
|
||||
|
@ -132,7 +133,7 @@ void main() {
|
|||
);
|
||||
});
|
||||
|
||||
testWidgets('Resize HTML view', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Resize HTML view', (WidgetTester tester) async {
|
||||
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
||||
fakePlatformViewRegistry.registerViewFactory('webview', _mockViewFactory);
|
||||
await tester.pumpWidget(
|
||||
|
@ -168,7 +169,7 @@ void main() {
|
|||
);
|
||||
});
|
||||
|
||||
testWidgets('Change HTML view type', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Change HTML view type', (WidgetTester tester) async {
|
||||
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
||||
fakePlatformViewRegistry.registerViewFactory('webview', _mockViewFactory);
|
||||
fakePlatformViewRegistry.registerViewFactory('maps', _mockViewFactory);
|
||||
|
@ -200,7 +201,7 @@ void main() {
|
|||
);
|
||||
});
|
||||
|
||||
testWidgets('Dispose HTML view', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Dispose HTML view', (WidgetTester tester) async {
|
||||
fakePlatformViewRegistry.registerViewFactory('webview', _mockViewFactory);
|
||||
await tester.pumpWidget(
|
||||
const Center(
|
||||
|
@ -227,7 +228,7 @@ void main() {
|
|||
);
|
||||
});
|
||||
|
||||
testWidgets('HTML view survives widget tree change', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('HTML view survives widget tree change', (WidgetTester tester) async {
|
||||
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
||||
fakePlatformViewRegistry.registerViewFactory('webview', _mockViewFactory);
|
||||
final GlobalKey key = GlobalKey();
|
||||
|
@ -259,7 +260,7 @@ void main() {
|
|||
);
|
||||
});
|
||||
|
||||
testWidgets('HtmlElementView has correct semantics', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('HtmlElementView has correct semantics', (WidgetTester tester) async {
|
||||
final SemanticsHandle handle = tester.ensureSemantics();
|
||||
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
||||
expect(currentViewId, greaterThanOrEqualTo(0));
|
||||
|
@ -306,7 +307,7 @@ void main() {
|
|||
debugOverridePlatformViewRegistry = null;
|
||||
});
|
||||
|
||||
testWidgets('Create platform view from tagName', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Create platform view from tagName', (WidgetTester tester) async {
|
||||
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
||||
|
||||
await tester.pumpWidget(
|
||||
|
@ -331,7 +332,7 @@ void main() {
|
|||
expect(htmlElement.tagName, equalsIgnoringCase('div'));
|
||||
});
|
||||
|
||||
testWidgets('Create invisible platform view', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Create invisible platform view', (WidgetTester tester) async {
|
||||
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
|
||||
|
||||
await tester.pumpWidget(
|
||||
|
@ -357,7 +358,7 @@ void main() {
|
|||
expect(htmlElement.tagName, equalsIgnoringCase('script'));
|
||||
});
|
||||
|
||||
testWidgets('onElementCreated', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('onElementCreated', (WidgetTester tester) async {
|
||||
final List<Object> createdElements = <Object>[];
|
||||
void onElementCreated(Object element) {
|
||||
createdElements.add(element);
|
||||
|
|
|
@ -55,7 +55,7 @@ void main() {
|
|||
});
|
||||
|
||||
group('construction check', () {
|
||||
testWidgets('ListWheelScrollView needs positive diameter ratio', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('ListWheelScrollView needs positive diameter ratio', (WidgetTester tester) async {
|
||||
expect(
|
||||
() => ListWheelScrollView(
|
||||
diameterRatio: nonconst(-2.0),
|
||||
|
@ -70,7 +70,7 @@ void main() {
|
|||
);
|
||||
});
|
||||
|
||||
testWidgets('ListWheelScrollView can have zero child', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('ListWheelScrollView can have zero child', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
|
@ -114,7 +114,7 @@ void main() {
|
|||
expect(detach, 1);
|
||||
});
|
||||
|
||||
testWidgets('ListWheelScrollView needs positive magnification', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('ListWheelScrollView needs positive magnification', (WidgetTester tester) async {
|
||||
expect(
|
||||
() {
|
||||
ListWheelScrollView(
|
||||
|
@ -128,7 +128,7 @@ void main() {
|
|||
);
|
||||
});
|
||||
|
||||
testWidgets('ListWheelScrollView needs valid overAndUnderCenterOpacity', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('ListWheelScrollView needs valid overAndUnderCenterOpacity', (WidgetTester tester) async {
|
||||
expect(
|
||||
() {
|
||||
ListWheelScrollView(
|
||||
|
@ -175,9 +175,9 @@ void main() {
|
|||
});
|
||||
|
||||
group('infinite scrolling', () {
|
||||
testWidgets('infinite looping list', (WidgetTester tester) async {
|
||||
final FixedExtentScrollController controller =
|
||||
FixedExtentScrollController();
|
||||
testWidgetsWithLeakTracking('infinite looping list', (WidgetTester tester) async {
|
||||
final FixedExtentScrollController controller = FixedExtentScrollController();
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
|
@ -221,9 +221,9 @@ void main() {
|
|||
);
|
||||
});
|
||||
|
||||
testWidgets('infinite child builder', (WidgetTester tester) async {
|
||||
final FixedExtentScrollController controller =
|
||||
FixedExtentScrollController();
|
||||
testWidgetsWithLeakTracking('infinite child builder', (WidgetTester tester) async {
|
||||
final FixedExtentScrollController controller = FixedExtentScrollController();
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
|
@ -262,12 +262,12 @@ void main() {
|
|||
);
|
||||
});
|
||||
|
||||
testWidgets('child builder with lower and upper limits', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('child builder with lower and upper limits', (WidgetTester tester) async {
|
||||
// Adjust the content dimensions at the end of `RenderListWheelViewport.performLayout()`
|
||||
final List<int> paintedChildren = <int>[];
|
||||
|
||||
final FixedExtentScrollController controller =
|
||||
FixedExtentScrollController(initialItem: -10);
|
||||
final FixedExtentScrollController controller = FixedExtentScrollController(initialItem: -10);
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
|
@ -320,9 +320,11 @@ void main() {
|
|||
});
|
||||
|
||||
group('layout', () {
|
||||
testWidgets('Flings with high velocity should not break the children lower and upper limits', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Flings with high velocity should not break the children lower and upper limits', (WidgetTester tester) async {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/112526
|
||||
final FixedExtentScrollController controller = FixedExtentScrollController();
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
Widget buildFrame() {
|
||||
return Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
|
@ -359,8 +361,10 @@ void main() {
|
|||
}, variant: TargetPlatformVariant(TargetPlatform.values.toSet()));
|
||||
|
||||
// Regression test for https://github.com/flutter/flutter/issues/90953
|
||||
testWidgets('ListWheelScrollView childDelegate update test 2', (WidgetTester tester) async {
|
||||
final FixedExtentScrollController controller = FixedExtentScrollController( initialItem: 2 );
|
||||
testWidgetsWithLeakTracking('ListWheelScrollView childDelegate update test 2', (WidgetTester tester) async {
|
||||
final FixedExtentScrollController controller = FixedExtentScrollController(initialItem: 2);
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
Widget buildFrame(int childCount) {
|
||||
return Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
|
@ -422,8 +426,10 @@ void main() {
|
|||
});
|
||||
|
||||
// Regression test for https://github.com/flutter/flutter/issues/58144
|
||||
testWidgets('ListWheelScrollView childDelegate update test', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('ListWheelScrollView childDelegate update test', (WidgetTester tester) async {
|
||||
final FixedExtentScrollController controller = FixedExtentScrollController();
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
Widget buildFrame(int childCount) {
|
||||
return Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
|
@ -453,7 +459,7 @@ void main() {
|
|||
expect(tester.renderObject(find.text('1')).attached, true);
|
||||
});
|
||||
|
||||
testWidgets("ListWheelScrollView takes parent's size with small children", (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking("ListWheelScrollView takes parent's size with small children", (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
|
@ -474,7 +480,7 @@ void main() {
|
|||
expect(tester.getBottomRight(find.byType(ListWheelScrollView)), const Offset(800.0, 600.0));
|
||||
});
|
||||
|
||||
testWidgets("ListWheelScrollView takes parent's size with large children", (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking("ListWheelScrollView takes parent's size with large children", (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
|
@ -495,7 +501,7 @@ void main() {
|
|||
expect(tester.getBottomRight(find.byType(ListWheelScrollView)), const Offset(800.0, 600.0));
|
||||
});
|
||||
|
||||
testWidgets("ListWheelScrollView children can't be bigger than itemExtent", (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking("ListWheelScrollView children can't be bigger than itemExtent", (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
|
@ -517,10 +523,10 @@ void main() {
|
|||
expect(find.text('blah'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('builder is never called twice for same index', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('builder is never called twice for same index', (WidgetTester tester) async {
|
||||
final Set<int> builtChildren = <int>{};
|
||||
final FixedExtentScrollController controller =
|
||||
FixedExtentScrollController();
|
||||
final FixedExtentScrollController controller = FixedExtentScrollController();
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
|
@ -554,9 +560,9 @@ void main() {
|
|||
await tester.pump();
|
||||
});
|
||||
|
||||
testWidgets('only visible children are maintained as children of the rendered viewport', (WidgetTester tester) async {
|
||||
final FixedExtentScrollController controller =
|
||||
FixedExtentScrollController();
|
||||
testWidgetsWithLeakTracking('only visible children are maintained as children of the rendered viewport', (WidgetTester tester) async {
|
||||
final FixedExtentScrollController controller = FixedExtentScrollController();
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
|
@ -591,9 +597,9 @@ void main() {
|
|||
expect(viewport.childCount, 4);
|
||||
});
|
||||
|
||||
testWidgets('a tighter squeeze lays out more children', (WidgetTester tester) async {
|
||||
final FixedExtentScrollController controller =
|
||||
FixedExtentScrollController(initialItem: 10);
|
||||
testWidgetsWithLeakTracking('a tighter squeeze lays out more children', (WidgetTester tester) async {
|
||||
final FixedExtentScrollController controller = FixedExtentScrollController(initialItem: 10);
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
|
@ -636,7 +642,7 @@ void main() {
|
|||
expect(viewport.childCount, 13);
|
||||
});
|
||||
|
||||
testWidgets('Active children are laid out with correct offset', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Active children are laid out with correct offset', (WidgetTester tester) async {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/123497
|
||||
Future<void> buildWidget(double width) async {
|
||||
return tester.pumpWidget(
|
||||
|
@ -673,8 +679,9 @@ void main() {
|
|||
});
|
||||
|
||||
group('pre-transform viewport', () {
|
||||
testWidgets('ListWheelScrollView starts and ends from the middle', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('ListWheelScrollView starts and ends from the middle', (WidgetTester tester) async {
|
||||
final ScrollController controller = ScrollController();
|
||||
addTearDown(controller.dispose);
|
||||
final List<int> paintedChildren = <int>[];
|
||||
|
||||
await tester.pumpWidget(
|
||||
|
@ -715,8 +722,9 @@ void main() {
|
|||
expect(paintedChildren, <int>[96, 97, 98, 99]);
|
||||
});
|
||||
|
||||
testWidgets('A child gets painted as soon as its first pixel is in the viewport', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('A child gets painted as soon as its first pixel is in the viewport', (WidgetTester tester) async {
|
||||
final ScrollController controller = ScrollController(initialScrollOffset: 50.0);
|
||||
addTearDown(controller.dispose);
|
||||
final List<int> paintedChildren = <int>[];
|
||||
|
||||
await tester.pumpWidget(
|
||||
|
@ -749,8 +757,9 @@ void main() {
|
|||
expect(paintedChildren, <int>[0, 1, 2, 3, 4]);
|
||||
});
|
||||
|
||||
testWidgets('A child is no longer painted after its last pixel leaves the viewport', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('A child is no longer painted after its last pixel leaves the viewport', (WidgetTester tester) async {
|
||||
final ScrollController controller = ScrollController(initialScrollOffset: 250.0);
|
||||
addTearDown(controller.dispose);
|
||||
final List<int> paintedChildren = <int>[];
|
||||
|
||||
await tester.pumpWidget(
|
||||
|
@ -793,7 +802,7 @@ void main() {
|
|||
});
|
||||
|
||||
group('viewport transformation', () {
|
||||
testWidgets('Center child is magnified', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Center child is magnified', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
|
@ -817,7 +826,7 @@ void main() {
|
|||
);
|
||||
});
|
||||
|
||||
testWidgets('Default middle transform', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Default middle transform', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
|
@ -846,8 +855,10 @@ void main() {
|
|||
));
|
||||
});
|
||||
|
||||
testWidgets('Curve the wheel to the left', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Curve the wheel to the left', (WidgetTester tester) async {
|
||||
final ScrollController controller = ScrollController(initialScrollOffset: 300.0);
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
|
@ -871,8 +882,9 @@ void main() {
|
|||
);
|
||||
});
|
||||
|
||||
testWidgets('Scrolling, diameterRatio, perspective all changes matrix', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Scrolling, diameterRatio, perspective all changes matrix', (WidgetTester tester) async {
|
||||
final ScrollController controller = ScrollController(initialScrollOffset: 200.0);
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
|
@ -990,8 +1002,9 @@ void main() {
|
|||
));
|
||||
});
|
||||
|
||||
testWidgets('offAxisFraction, magnification changes matrix', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('offAxisFraction, magnification changes matrix', (WidgetTester tester) async {
|
||||
final ScrollController controller = ScrollController(initialScrollOffset: 200.0);
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
|
@ -1089,7 +1102,7 @@ void main() {
|
|||
});
|
||||
|
||||
group('scroll notifications', () {
|
||||
testWidgets('no onSelectedItemChanged callback on first build', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('no onSelectedItemChanged callback on first build', (WidgetTester tester) async {
|
||||
bool itemChangeCalled = false;
|
||||
void onItemChange(int _) { itemChangeCalled = true; }
|
||||
|
||||
|
@ -1114,7 +1127,7 @@ void main() {
|
|||
expect(itemChangeCalled, false);
|
||||
});
|
||||
|
||||
testWidgets('onSelectedItemChanged when a new item is closest to center', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('onSelectedItemChanged when a new item is closest to center', (WidgetTester tester) async {
|
||||
final List<int> selectedItems = <int>[];
|
||||
|
||||
await tester.pumpWidget(
|
||||
|
@ -1151,7 +1164,7 @@ void main() {
|
|||
expect(selectedItems, <int>[1, 2, 1]);
|
||||
});
|
||||
|
||||
testWidgets('onSelectedItemChanged reports only in valid range', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('onSelectedItemChanged reports only in valid range', (WidgetTester tester) async {
|
||||
final List<int> selectedItems = <int>[];
|
||||
|
||||
await tester.pumpWidget(
|
||||
|
@ -1187,8 +1200,9 @@ void main() {
|
|||
});
|
||||
|
||||
group('scroll controller', () {
|
||||
testWidgets('initialItem', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('initialItem', (WidgetTester tester) async {
|
||||
final FixedExtentScrollController controller = FixedExtentScrollController(initialItem: 10);
|
||||
addTearDown(controller.dispose);
|
||||
final List<int> paintedChildren = <int>[];
|
||||
|
||||
await tester.pumpWidget(
|
||||
|
@ -1213,8 +1227,9 @@ void main() {
|
|||
expect(controller.selectedItem, 10);
|
||||
});
|
||||
|
||||
testWidgets('controller jump', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('controller jump', (WidgetTester tester) async {
|
||||
final FixedExtentScrollController controller = FixedExtentScrollController(initialItem: 10);
|
||||
addTearDown(controller.dispose);
|
||||
final List<int> paintedChildren = <int>[];
|
||||
|
||||
await tester.pumpWidget(
|
||||
|
@ -1245,8 +1260,9 @@ void main() {
|
|||
expect(controller.selectedItem, 0);
|
||||
});
|
||||
|
||||
testWidgets('controller animateToItem', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('controller animateToItem', (WidgetTester tester) async {
|
||||
final FixedExtentScrollController controller = FixedExtentScrollController(initialItem: 10);
|
||||
addTearDown(controller.dispose);
|
||||
final List<int> paintedChildren = <int>[];
|
||||
|
||||
await tester.pumpWidget(
|
||||
|
@ -1282,9 +1298,10 @@ void main() {
|
|||
expect(controller.selectedItem, 0);
|
||||
});
|
||||
|
||||
testWidgets('onSelectedItemChanged and controller are in sync', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('onSelectedItemChanged and controller are in sync', (WidgetTester tester) async {
|
||||
final List<int> selectedItems = <int>[];
|
||||
final FixedExtentScrollController controller = FixedExtentScrollController(initialItem: 10);
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
|
@ -1334,8 +1351,7 @@ void main() {
|
|||
await tester.drag(find.byType(ListWheelScrollView), const Offset(0.0, -500.0));
|
||||
await tester.pump();
|
||||
|
||||
final FixedExtentScrollController controller1 =
|
||||
FixedExtentScrollController(initialItem: 30);
|
||||
final FixedExtentScrollController controller1 = FixedExtentScrollController(initialItem: 30);
|
||||
addTearDown(controller1.dispose);
|
||||
|
||||
// Attaching first controller.
|
||||
|
@ -1360,8 +1376,7 @@ void main() {
|
|||
expect(controller1.selectedItem, 50);
|
||||
expect(controller1.position.pixels, 5000.0);
|
||||
|
||||
final FixedExtentScrollController controller2 =
|
||||
FixedExtentScrollController(initialItem: 33);
|
||||
final FixedExtentScrollController controller2 = FixedExtentScrollController(initialItem: 33);
|
||||
addTearDown(controller2.dispose);
|
||||
|
||||
// Attaching the second controller.
|
||||
|
@ -1407,8 +1422,7 @@ void main() {
|
|||
});
|
||||
|
||||
testWidgetsWithLeakTracking('controller can be reused', (WidgetTester tester) async {
|
||||
final FixedExtentScrollController controller =
|
||||
FixedExtentScrollController(initialItem: 3);
|
||||
final FixedExtentScrollController controller = FixedExtentScrollController(initialItem: 3);
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
await tester.pumpWidget(
|
||||
|
@ -1458,8 +1472,9 @@ void main() {
|
|||
});
|
||||
|
||||
group('physics', () {
|
||||
testWidgets('fling velocities too low snaps back to the same item', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('fling velocities too low snaps back to the same item', (WidgetTester tester) async {
|
||||
final FixedExtentScrollController controller = FixedExtentScrollController(initialItem: 40);
|
||||
addTearDown(controller.dispose);
|
||||
final List<double> scrolledPositions = <double>[];
|
||||
|
||||
await tester.pumpWidget(
|
||||
|
@ -1508,8 +1523,9 @@ void main() {
|
|||
expect(scrolledPositions.last, moreOrLessEquals(40 * 1000.0, epsilon: 0.2));
|
||||
});
|
||||
|
||||
testWidgets('high fling velocities lands exactly on items', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('high fling velocities lands exactly on items', (WidgetTester tester) async {
|
||||
final FixedExtentScrollController controller = FixedExtentScrollController(initialItem: 40);
|
||||
addTearDown(controller.dispose);
|
||||
final List<double> scrolledPositions = <double>[];
|
||||
|
||||
await tester.pumpWidget(
|
||||
|
@ -1561,9 +1577,11 @@ void main() {
|
|||
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
|
||||
});
|
||||
|
||||
testWidgets('ListWheelScrollView getOffsetToReveal', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('ListWheelScrollView getOffsetToReveal', (WidgetTester tester) async {
|
||||
List<Widget> outerChildren;
|
||||
final List<Widget> innerChildren = List<Widget>.generate(10, (int index) => Container());
|
||||
final ScrollController controller = ScrollController(initialScrollOffset: 300.0);
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
|
@ -1573,7 +1591,7 @@ void main() {
|
|||
height: 500.0,
|
||||
width: 300.0,
|
||||
child: ListWheelScrollView(
|
||||
controller: ScrollController(initialScrollOffset: 300.0),
|
||||
controller: controller,
|
||||
itemExtent: 100.0,
|
||||
children: outerChildren = List<Widget>.generate(10, (int i) {
|
||||
return Center(
|
||||
|
@ -1629,7 +1647,10 @@ void main() {
|
|||
expect(revealed.rect, const Rect.fromLTWH(165.0, 265.0, 10.0, 10.0));
|
||||
});
|
||||
|
||||
testWidgets('will not assert on getOffsetToReveal Axis', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('will not assert on getOffsetToReveal Axis', (WidgetTester tester) async {
|
||||
final ScrollController controller = ScrollController(initialScrollOffset: 300.0);
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
|
@ -1638,7 +1659,7 @@ void main() {
|
|||
height: 500.0,
|
||||
width: 300.0,
|
||||
child: ListWheelScrollView(
|
||||
controller: ScrollController(initialScrollOffset: 300.0),
|
||||
controller: controller,
|
||||
itemExtent: 100.0,
|
||||
children: List<Widget>.generate(10, (int i) {
|
||||
return Center(
|
||||
|
@ -1660,10 +1681,11 @@ void main() {
|
|||
viewport.getOffsetToReveal(target, 0.0, axis: Axis.horizontal);
|
||||
});
|
||||
|
||||
testWidgets('ListWheelScrollView showOnScreen', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('ListWheelScrollView showOnScreen', (WidgetTester tester) async {
|
||||
List<Widget> outerChildren;
|
||||
final List<Widget> innerChildren = List<Widget>.generate(10, (int index) => Container());
|
||||
ScrollController controller;
|
||||
final ScrollController controller = ScrollController(initialScrollOffset: 300.0);
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
|
@ -1673,7 +1695,7 @@ void main() {
|
|||
height: 500.0,
|
||||
width: 300.0,
|
||||
child: ListWheelScrollView(
|
||||
controller: controller = ScrollController(initialScrollOffset: 300.0),
|
||||
controller: controller,
|
||||
itemExtent: 100.0,
|
||||
children:
|
||||
outerChildren = List<Widget>.generate(10, (int i) {
|
||||
|
@ -1716,8 +1738,9 @@ void main() {
|
|||
});
|
||||
|
||||
group('gestures', () {
|
||||
testWidgets('ListWheelScrollView allows taps for on its children', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('ListWheelScrollView allows taps for on its children', (WidgetTester tester) async {
|
||||
final FixedExtentScrollController controller = FixedExtentScrollController(initialItem: 10);
|
||||
addTearDown(controller.dispose);
|
||||
final List<int> children = List<int>.generate(100, (int index) => index);
|
||||
final List<int> paintedChildren = <int>[];
|
||||
final Set<int> tappedChildren = <int>{};
|
||||
|
@ -1758,8 +1781,9 @@ void main() {
|
|||
expect(tappedChildren, paintedChildren);
|
||||
});
|
||||
|
||||
testWidgets('ListWheelScrollView allows for horizontal drags on its children', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('ListWheelScrollView allows for horizontal drags on its children', (WidgetTester tester) async {
|
||||
final PageController pageController = PageController();
|
||||
addTearDown(pageController.dispose);
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
|
@ -1785,10 +1809,11 @@ void main() {
|
|||
expect(pageController.page, 1.0);
|
||||
});
|
||||
|
||||
testWidgets('ListWheelScrollView does not crash and does not allow taps on children that were laid out, but not painted', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('ListWheelScrollView does not crash and does not allow taps on children that were laid out, but not painted', (WidgetTester tester) async {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/126491
|
||||
|
||||
final FixedExtentScrollController controller = FixedExtentScrollController();
|
||||
addTearDown(controller.dispose);
|
||||
final List<int> children = List<int>.generate(100, (int index) => index);
|
||||
final List<int> paintedChildren = <int>[];
|
||||
final Set<int> tappedChildren = <int>{};
|
||||
|
@ -1845,7 +1870,7 @@ void main() {
|
|||
});
|
||||
});
|
||||
|
||||
testWidgets('ListWheelScrollView creates only one opacity layer for all children', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('ListWheelScrollView creates only one opacity layer for all children', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
ListWheelScrollView(
|
||||
overAndUnderCenterOpacity: 0.5,
|
||||
|
|
|
@ -121,7 +121,7 @@ class SlideInOutPageRoute<T> extends PageRouteBuilder<T> {
|
|||
}
|
||||
|
||||
void main() {
|
||||
testWidgets('Can navigator navigate to and from a stateful widget', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Can navigator navigate to and from a stateful widget', (WidgetTester tester) async {
|
||||
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
|
||||
'/': (BuildContext context) => const FirstWidget(), // X
|
||||
'/second': (BuildContext context) => const SecondWidget(), // Y
|
||||
|
@ -171,7 +171,7 @@ void main() {
|
|||
expect(find.text('Y', skipOffstage: false), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('Navigator.of fails gracefully when not found in context', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Navigator.of fails gracefully when not found in context', (WidgetTester tester) async {
|
||||
const Key targetKey = Key('foo');
|
||||
dynamic exception;
|
||||
final Widget widget = ThirdWidget(
|
||||
|
@ -186,7 +186,7 @@ void main() {
|
|||
expect('$exception', startsWith('Navigator operation requested with a context'));
|
||||
});
|
||||
|
||||
testWidgets('Navigator can push Route created through page class as Pageless route', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Navigator can push Route created through page class as Pageless route', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> nav = GlobalKey<NavigatorState>();
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
|
@ -206,7 +206,7 @@ void main() {
|
|||
expect(find.text('home'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('Navigator can set clip behavior', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Navigator can set clip behavior', (WidgetTester tester) async {
|
||||
const MaterialPage<void> page = MaterialPage<void>(child: Text('page'));
|
||||
await tester.pumpWidget(
|
||||
MediaQuery(
|
||||
|
@ -239,7 +239,7 @@ void main() {
|
|||
expect(tester.widget<Overlay>(find.byType(Overlay)).clipBehavior, Clip.none);
|
||||
});
|
||||
|
||||
testWidgets('Zero transition page-based route correctly notifies observers when it is popped', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Zero transition page-based route correctly notifies observers when it is popped', (WidgetTester tester) async {
|
||||
final List<Page<void>> pages = <Page<void>>[
|
||||
const ZeroTransitionPage(name: 'Page 1'),
|
||||
const ZeroTransitionPage(name: 'Page 2'),
|
||||
|
@ -279,7 +279,7 @@ void main() {
|
|||
expect(observations[0].previous, 'Page 1');
|
||||
});
|
||||
|
||||
testWidgets('Navigator.of rootNavigator finds root Navigator', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Navigator.of rootNavigator finds root Navigator', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
home: Material(
|
||||
child: Column(
|
||||
|
@ -347,7 +347,7 @@ void main() {
|
|||
expect(tester.getTopLeft(find.text('Dialog')).dy, 0.0);
|
||||
});
|
||||
|
||||
testWidgets('Gestures between push and build are ignored', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Gestures between push and build are ignored', (WidgetTester tester) async {
|
||||
final List<String> log = <String>[];
|
||||
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
|
||||
'/': (BuildContext context) {
|
||||
|
@ -377,7 +377,7 @@ void main() {
|
|||
expect(log, equals(<String>['left']));
|
||||
});
|
||||
|
||||
testWidgets('pushnamed can handle Object as type', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('pushnamed can handle Object as type', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> nav = GlobalKey<NavigatorState>();
|
||||
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
|
||||
'/': (BuildContext context) => const Text('/'),
|
||||
|
@ -397,7 +397,7 @@ void main() {
|
|||
expect(find.text('/second'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('Pending gestures are rejected', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Pending gestures are rejected', (WidgetTester tester) async {
|
||||
final List<String> log = <String>[];
|
||||
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
|
||||
'/': (BuildContext context) {
|
||||
|
@ -428,7 +428,7 @@ void main() {
|
|||
expect(log, equals(<String>['left']));
|
||||
});
|
||||
|
||||
testWidgets('popAndPushNamed', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('popAndPushNamed', (WidgetTester tester) async {
|
||||
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
|
||||
'/' : (BuildContext context) => OnTapPage(id: '/', onTap: () { Navigator.pushNamed(context, '/A'); }),
|
||||
'/A': (BuildContext context) => OnTapPage(id: 'A', onTap: () { Navigator.popAndPushNamed(context, '/B'); }),
|
||||
|
@ -455,7 +455,7 @@ void main() {
|
|||
expect(find.text('B'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('popAndPushNamed with explicit void type parameter', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('popAndPushNamed with explicit void type parameter', (WidgetTester tester) async {
|
||||
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
|
||||
'/' : (BuildContext context) => OnTapPage(id: '/', onTap: () { Navigator.pushNamed<void>(context, '/A'); }),
|
||||
'/A': (BuildContext context) => OnTapPage(id: 'A', onTap: () { Navigator.popAndPushNamed<void, void>(context, '/B'); }),
|
||||
|
@ -482,7 +482,7 @@ void main() {
|
|||
expect(find.text('B'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('Push and pop should trigger the observers', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Push and pop should trigger the observers', (WidgetTester tester) async {
|
||||
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
|
||||
'/' : (BuildContext context) => OnTapPage(id: '/', onTap: () { Navigator.pushNamed(context, '/A'); }),
|
||||
'/A': (BuildContext context) => OnTapPage(id: 'A', onTap: () { Navigator.pop(context); }),
|
||||
|
@ -542,7 +542,7 @@ void main() {
|
|||
expect(isPopped, isTrue);
|
||||
});
|
||||
|
||||
testWidgets('Add and remove an observer should work', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Add and remove an observer should work', (WidgetTester tester) async {
|
||||
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
|
||||
'/' : (BuildContext context) => OnTapPage(id: '/', onTap: () { Navigator.pushNamed(context, '/A'); }),
|
||||
'/A': (BuildContext context) => OnTapPage(id: 'A', onTap: () { Navigator.pop(context); }),
|
||||
|
@ -589,7 +589,7 @@ void main() {
|
|||
expect(isPopped, isFalse);
|
||||
});
|
||||
|
||||
testWidgets('initial route trigger observer in the right order', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('initial route trigger observer in the right order', (WidgetTester tester) async {
|
||||
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
|
||||
'/' : (BuildContext context) => const Text('/'),
|
||||
'/A': (BuildContext context) => const Text('A'),
|
||||
|
@ -663,7 +663,7 @@ void main() {
|
|||
MemoryAllocations.instance.removeListener(listener);
|
||||
});
|
||||
|
||||
testWidgets('Route didAdd and dispose in same frame work', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Route didAdd and dispose in same frame work', (WidgetTester tester) async {
|
||||
// Regression Test for https://github.com/flutter/flutter/issues/61346.
|
||||
Widget buildNavigator() {
|
||||
return Navigator(
|
||||
|
@ -676,6 +676,8 @@ void main() {
|
|||
);
|
||||
}
|
||||
final TabController controller = TabController(length: 3, vsync: tester);
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
await tester.pumpWidget(
|
||||
TestDependencies(
|
||||
child: TabBarView(
|
||||
|
@ -694,7 +696,7 @@ void main() {
|
|||
await tester.pumpAndSettle();
|
||||
});
|
||||
|
||||
testWidgets('Page-based route pop before push finishes', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Page-based route pop before push finishes', (WidgetTester tester) async {
|
||||
List<Page<void>> pages = <Page<void>>[const MaterialPage<void>(child: Text('Page 1'))];
|
||||
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
|
||||
Widget buildNavigator() {
|
||||
|
@ -730,7 +732,7 @@ void main() {
|
|||
expect(find.text('Page 1'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('Pages update does update overlay correctly', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Pages update does update overlay correctly', (WidgetTester tester) async {
|
||||
// Regression Test for https://github.com/flutter/flutter/issues/64941.
|
||||
List<Page<void>> pages = const <Page<void>>[
|
||||
MaterialPage<void>(
|
||||
|
@ -779,7 +781,7 @@ void main() {
|
|||
expect(find.text('page 0'), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('replaceNamed replaces', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('replaceNamed replaces', (WidgetTester tester) async {
|
||||
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
|
||||
'/' : (BuildContext context) => OnTapPage(id: '/', onTap: () { Navigator.pushReplacementNamed(context, '/A'); }),
|
||||
'/A': (BuildContext context) => OnTapPage(id: 'A', onTap: () { Navigator.pushReplacementNamed(context, '/B'); }),
|
||||
|
@ -801,7 +803,7 @@ void main() {
|
|||
expect(find.text('B'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('pushReplacement sets secondaryAnimation after transition, with history change during transition', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('pushReplacement sets secondaryAnimation after transition, with history change during transition', (WidgetTester tester) async {
|
||||
final Map<String, SlideInOutPageRoute<dynamic>> routes = <String, SlideInOutPageRoute<dynamic>>{};
|
||||
final Map<String, WidgetBuilder> builders = <String, WidgetBuilder>{
|
||||
'/' : (BuildContext context) => OnTapPage(
|
||||
|
@ -858,7 +860,7 @@ void main() {
|
|||
expect(routes['/A']!.secondaryAnimation!.value, equals(routes['/C']!.animation!.value));
|
||||
});
|
||||
|
||||
testWidgets('new route removed from navigator history during pushReplacement transition', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('new route removed from navigator history during pushReplacement transition', (WidgetTester tester) async {
|
||||
final Map<String, SlideInOutPageRoute<dynamic>> routes = <String, SlideInOutPageRoute<dynamic>>{};
|
||||
final Map<String, WidgetBuilder> builders = <String, WidgetBuilder>{
|
||||
'/' : (BuildContext context) => OnTapPage(
|
||||
|
@ -904,7 +906,7 @@ void main() {
|
|||
expect(routes['/']!.animation!.value, equals(1.0));
|
||||
});
|
||||
|
||||
testWidgets('pushReplacement triggers secondaryAnimation', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('pushReplacement triggers secondaryAnimation', (WidgetTester tester) async {
|
||||
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
|
||||
'/' : (BuildContext context) => OnTapPage(
|
||||
id: '/',
|
||||
|
@ -953,7 +955,7 @@ void main() {
|
|||
expect(aOffset.dx, lessThan(aOffsetOriginal.dx));
|
||||
});
|
||||
|
||||
testWidgets('pushReplacement correctly reports didReplace to the observer', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('pushReplacement correctly reports didReplace to the observer', (WidgetTester tester) async {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/56892.
|
||||
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
|
||||
'/' : (BuildContext context) => const OnTapPage(
|
||||
|
@ -1021,7 +1023,7 @@ void main() {
|
|||
expect(find.text('C'), isOnstage);
|
||||
});
|
||||
|
||||
testWidgets('Able to pop all routes', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Able to pop all routes', (WidgetTester tester) async {
|
||||
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
|
||||
'/' : (BuildContext context) => const OnTapPage(
|
||||
id: '/',
|
||||
|
@ -1048,7 +1050,7 @@ void main() {
|
|||
expect(tester.takeException(), isNull);
|
||||
});
|
||||
|
||||
testWidgets('pushAndRemoveUntil triggers secondaryAnimation', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('pushAndRemoveUntil triggers secondaryAnimation', (WidgetTester tester) async {
|
||||
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
|
||||
'/' : (BuildContext context) => OnTapPage(
|
||||
id: '/',
|
||||
|
@ -1102,7 +1104,7 @@ void main() {
|
|||
expect(find.text('B'), isOnstage);
|
||||
});
|
||||
|
||||
testWidgets('pushAndRemoveUntil does not remove routes below the first route that pass the predicate', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('pushAndRemoveUntil does not remove routes below the first route that pass the predicate', (WidgetTester tester) async {
|
||||
// Regression https://github.com/flutter/flutter/issues/56688
|
||||
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
|
||||
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
|
||||
|
@ -1138,7 +1140,7 @@ void main() {
|
|||
expect(find.text('home'), isOnstage);
|
||||
});
|
||||
|
||||
testWidgets('replaceNamed returned value', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('replaceNamed returned value', (WidgetTester tester) async {
|
||||
late Future<String?> value;
|
||||
|
||||
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
|
||||
|
@ -1187,7 +1189,7 @@ void main() {
|
|||
expect(replaceNamedValue, 'B');
|
||||
});
|
||||
|
||||
testWidgets('removeRoute', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('removeRoute', (WidgetTester tester) async {
|
||||
final Map<String, WidgetBuilder> pageBuilders = <String, WidgetBuilder>{
|
||||
'/' : (BuildContext context) => OnTapPage(id: '/', onTap: () { Navigator.pushNamed(context, '/A'); }),
|
||||
'/A': (BuildContext context) => OnTapPage(id: 'A', onTap: () { Navigator.pushNamed(context, '/B'); }),
|
||||
|
@ -1273,7 +1275,7 @@ void main() {
|
|||
expect(previousRoute, routes['/']);
|
||||
});
|
||||
|
||||
testWidgets('remove a route whose value is awaited', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('remove a route whose value is awaited', (WidgetTester tester) async {
|
||||
late Future<String?> pageValue;
|
||||
final Map<String, WidgetBuilder> pageBuilders = <String, WidgetBuilder>{
|
||||
'/': (BuildContext context) => OnTapPage(id: '/', onTap: () { pageValue = Navigator.pushNamed(context, '/A'); }),
|
||||
|
@ -1301,7 +1303,7 @@ void main() {
|
|||
navigator.removeRoute(routes['/A']!); // stack becomes /, pageValue will not complete
|
||||
});
|
||||
|
||||
testWidgets('replacing route can be observed', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('replacing route can be observed', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> key = GlobalKey<NavigatorState>();
|
||||
final List<String> log = <String>[];
|
||||
final TestObserver observer = TestObserver()
|
||||
|
@ -1371,7 +1373,7 @@ void main() {
|
|||
expect(log, <String>['pushed / (previous is <none>)', 'pushed B (previous is /)', 'pushed C (previous is B)', 'replaced B with D']);
|
||||
});
|
||||
|
||||
testWidgets('didStartUserGesture observable', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('didStartUserGesture observable', (WidgetTester tester) async {
|
||||
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
|
||||
'/' : (BuildContext context) => OnTapPage(id: '/', onTap: () { Navigator.pushNamed(context, '/A'); }),
|
||||
'/A': (BuildContext context) => OnTapPage(id: 'A', onTap: () { Navigator.pop(context); }),
|
||||
|
@ -1402,7 +1404,7 @@ void main() {
|
|||
expect(observedPreviousRoute.settings.name, '/');
|
||||
});
|
||||
|
||||
testWidgets('ModalRoute.of sets up a route to rebuild if its state changes', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('ModalRoute.of sets up a route to rebuild if its state changes', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> key = GlobalKey<NavigatorState>();
|
||||
final List<String> log = <String>[];
|
||||
late Route<void> routeB;
|
||||
|
@ -1469,7 +1471,7 @@ void main() {
|
|||
expect(log, <String>['building B', 'building C', 'found C', 'building D']);
|
||||
});
|
||||
|
||||
testWidgets("Routes don't rebuild just because their animations ended", (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking("Routes don't rebuild just because their animations ended", (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> key = GlobalKey<NavigatorState>();
|
||||
final List<String> log = <String>[];
|
||||
Route<dynamic>? nextRoute = PageRouteBuilder<int>(
|
||||
|
@ -1512,7 +1514,7 @@ void main() {
|
|||
expect(log, <String>['building page 1 - false', 'building page 2 - false', 'building page 3 - false']);
|
||||
});
|
||||
|
||||
testWidgets('route semantics', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('route semantics', (WidgetTester tester) async {
|
||||
final SemanticsTester semantics = SemanticsTester(tester);
|
||||
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
|
||||
'/': (BuildContext context) => OnTapPage(id: '1', onTap: () { Navigator.pushNamed(context, '/A'); }),
|
||||
|
@ -1569,7 +1571,7 @@ void main() {
|
|||
semantics.dispose();
|
||||
});
|
||||
|
||||
testWidgets('arguments for named routes on Navigator', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('arguments for named routes on Navigator', (WidgetTester tester) async {
|
||||
late GlobalKey currentRouteKey;
|
||||
final List<Object?> arguments = <Object?>[];
|
||||
|
||||
|
@ -1643,7 +1645,7 @@ void main() {
|
|||
arguments.clear();
|
||||
});
|
||||
|
||||
testWidgets('arguments for named routes on NavigatorState', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('arguments for named routes on NavigatorState', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
|
||||
final List<Object?> arguments = <Object?>[];
|
||||
|
||||
|
@ -1714,7 +1716,7 @@ void main() {
|
|||
arguments.clear();
|
||||
});
|
||||
|
||||
testWidgets('Initial route can have gaps', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Initial route can have gaps', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> keyNav = GlobalKey<NavigatorState>();
|
||||
const Key keyRoot = Key('Root');
|
||||
const Key keyA = Key('A');
|
||||
|
@ -1745,7 +1747,7 @@ void main() {
|
|||
expect(find.byKey(keyABC, skipOffstage: false), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('The full initial route has to be matched', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('The full initial route has to be matched', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> keyNav = GlobalKey<NavigatorState>();
|
||||
const Key keyRoot = Key('Root');
|
||||
const Key keyA = Key('A');
|
||||
|
@ -1775,7 +1777,7 @@ void main() {
|
|||
expect(find.byKey(keyAB), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets("Popping immediately after pushing doesn't crash", (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking("Popping immediately after pushing doesn't crash", (WidgetTester tester) async {
|
||||
// Added this test to protect against regression of https://github.com/flutter/flutter/issues/45539
|
||||
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
|
||||
'/' : (BuildContext context) => OnTapPage(id: '/', onTap: () {
|
||||
|
@ -1824,7 +1826,7 @@ void main() {
|
|||
});
|
||||
|
||||
group('error control test', () {
|
||||
testWidgets('onUnknownRoute null and onGenerateRoute returns null', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('onUnknownRoute null and onGenerateRoute returns null', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
|
||||
await tester.pumpWidget(Navigator(
|
||||
key: navigatorKey,
|
||||
|
@ -1850,7 +1852,7 @@ void main() {
|
|||
);
|
||||
});
|
||||
|
||||
testWidgets('onUnknownRoute null and onGenerateRoute returns null', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('onUnknownRoute null and onGenerateRoute returns null', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
|
||||
await tester.pumpWidget(Navigator(
|
||||
key: navigatorKey,
|
||||
|
@ -1877,7 +1879,7 @@ void main() {
|
|||
});
|
||||
});
|
||||
|
||||
testWidgets('OverlayEntry of topmost initial route is marked as opaque', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('OverlayEntry of topmost initial route is marked as opaque', (WidgetTester tester) async {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/38038.
|
||||
|
||||
final Key root = UniqueKey();
|
||||
|
@ -1901,7 +1903,7 @@ void main() {
|
|||
expect(find.byKey(topmost), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('OverlayEntry of topmost route is set to opaque after Push', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('OverlayEntry of topmost route is set to opaque after Push', (WidgetTester tester) async {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/38038.
|
||||
|
||||
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
|
||||
|
@ -1928,7 +1930,7 @@ void main() {
|
|||
expect(find.byKey(const ValueKey<String>('/A')), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('OverlayEntry of topmost route is set to opaque after Replace', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('OverlayEntry of topmost route is set to opaque after Replace', (WidgetTester tester) async {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/38038.
|
||||
|
||||
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
|
||||
|
@ -1973,7 +1975,7 @@ void main() {
|
|||
expect(find.byKey(const ValueKey<String>('/C')), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('Pushing opaque Route does not rebuild routes below', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Pushing opaque Route does not rebuild routes below', (WidgetTester tester) async {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/45797.
|
||||
|
||||
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
|
||||
|
@ -2007,7 +2009,7 @@ void main() {
|
|||
expect(tester.state<StatefulTestState>(find.byKey(topRoute)).rebuildCount, 1);
|
||||
});
|
||||
|
||||
testWidgets('initial routes below opaque route are offstage', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('initial routes below opaque route are offstage', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> testKey = GlobalKey<NavigatorState>();
|
||||
await tester.pumpWidget(
|
||||
TestDependencies(
|
||||
|
@ -2048,7 +2050,7 @@ void main() {
|
|||
expect(find.text('+/a/b+'), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('Can provide custom onGenerateInitialRoutes', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Can provide custom onGenerateInitialRoutes', (WidgetTester tester) async {
|
||||
bool onGenerateInitialRoutesCalled = false;
|
||||
final GlobalKey<NavigatorState> testKey = GlobalKey<NavigatorState>();
|
||||
await tester.pumpWidget(
|
||||
|
@ -2081,7 +2083,7 @@ void main() {
|
|||
expect(find.text('World'), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('Navigator.of able to handle input context is a navigator context', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Navigator.of able to handle input context is a navigator context', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> testKey = GlobalKey<NavigatorState>();
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
|
@ -2094,7 +2096,7 @@ void main() {
|
|||
expect(state, testKey.currentState);
|
||||
});
|
||||
|
||||
testWidgets('Navigator.of able to handle input context is a navigator context - root navigator', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Navigator.of able to handle input context is a navigator context - root navigator', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> root = GlobalKey<NavigatorState>();
|
||||
final GlobalKey<NavigatorState> sub = GlobalKey<NavigatorState>();
|
||||
await tester.pumpWidget(
|
||||
|
@ -2116,7 +2118,7 @@ void main() {
|
|||
expect(state, root.currentState);
|
||||
});
|
||||
|
||||
testWidgets('Navigator.maybeOf throws when there is no navigator', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Navigator.maybeOf throws when there is no navigator', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> testKey = GlobalKey<NavigatorState>();
|
||||
await tester.pumpWidget(SizedBox(key: testKey));
|
||||
|
||||
|
@ -2125,7 +2127,7 @@ void main() {
|
|||
}, throwsFlutterError);
|
||||
});
|
||||
|
||||
testWidgets('Navigator.maybeOf works when there is no navigator', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Navigator.maybeOf works when there is no navigator', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> testKey = GlobalKey<NavigatorState>();
|
||||
await tester.pumpWidget(SizedBox(key: testKey));
|
||||
|
||||
|
@ -2133,7 +2135,7 @@ void main() {
|
|||
expect(state, isNull);
|
||||
});
|
||||
|
||||
testWidgets('Navigator.maybeOf able to handle input context is a navigator context', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Navigator.maybeOf able to handle input context is a navigator context', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> testKey = GlobalKey<NavigatorState>();
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
|
@ -2147,7 +2149,7 @@ void main() {
|
|||
expect(state, testKey.currentState);
|
||||
});
|
||||
|
||||
testWidgets('Navigator.maybeOf able to handle input context is a navigator context - root navigator', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Navigator.maybeOf able to handle input context is a navigator context - root navigator', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> root = GlobalKey<NavigatorState>();
|
||||
final GlobalKey<NavigatorState> sub = GlobalKey<NavigatorState>();
|
||||
await tester.pumpWidget(
|
||||
|
@ -2170,7 +2172,7 @@ void main() {
|
|||
expect(state, root.currentState);
|
||||
});
|
||||
|
||||
testWidgets('pushAndRemove until animates the push', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('pushAndRemove until animates the push', (WidgetTester tester) async {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/25080.
|
||||
|
||||
const Duration kFourTenthsOfTheTransitionDuration = Duration(milliseconds: 120);
|
||||
|
@ -2252,7 +2254,7 @@ void main() {
|
|||
expect(find.text('Route: 4', skipOffstage: false), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('Wrapping TickerMode can turn off ticking in routes', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Wrapping TickerMode can turn off ticking in routes', (WidgetTester tester) async {
|
||||
int tickCount = 0;
|
||||
Widget widgetUnderTest({required bool enabled}) {
|
||||
return TickerMode(
|
||||
|
@ -2345,7 +2347,7 @@ void main() {
|
|||
expect(popNextOfFirst, secondRoute);
|
||||
});
|
||||
|
||||
testWidgets('hero controller scope works', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('hero controller scope works', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> top = GlobalKey<NavigatorState>();
|
||||
final GlobalKey<NavigatorState> sub = GlobalKey<NavigatorState>();
|
||||
|
||||
|
@ -2415,7 +2417,7 @@ void main() {
|
|||
expect(observations[1].previous, 'top1');
|
||||
});
|
||||
|
||||
testWidgets('hero controller can correctly transfer subscription - replacing navigator', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('hero controller can correctly transfer subscription - replacing navigator', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> key1 = GlobalKey<NavigatorState>();
|
||||
final GlobalKey<NavigatorState> key2 = GlobalKey<NavigatorState>();
|
||||
|
||||
|
@ -2484,7 +2486,7 @@ void main() {
|
|||
expect(observations[0].previous, 'navigator2');
|
||||
});
|
||||
|
||||
testWidgets('hero controller can correctly transfer subscription - swapping navigator', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('hero controller can correctly transfer subscription - swapping navigator', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> key1 = GlobalKey<NavigatorState>();
|
||||
final GlobalKey<NavigatorState> key2 = GlobalKey<NavigatorState>();
|
||||
|
||||
|
@ -2624,7 +2626,7 @@ void main() {
|
|||
expect(observations2[1].previous, 'navigator1');
|
||||
});
|
||||
|
||||
testWidgets('hero controller subscribes to multiple navigators does throw', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('hero controller subscribes to multiple navigators does throw', (WidgetTester tester) async {
|
||||
final HeroControllerSpy spy = HeroControllerSpy();
|
||||
await tester.pumpWidget(
|
||||
HeroControllerScope(
|
||||
|
@ -2662,7 +2664,7 @@ void main() {
|
|||
expect(tester.takeException(), isAssertionError);
|
||||
});
|
||||
|
||||
testWidgets('hero controller throws has correct error message', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('hero controller throws has correct error message', (WidgetTester tester) async {
|
||||
final HeroControllerSpy spy = HeroControllerSpy();
|
||||
await tester.pumpWidget(
|
||||
HeroControllerScope(
|
||||
|
@ -2746,7 +2748,7 @@ void main() {
|
|||
);
|
||||
}
|
||||
|
||||
testWidgets('can initialize with pages list', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('can initialize with pages list', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
|
||||
final List<TestPage> myPages = <TestPage>[
|
||||
const TestPage(key: ValueKey<String>('1'), name:'initial'),
|
||||
|
@ -2784,7 +2786,7 @@ void main() {
|
|||
expect(find.text('initial'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('can handle duplicate page key if update before transition finishes', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('can handle duplicate page key if update before transition finishes', (WidgetTester tester) async {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/97363.
|
||||
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
|
||||
final List<TestPage> myPages1 = <TestPage>[
|
||||
|
@ -2840,7 +2842,7 @@ void main() {
|
|||
expect(tester.takeException(), isNull);
|
||||
});
|
||||
|
||||
testWidgets('throw if onPopPage callback is not provided', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('throw if onPopPage callback is not provided', (WidgetTester tester) async {
|
||||
final List<TestPage> myPages = <TestPage>[
|
||||
const TestPage(key: ValueKey<String>('1'), name:'initial'),
|
||||
const TestPage(key: ValueKey<String>('2'), name:'second'),
|
||||
|
@ -2910,7 +2912,7 @@ void main() {
|
|||
);
|
||||
});
|
||||
|
||||
testWidgets('Can pop route with local history entries using page api', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Can pop route with local history entries using page api', (WidgetTester tester) async {
|
||||
List<Page<void>> myPages = const <Page<void>>[
|
||||
MaterialPage<void>(child: Text('page1')),
|
||||
MaterialPage<void>(child: Text('page2')),
|
||||
|
@ -2961,7 +2963,7 @@ void main() {
|
|||
expect(entryRemoved, isTrue);
|
||||
});
|
||||
|
||||
testWidgets('ModalRoute must comply with willHandlePopInternally when there is a PopScope', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('ModalRoute must comply with willHandlePopInternally when there is a PopScope', (WidgetTester tester) async {
|
||||
const List<Page<void>> myPages = <Page<void>>[
|
||||
MaterialPage<void>(child: Text('page1')),
|
||||
MaterialPage<void>(
|
||||
|
@ -2994,7 +2996,7 @@ void main() {
|
|||
expect(route.didPop(null), true);
|
||||
});
|
||||
|
||||
testWidgets('can push and pop pages using page api', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('can push and pop pages using page api', (WidgetTester tester) async {
|
||||
late Animation<double> secondaryAnimationOfRouteOne;
|
||||
late Animation<double> primaryAnimationOfRouteOne;
|
||||
late Animation<double> secondaryAnimationOfRouteTwo;
|
||||
|
@ -3143,7 +3145,7 @@ void main() {
|
|||
expect(primaryAnimationOfRouteThree.status, AnimationStatus.dismissed);
|
||||
});
|
||||
|
||||
testWidgets('can modify routes history and secondary animation still works', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('can modify routes history and secondary animation still works', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
|
||||
late Animation<double> secondaryAnimationOfRouteOne;
|
||||
late Animation<double> primaryAnimationOfRouteOne;
|
||||
|
@ -3254,7 +3256,7 @@ void main() {
|
|||
expect(primaryAnimationOfRouteOne.status, AnimationStatus.dismissed);
|
||||
});
|
||||
|
||||
testWidgets('Pop no animation page does not crash', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Pop no animation page does not crash', (WidgetTester tester) async {
|
||||
// Regression Test for https://github.com/flutter/flutter/issues/86604.
|
||||
Widget buildNavigator(bool secondPage) {
|
||||
return TestDependencies(
|
||||
|
@ -3279,7 +3281,7 @@ void main() {
|
|||
expect(find.text('page1'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('can work with pageless route', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('can work with pageless route', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
|
||||
List<TestPage> myPages = <TestPage>[
|
||||
const TestPage(key: ValueKey<String>('1'), name:'initial'),
|
||||
|
@ -3427,7 +3429,7 @@ void main() {
|
|||
expect(myPages.length, 1);
|
||||
});
|
||||
|
||||
testWidgets('complex case 1', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('complex case 1', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
|
||||
List<TestPage> myPages = <TestPage>[
|
||||
const TestPage(key: ValueKey<String>('1'), name: 'initial'),
|
||||
|
@ -3564,7 +3566,7 @@ void main() {
|
|||
});
|
||||
|
||||
//Regression test for https://github.com/flutter/flutter/issues/115887
|
||||
testWidgets('Complex case 2', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Complex case 2', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
|
||||
List<TestPage> myPages = <TestPage>[
|
||||
const TestPage(key: ValueKey<String>('1'), name:'initial'),
|
||||
|
@ -3628,7 +3630,7 @@ void main() {
|
|||
expect(find.text('second-pageless1'), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('complex case 1 - with always remove transition delegate', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('complex case 1 - with always remove transition delegate', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
|
||||
final AlwaysRemoveTransitionDelegate transitionDelegate = AlwaysRemoveTransitionDelegate();
|
||||
List<TestPage> myPages = <TestPage>[
|
||||
|
@ -3773,7 +3775,7 @@ void main() {
|
|||
expect(find.text('forth'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('can repush a page that was previously popped before it has finished popping', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('can repush a page that was previously popped before it has finished popping', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
|
||||
List<Page<dynamic>> myPages = <TestPage>[
|
||||
const TestPage(key: ValueKey<String>('1'), name: 'initial'),
|
||||
|
@ -3825,7 +3827,7 @@ void main() {
|
|||
expect(find.text('second'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('can update pages before a route has finished popping', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('can update pages before a route has finished popping', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
|
||||
List<Page<dynamic>> myPages = <TestPage>[
|
||||
const TestPage(key: ValueKey<String>('1'), name: 'initial'),
|
||||
|
@ -3876,7 +3878,7 @@ void main() {
|
|||
expect(find.text('initial'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('can update pages before a pageless route has finished popping', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('can update pages before a pageless route has finished popping', (WidgetTester tester) async {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/68162.
|
||||
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
|
||||
List<Page<dynamic>> myPages = <TestPage>[
|
||||
|
@ -3923,7 +3925,7 @@ void main() {
|
|||
expect(find.text('initial'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('pages remove and add trigger observer in the right order', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('pages remove and add trigger observer in the right order', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
|
||||
List<TestPage> myPages = <TestPage>[
|
||||
const TestPage(key: ValueKey<String>('1'), name:'first'),
|
||||
|
@ -4016,7 +4018,7 @@ void main() {
|
|||
});
|
||||
});
|
||||
|
||||
testWidgets('Can reuse NavigatorObserver in rebuilt tree', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Can reuse NavigatorObserver in rebuilt tree', (WidgetTester tester) async {
|
||||
final NavigatorObserver observer = NavigatorObserver();
|
||||
Widget build([Key? key]) {
|
||||
return TestDependencies(
|
||||
|
@ -4051,7 +4053,7 @@ void main() {
|
|||
expect(observer.navigator, tester.state<NavigatorState>(find.byType(Navigator)));
|
||||
});
|
||||
|
||||
testWidgets('Navigator requests focus if requestFocus is true', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Navigator requests focus if requestFocus is true', (WidgetTester tester) async {
|
||||
final GlobalKey navigatorKey = GlobalKey();
|
||||
final GlobalKey innerKey = GlobalKey();
|
||||
final Map<String, Widget> routes = <String, Widget>{
|
||||
|
@ -4060,6 +4062,7 @@ void main() {
|
|||
};
|
||||
late final NavigatorState navigator = navigatorKey.currentState! as NavigatorState;
|
||||
final FocusScopeNode focusNode = FocusScopeNode();
|
||||
addTearDown(focusNode.dispose);
|
||||
|
||||
await tester.pumpWidget(Column(
|
||||
children: <Widget>[
|
||||
|
@ -4126,7 +4129,7 @@ void main() {
|
|||
expect(focusNode.hasFocus, true);
|
||||
});
|
||||
|
||||
testWidgets('Navigator does not request focus if requestFocus is false', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Navigator does not request focus if requestFocus is false', (WidgetTester tester) async {
|
||||
final GlobalKey navigatorKey = GlobalKey();
|
||||
final GlobalKey innerKey = GlobalKey();
|
||||
final Map<String, Widget> routes = <String, Widget>{
|
||||
|
@ -4136,6 +4139,7 @@ void main() {
|
|||
late final NavigatorState navigator =
|
||||
navigatorKey.currentState! as NavigatorState;
|
||||
final FocusScopeNode focusNode = FocusScopeNode();
|
||||
addTearDown(focusNode.dispose);
|
||||
|
||||
await tester.pumpWidget(Column(
|
||||
children: <Widget>[
|
||||
|
@ -4192,7 +4196,7 @@ void main() {
|
|||
expect(focusNode.hasFocus, true);
|
||||
});
|
||||
|
||||
testWidgets('class implementing NavigatorObserver can be used without problems', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('class implementing NavigatorObserver can be used without problems', (WidgetTester tester) async {
|
||||
final _MockNavigatorObserver observer = _MockNavigatorObserver();
|
||||
Widget build([Key? key]) {
|
||||
return TestDependencies(
|
||||
|
@ -4224,7 +4228,7 @@ void main() {
|
|||
observer._checkInvocations(<Symbol>[#navigator, #navigator]);
|
||||
});
|
||||
|
||||
testWidgets("Navigator doesn't override FocusTraversalPolicy of ancestors", (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking("Navigator doesn't override FocusTraversalPolicy of ancestors", (WidgetTester tester) async {
|
||||
FocusTraversalPolicy? policy;
|
||||
await tester.pumpWidget(
|
||||
TestDependencies(
|
||||
|
@ -4247,7 +4251,7 @@ void main() {
|
|||
expect(policy, isA<WidgetOrderTraversalPolicy>());
|
||||
});
|
||||
|
||||
testWidgets('Navigator inserts ReadingOrderTraversalPolicy if no ancestor has a policy', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Navigator inserts ReadingOrderTraversalPolicy if no ancestor has a policy', (WidgetTester tester) async {
|
||||
FocusTraversalPolicy? policy;
|
||||
await tester.pumpWidget(
|
||||
TestDependencies(
|
||||
|
@ -4302,7 +4306,7 @@ void main() {
|
|||
.setMockMethodCallHandler(SystemChannels.platform, null);
|
||||
});
|
||||
|
||||
testWidgets('a single route is already defaulted to false', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('a single route is already defaulted to false', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
const MaterialApp(
|
||||
home: Scaffold(
|
||||
|
@ -4317,7 +4321,7 @@ void main() {
|
|||
skip: isBrowser, // [intended] only non-web Android supports predictive back.
|
||||
);
|
||||
|
||||
testWidgets('navigating around a single Navigator with .pop', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('navigating around a single Navigator with .pop', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
initialRoute: '/',
|
||||
|
@ -4394,7 +4398,7 @@ void main() {
|
|||
skip: isBrowser, // [intended] only non-web Android supports predictive back.
|
||||
);
|
||||
|
||||
testWidgets('navigating around a single Navigator with system back', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('navigating around a single Navigator with system back', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
initialRoute: '/',
|
||||
|
@ -4471,7 +4475,7 @@ void main() {
|
|||
skip: isBrowser, // [intended] only non-web Android supports predictive back.
|
||||
);
|
||||
|
||||
testWidgets('a single Navigator with a PopScope that defaults to enabled', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('a single Navigator with a PopScope that defaults to enabled', (WidgetTester tester) async {
|
||||
bool canPop = true;
|
||||
late StateSetter setState;
|
||||
await tester.pumpWidget(
|
||||
|
@ -4511,7 +4515,7 @@ void main() {
|
|||
skip: isBrowser, // [intended] only non-web Android supports predictive back.
|
||||
);
|
||||
|
||||
testWidgets('a single Navigator with a PopScope that defaults to disabled', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('a single Navigator with a PopScope that defaults to disabled', (WidgetTester tester) async {
|
||||
bool canPop = false;
|
||||
late StateSetter setState;
|
||||
await tester.pumpWidget(
|
||||
|
@ -4553,7 +4557,7 @@ void main() {
|
|||
|
||||
// Test both system back gestures and Navigator.pop.
|
||||
for (final _BackType backType in _BackType.values) {
|
||||
testWidgets('navigating around nested Navigators', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('navigating around nested Navigators', (WidgetTester tester) async {
|
||||
final GlobalKey<NavigatorState> nav = GlobalKey<NavigatorState>();
|
||||
final GlobalKey<NavigatorState> nestedNav = GlobalKey<NavigatorState>();
|
||||
Future<void> goBack() async {
|
||||
|
@ -4653,7 +4657,7 @@ void main() {
|
|||
);
|
||||
}
|
||||
|
||||
testWidgets('nested Navigators with a nested PopScope', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('nested Navigators with a nested PopScope', (WidgetTester tester) async {
|
||||
bool canPop = true;
|
||||
late StateSetter setState;
|
||||
await tester.pumpWidget(
|
||||
|
@ -4780,7 +4784,7 @@ void main() {
|
|||
);
|
||||
|
||||
group('Navigator page API', () {
|
||||
testWidgets('starting with one route as usual', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('starting with one route as usual', (WidgetTester tester) async {
|
||||
late StateSetter builderSetState;
|
||||
final List<_Page> pages = <_Page>[_Page.home];
|
||||
bool canPop() => pages.length <= 1;
|
||||
|
@ -4898,7 +4902,7 @@ void main() {
|
|||
skip: isBrowser, // [intended] only non-web Android supports predictive back.
|
||||
);
|
||||
|
||||
testWidgets('starting with existing route history', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('starting with existing route history', (WidgetTester tester) async {
|
||||
final List<_Page> pages = <_Page>[_Page.home, _Page.one];
|
||||
bool canPop() => pages.length <= 1;
|
||||
|
||||
|
|
|
@ -5,20 +5,26 @@
|
|||
import 'package:flutter/foundation.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('OverflowEntries context contains Overlay', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('OverflowEntries context contains Overlay', (WidgetTester tester) async {
|
||||
final GlobalKey overlayKey = GlobalKey();
|
||||
bool didBuild = false;
|
||||
late final OverlayEntry overlayEntry1;
|
||||
addTearDown(() => overlayEntry1..remove()..dispose());
|
||||
late final OverlayEntry overlayEntry2;
|
||||
addTearDown(() => overlayEntry2..remove()..dispose());
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Overlay(
|
||||
key: overlayKey,
|
||||
initialEntries: <OverlayEntry>[
|
||||
OverlayEntry(
|
||||
overlayEntry1 = OverlayEntry(
|
||||
builder: (BuildContext context) {
|
||||
didBuild = true;
|
||||
final Overlay overlay = context.findAncestorWidgetOfExactType<Overlay>()!;
|
||||
|
@ -26,7 +32,7 @@ void main() {
|
|||
return Container();
|
||||
},
|
||||
),
|
||||
OverlayEntry(
|
||||
overlayEntry2 = OverlayEntry(
|
||||
builder: (BuildContext context) => Container(),
|
||||
),
|
||||
],
|
||||
|
@ -80,25 +86,32 @@ void main() {
|
|||
);
|
||||
});
|
||||
|
||||
testWidgets('Offstage overlay', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Offstage overlay', (WidgetTester tester) async {
|
||||
final GlobalKey overlayKey = GlobalKey();
|
||||
late final OverlayEntry overlayEntry1;
|
||||
addTearDown(() => overlayEntry1..remove()..dispose());
|
||||
late final OverlayEntry overlayEntry2;
|
||||
addTearDown(() => overlayEntry2..remove()..dispose());
|
||||
late final OverlayEntry overlayEntry3;
|
||||
addTearDown(() => overlayEntry3..remove()..dispose());
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Overlay(
|
||||
key: overlayKey,
|
||||
initialEntries: <OverlayEntry>[
|
||||
OverlayEntry(
|
||||
overlayEntry1 = OverlayEntry(
|
||||
opaque: true,
|
||||
maintainState: true,
|
||||
builder: (BuildContext context) => Container(),
|
||||
),
|
||||
OverlayEntry(
|
||||
overlayEntry2 = OverlayEntry(
|
||||
opaque: true,
|
||||
maintainState: true,
|
||||
builder: (BuildContext context) => Container(),
|
||||
),
|
||||
OverlayEntry(
|
||||
overlayEntry3 = OverlayEntry(
|
||||
opaque: true,
|
||||
maintainState: true,
|
||||
builder: (BuildContext context) => Container(),
|
||||
|
@ -163,16 +176,19 @@ void main() {
|
|||
);
|
||||
});
|
||||
|
||||
testWidgets('insert top', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('insert top', (WidgetTester tester) async {
|
||||
final GlobalKey overlayKey = GlobalKey();
|
||||
final List<String> buildOrder = <String>[];
|
||||
late final OverlayEntry baseEntry;
|
||||
addTearDown(() => baseEntry..remove()..dispose());
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Overlay(
|
||||
key: overlayKey,
|
||||
initialEntries: <OverlayEntry>[
|
||||
OverlayEntry(
|
||||
baseEntry = OverlayEntry(
|
||||
builder: (BuildContext context) {
|
||||
buildOrder.add('Base');
|
||||
return Container();
|
||||
|
@ -187,8 +203,10 @@ void main() {
|
|||
|
||||
buildOrder.clear();
|
||||
final OverlayState overlay = overlayKey.currentState! as OverlayState;
|
||||
late final OverlayEntry newEntry;
|
||||
addTearDown(() => newEntry..remove()..dispose());
|
||||
overlay.insert(
|
||||
OverlayEntry(
|
||||
newEntry = OverlayEntry(
|
||||
builder: (BuildContext context) {
|
||||
buildOrder.add('New');
|
||||
return Container();
|
||||
|
@ -200,17 +218,19 @@ void main() {
|
|||
expect(buildOrder, <String>['Base', 'New']);
|
||||
});
|
||||
|
||||
testWidgets('insert below', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('insert below', (WidgetTester tester) async {
|
||||
final GlobalKey overlayKey = GlobalKey();
|
||||
OverlayEntry base;
|
||||
late final OverlayEntry baseEntry;
|
||||
addTearDown(() => baseEntry..remove()..dispose());
|
||||
final List<String> buildOrder = <String>[];
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Overlay(
|
||||
key: overlayKey,
|
||||
initialEntries: <OverlayEntry>[
|
||||
base = OverlayEntry(
|
||||
baseEntry = OverlayEntry(
|
||||
builder: (BuildContext context) {
|
||||
buildOrder.add('Base');
|
||||
return Container();
|
||||
|
@ -225,37 +245,43 @@ void main() {
|
|||
|
||||
buildOrder.clear();
|
||||
final OverlayState overlay = overlayKey.currentState! as OverlayState;
|
||||
late final OverlayEntry newEntry;
|
||||
addTearDown(() => newEntry..remove()..dispose());
|
||||
overlay.insert(
|
||||
OverlayEntry(
|
||||
newEntry = OverlayEntry(
|
||||
builder: (BuildContext context) {
|
||||
buildOrder.add('New');
|
||||
return Container();
|
||||
},
|
||||
),
|
||||
below: base,
|
||||
below: baseEntry,
|
||||
);
|
||||
await tester.pump();
|
||||
|
||||
expect(buildOrder, <String>['New', 'Base']);
|
||||
});
|
||||
|
||||
testWidgets('insert above', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('insert above', (WidgetTester tester) async {
|
||||
final GlobalKey overlayKey = GlobalKey();
|
||||
OverlayEntry base;
|
||||
late final OverlayEntry baseEntry;
|
||||
addTearDown(() => baseEntry..remove()..dispose());
|
||||
late final OverlayEntry topEntry;
|
||||
addTearDown(() => topEntry..remove()..dispose());
|
||||
final List<String> buildOrder = <String>[];
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Overlay(
|
||||
key: overlayKey,
|
||||
initialEntries: <OverlayEntry>[
|
||||
base = OverlayEntry(
|
||||
baseEntry = OverlayEntry(
|
||||
builder: (BuildContext context) {
|
||||
buildOrder.add('Base');
|
||||
return Container();
|
||||
},
|
||||
),
|
||||
OverlayEntry(
|
||||
topEntry = OverlayEntry(
|
||||
builder: (BuildContext context) {
|
||||
buildOrder.add('Top');
|
||||
return Container();
|
||||
|
@ -270,30 +296,35 @@ void main() {
|
|||
|
||||
buildOrder.clear();
|
||||
final OverlayState overlay = overlayKey.currentState! as OverlayState;
|
||||
late final OverlayEntry newEntry;
|
||||
addTearDown(() => newEntry..remove()..dispose());
|
||||
overlay.insert(
|
||||
OverlayEntry(
|
||||
newEntry = OverlayEntry(
|
||||
builder: (BuildContext context) {
|
||||
buildOrder.add('New');
|
||||
return Container();
|
||||
},
|
||||
),
|
||||
above: base,
|
||||
above: baseEntry,
|
||||
);
|
||||
await tester.pump();
|
||||
|
||||
expect(buildOrder, <String>['Base', 'New', 'Top']);
|
||||
});
|
||||
|
||||
testWidgets('insertAll top', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('insertAll top', (WidgetTester tester) async {
|
||||
final GlobalKey overlayKey = GlobalKey();
|
||||
final List<String> buildOrder = <String>[];
|
||||
late final OverlayEntry baseEntry;
|
||||
addTearDown(() => baseEntry..remove()..dispose());
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Overlay(
|
||||
key: overlayKey,
|
||||
initialEntries: <OverlayEntry>[
|
||||
OverlayEntry(
|
||||
baseEntry = OverlayEntry(
|
||||
builder: (BuildContext context) {
|
||||
buildOrder.add('Base');
|
||||
return Container();
|
||||
|
@ -320,6 +351,11 @@ void main() {
|
|||
},
|
||||
),
|
||||
];
|
||||
addTearDown(() {
|
||||
for (final OverlayEntry entry in entries) {
|
||||
entry..remove()..dispose();
|
||||
}
|
||||
});
|
||||
|
||||
buildOrder.clear();
|
||||
final OverlayState overlay = overlayKey.currentState! as OverlayState;
|
||||
|
@ -329,17 +365,19 @@ void main() {
|
|||
expect(buildOrder, <String>['Base', 'New1', 'New2']);
|
||||
});
|
||||
|
||||
testWidgets('insertAll below', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('insertAll below', (WidgetTester tester) async {
|
||||
final GlobalKey overlayKey = GlobalKey();
|
||||
OverlayEntry base;
|
||||
late final OverlayEntry baseEntry;
|
||||
addTearDown(() => baseEntry..remove()..dispose());
|
||||
final List<String> buildOrder = <String>[];
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Overlay(
|
||||
key: overlayKey,
|
||||
initialEntries: <OverlayEntry>[
|
||||
base = OverlayEntry(
|
||||
baseEntry = OverlayEntry(
|
||||
builder: (BuildContext context) {
|
||||
buildOrder.add('Base');
|
||||
return Container();
|
||||
|
@ -366,32 +404,41 @@ void main() {
|
|||
},
|
||||
),
|
||||
];
|
||||
addTearDown(() {
|
||||
for (final OverlayEntry entry in entries) {
|
||||
entry..remove()..dispose();
|
||||
}
|
||||
});
|
||||
|
||||
buildOrder.clear();
|
||||
final OverlayState overlay = overlayKey.currentState! as OverlayState;
|
||||
overlay.insertAll(entries, below: base);
|
||||
overlay.insertAll(entries, below: baseEntry);
|
||||
await tester.pump();
|
||||
|
||||
expect(buildOrder, <String>['New1', 'New2','Base']);
|
||||
});
|
||||
|
||||
testWidgets('insertAll above', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('insertAll above', (WidgetTester tester) async {
|
||||
final GlobalKey overlayKey = GlobalKey();
|
||||
final List<String> buildOrder = <String>[];
|
||||
OverlayEntry base;
|
||||
late final OverlayEntry baseEntry;
|
||||
addTearDown(() => baseEntry..remove()..dispose());
|
||||
late final OverlayEntry topEntry;
|
||||
addTearDown(() => topEntry..remove()..dispose());
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Overlay(
|
||||
key: overlayKey,
|
||||
initialEntries: <OverlayEntry>[
|
||||
base = OverlayEntry(
|
||||
baseEntry = OverlayEntry(
|
||||
builder: (BuildContext context) {
|
||||
buildOrder.add('Base');
|
||||
return Container();
|
||||
},
|
||||
),
|
||||
OverlayEntry(
|
||||
topEntry = OverlayEntry(
|
||||
builder: (BuildContext context) {
|
||||
buildOrder.add('Top');
|
||||
return Container();
|
||||
|
@ -418,16 +465,21 @@ void main() {
|
|||
},
|
||||
),
|
||||
];
|
||||
addTearDown(() {
|
||||
for (final OverlayEntry entry in entries) {
|
||||
entry..remove()..dispose();
|
||||
}
|
||||
});
|
||||
|
||||
buildOrder.clear();
|
||||
final OverlayState overlay = overlayKey.currentState! as OverlayState;
|
||||
overlay.insertAll(entries, above: base);
|
||||
overlay.insertAll(entries, above: baseEntry);
|
||||
await tester.pump();
|
||||
|
||||
expect(buildOrder, <String>['Base', 'New1', 'New2', 'Top']);
|
||||
});
|
||||
|
||||
testWidgets('rearrange', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('rearrange', (WidgetTester tester) async {
|
||||
final GlobalKey overlayKey = GlobalKey();
|
||||
final List<int> buildOrder = <int>[];
|
||||
final List<OverlayEntry> initialEntries = <OverlayEntry>[
|
||||
|
@ -456,6 +508,11 @@ void main() {
|
|||
},
|
||||
),
|
||||
];
|
||||
addTearDown(() {
|
||||
for (final OverlayEntry entry in initialEntries) {
|
||||
entry..remove()..dispose();
|
||||
}
|
||||
});
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
|
@ -469,9 +526,11 @@ void main() {
|
|||
|
||||
expect(buildOrder, <int>[0, 1, 2, 3]);
|
||||
|
||||
late final OverlayEntry newEntry;
|
||||
addTearDown(() => newEntry..remove()..dispose());
|
||||
final List<OverlayEntry> rearranged = <OverlayEntry>[
|
||||
initialEntries[3],
|
||||
OverlayEntry(
|
||||
newEntry = OverlayEntry(
|
||||
builder: (BuildContext context) {
|
||||
buildOrder.add(4);
|
||||
return Container();
|
||||
|
@ -490,9 +549,10 @@ void main() {
|
|||
expect(buildOrder, <int>[3, 4, 2, 0, 1]);
|
||||
});
|
||||
|
||||
testWidgets('rearrange above', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('rearrange above', (WidgetTester tester) async {
|
||||
final GlobalKey overlayKey = GlobalKey();
|
||||
final List<int> buildOrder = <int>[];
|
||||
|
||||
final List<OverlayEntry> initialEntries = <OverlayEntry>[
|
||||
OverlayEntry(
|
||||
builder: (BuildContext context) {
|
||||
|
@ -519,6 +579,11 @@ void main() {
|
|||
},
|
||||
),
|
||||
];
|
||||
addTearDown(() {
|
||||
for (final OverlayEntry entry in initialEntries) {
|
||||
entry..remove()..dispose();
|
||||
}
|
||||
});
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
|
@ -532,9 +597,11 @@ void main() {
|
|||
|
||||
expect(buildOrder, <int>[0, 1, 2, 3]);
|
||||
|
||||
late final OverlayEntry newEntry;
|
||||
addTearDown(() => newEntry..remove()..dispose());
|
||||
final List<OverlayEntry> rearranged = <OverlayEntry>[
|
||||
initialEntries[3],
|
||||
OverlayEntry(
|
||||
newEntry = OverlayEntry(
|
||||
builder: (BuildContext context) {
|
||||
buildOrder.add(4);
|
||||
return Container();
|
||||
|
@ -553,7 +620,7 @@ void main() {
|
|||
expect(buildOrder, <int>[3, 4, 2, 1, 0]);
|
||||
});
|
||||
|
||||
testWidgets('rearrange below', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('rearrange below', (WidgetTester tester) async {
|
||||
final GlobalKey overlayKey = GlobalKey();
|
||||
final List<int> buildOrder = <int>[];
|
||||
final List<OverlayEntry> initialEntries = <OverlayEntry>[
|
||||
|
@ -582,6 +649,11 @@ void main() {
|
|||
},
|
||||
),
|
||||
];
|
||||
addTearDown(() {
|
||||
for (final OverlayEntry entry in initialEntries) {
|
||||
entry..remove()..dispose();
|
||||
}
|
||||
});
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
|
@ -595,9 +667,11 @@ void main() {
|
|||
|
||||
expect(buildOrder, <int>[0, 1, 2, 3]);
|
||||
|
||||
late final OverlayEntry newEntry;
|
||||
addTearDown(() => newEntry..remove()..dispose());
|
||||
final List<OverlayEntry> rearranged = <OverlayEntry>[
|
||||
initialEntries[3],
|
||||
OverlayEntry(
|
||||
newEntry = OverlayEntry(
|
||||
builder: (BuildContext context) {
|
||||
buildOrder.add(4);
|
||||
return Container();
|
||||
|
@ -694,7 +768,7 @@ void main() {
|
|||
await tester.pump();
|
||||
});
|
||||
|
||||
testWidgets('OverlayState.of() throws when called if an Overlay does not exist', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('OverlayState.of() throws when called if an Overlay does not exist', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
|
@ -740,9 +814,11 @@ void main() {
|
|||
);
|
||||
});
|
||||
|
||||
testWidgets("OverlayState.maybeOf() works when an Overlay does and doesn't exist", (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking("OverlayState.maybeOf() works when an Overlay does and doesn't exist", (WidgetTester tester) async {
|
||||
final GlobalKey overlayKey = GlobalKey();
|
||||
OverlayState? foundState;
|
||||
late final OverlayEntry baseEntry;
|
||||
addTearDown(() => baseEntry..remove()..dispose());
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
|
@ -750,7 +826,7 @@ void main() {
|
|||
child: Overlay(
|
||||
key: overlayKey,
|
||||
initialEntries: <OverlayEntry>[
|
||||
OverlayEntry(
|
||||
baseEntry = OverlayEntry(
|
||||
builder: (BuildContext context) {
|
||||
foundState = Overlay.maybeOf(context);
|
||||
return Container();
|
||||
|
@ -781,7 +857,7 @@ void main() {
|
|||
expect(foundState, isNull);
|
||||
});
|
||||
|
||||
testWidgets('OverlayEntry.opaque can be changed when OverlayEntry is not part of an Overlay (yet)', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('OverlayEntry.opaque can be changed when OverlayEntry is not part of an Overlay (yet)', (WidgetTester tester) async {
|
||||
final GlobalKey<OverlayState> overlayKey = GlobalKey<OverlayState>();
|
||||
final Key root = UniqueKey();
|
||||
final Key top = UniqueKey();
|
||||
|
@ -790,6 +866,7 @@ void main() {
|
|||
return Container(key: root);
|
||||
},
|
||||
);
|
||||
addTearDown(() => rootEntry..remove()..dispose());
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
|
@ -810,6 +887,7 @@ void main() {
|
|||
return Container(key: top);
|
||||
},
|
||||
);
|
||||
addTearDown(() => newEntry..remove()..dispose());
|
||||
expect(newEntry.opaque, isFalse);
|
||||
newEntry.opaque = true; // Does neither trigger an assert nor throw.
|
||||
expect(newEntry.opaque, isTrue);
|
||||
|
@ -822,7 +900,7 @@ void main() {
|
|||
expect(find.byKey(top), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('OverlayEntries do not rebuild when opaqueness changes', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('OverlayEntries do not rebuild when opaqueness changes', (WidgetTester tester) async {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/45797.
|
||||
|
||||
final GlobalKey<OverlayState> overlayKey = GlobalKey<OverlayState>();
|
||||
|
@ -839,18 +917,21 @@ void main() {
|
|||
return bottomWidget;
|
||||
},
|
||||
);
|
||||
addTearDown(() => bottomEntry..remove()..dispose());
|
||||
final OverlayEntry middleEntry = OverlayEntry(
|
||||
maintainState: true,
|
||||
builder: (BuildContext context) {
|
||||
return middleWidget;
|
||||
},
|
||||
);
|
||||
addTearDown(() => middleEntry..remove()..dispose());
|
||||
final OverlayEntry topEntry = OverlayEntry(
|
||||
maintainState: true,
|
||||
builder: (BuildContext context) {
|
||||
return topWidget;
|
||||
},
|
||||
);
|
||||
addTearDown(() => topEntry..remove()..dispose());
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
|
@ -881,7 +962,7 @@ void main() {
|
|||
expect(tester.state<StatefulTestState>(find.byKey(top)).rebuildCount, 1);
|
||||
});
|
||||
|
||||
testWidgets('OverlayEntries do not rebuild when opaque entry is added', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('OverlayEntries do not rebuild when opaque entry is added', (WidgetTester tester) async {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/45797.
|
||||
|
||||
final GlobalKey<OverlayState> overlayKey = GlobalKey<OverlayState>();
|
||||
|
@ -898,6 +979,7 @@ void main() {
|
|||
return bottomWidget;
|
||||
},
|
||||
);
|
||||
addTearDown(() => bottomEntry..remove()..dispose());
|
||||
final OverlayEntry middleEntry = OverlayEntry(
|
||||
opaque: true,
|
||||
maintainState: true,
|
||||
|
@ -905,12 +987,14 @@ void main() {
|
|||
return middleWidget;
|
||||
},
|
||||
);
|
||||
addTearDown(() => middleEntry..remove()..dispose());
|
||||
final OverlayEntry topEntry = OverlayEntry(
|
||||
maintainState: true,
|
||||
builder: (BuildContext context) {
|
||||
return topWidget;
|
||||
},
|
||||
);
|
||||
addTearDown(() => topEntry..remove()..dispose());
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
|
@ -941,16 +1025,19 @@ void main() {
|
|||
expect(tester.state<StatefulTestState>(find.byKey(top)).rebuildCount, 1);
|
||||
});
|
||||
|
||||
testWidgets('entries below opaque entries are ignored for hit testing', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('entries below opaque entries are ignored for hit testing', (WidgetTester tester) async {
|
||||
final GlobalKey<OverlayState> overlayKey = GlobalKey<OverlayState>();
|
||||
int bottomTapCount = 0;
|
||||
late final OverlayEntry baseEntry;
|
||||
addTearDown(() => baseEntry..remove()..dispose());
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Overlay(
|
||||
key: overlayKey,
|
||||
initialEntries: <OverlayEntry>[
|
||||
OverlayEntry(
|
||||
baseEntry = OverlayEntry(
|
||||
maintainState: true,
|
||||
builder: (BuildContext context) {
|
||||
return GestureDetector(
|
||||
|
@ -969,13 +1056,17 @@ void main() {
|
|||
await tester.tap(find.byKey(overlayKey), warnIfMissed: false); // gesture detector is translucent; no hit is registered between it and the render view
|
||||
expect(bottomTapCount, 1);
|
||||
|
||||
overlayKey.currentState!.insert(OverlayEntry(
|
||||
maintainState: true,
|
||||
opaque: true,
|
||||
builder: (BuildContext context) {
|
||||
return Container();
|
||||
},
|
||||
));
|
||||
late final OverlayEntry newEntry1;
|
||||
addTearDown(() => newEntry1..remove()..dispose());
|
||||
overlayKey.currentState!.insert(
|
||||
newEntry1 = OverlayEntry(
|
||||
maintainState: true,
|
||||
opaque: true,
|
||||
builder: (BuildContext context) {
|
||||
return Container();
|
||||
},
|
||||
),
|
||||
);
|
||||
await tester.pump();
|
||||
|
||||
// Bottom is offstage and does not receive tap events.
|
||||
|
@ -985,17 +1076,21 @@ void main() {
|
|||
expect(bottomTapCount, 1);
|
||||
|
||||
int topTapCount = 0;
|
||||
overlayKey.currentState!.insert(OverlayEntry(
|
||||
maintainState: true,
|
||||
opaque: true,
|
||||
builder: (BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
topTapCount++;
|
||||
},
|
||||
);
|
||||
},
|
||||
));
|
||||
late final OverlayEntry newEntry2;
|
||||
addTearDown(() => newEntry2..remove()..dispose());
|
||||
overlayKey.currentState!.insert(
|
||||
newEntry2 = OverlayEntry(
|
||||
maintainState: true,
|
||||
opaque: true,
|
||||
builder: (BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
topTapCount++;
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
await tester.pump();
|
||||
|
||||
expect(topTapCount, 0);
|
||||
|
@ -1004,22 +1099,27 @@ void main() {
|
|||
expect(bottomTapCount, 1);
|
||||
});
|
||||
|
||||
testWidgets('Semantics of entries below opaque entries are ignored', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Semantics of entries below opaque entries are ignored', (WidgetTester tester) async {
|
||||
final SemanticsTester semantics = SemanticsTester(tester);
|
||||
final GlobalKey<OverlayState> overlayKey = GlobalKey<OverlayState>();
|
||||
late final OverlayEntry bottomEntry;
|
||||
addTearDown(() => bottomEntry..remove()..dispose());
|
||||
late final OverlayEntry topEntry;
|
||||
addTearDown(() => topEntry..remove()..dispose());
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Overlay(
|
||||
key: overlayKey,
|
||||
initialEntries: <OverlayEntry>[
|
||||
OverlayEntry(
|
||||
bottomEntry = OverlayEntry(
|
||||
maintainState: true,
|
||||
builder: (BuildContext context) {
|
||||
return const Text('bottom');
|
||||
},
|
||||
),
|
||||
OverlayEntry(
|
||||
topEntry = OverlayEntry(
|
||||
maintainState: true,
|
||||
opaque: true,
|
||||
builder: (BuildContext context) {
|
||||
|
@ -1039,13 +1139,16 @@ void main() {
|
|||
semantics.dispose();
|
||||
});
|
||||
|
||||
testWidgets('Can use Positioned within OverlayEntry', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Can use Positioned within OverlayEntry', (WidgetTester tester) async {
|
||||
late final OverlayEntry baseEntry;
|
||||
addTearDown(() => baseEntry..remove()..dispose());
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Overlay(
|
||||
initialEntries: <OverlayEntry>[
|
||||
OverlayEntry(
|
||||
baseEntry = OverlayEntry(
|
||||
builder: (BuildContext context) {
|
||||
return const Positioned(
|
||||
left: 145,
|
||||
|
@ -1117,13 +1220,16 @@ void main() {
|
|||
}
|
||||
});
|
||||
|
||||
testWidgets('Overlay always applies clip', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Overlay always applies clip', (WidgetTester tester) async {
|
||||
late final OverlayEntry baseEntry;
|
||||
addTearDown(() => baseEntry..remove()..dispose());
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Overlay(
|
||||
initialEntries: <OverlayEntry>[
|
||||
OverlayEntry(
|
||||
baseEntry = OverlayEntry(
|
||||
builder: (BuildContext context) => Positioned(left: 10, right: 10, child: Container()),
|
||||
),
|
||||
],
|
||||
|
@ -1139,7 +1245,7 @@ void main() {
|
|||
);
|
||||
});
|
||||
|
||||
testWidgets('OverlayEntry throws if inserted to an invalid Overlay', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('OverlayEntry throws if inserted to an invalid Overlay', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
const Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
|
@ -1148,6 +1254,7 @@ void main() {
|
|||
);
|
||||
final OverlayState overlay = tester.state(find.byType(Overlay));
|
||||
final OverlayEntry entry = OverlayEntry(builder: (BuildContext context) => const SizedBox());
|
||||
addTearDown(() => entry..remove()..dispose());
|
||||
expect(
|
||||
() => overlay.insert(entry),
|
||||
returnsNormally,
|
||||
|
@ -1212,13 +1319,14 @@ void main() {
|
|||
child: Overlay(key: overlayKey),
|
||||
);
|
||||
|
||||
testWidgets('mounted state can be listened', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('mounted state can be listened', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(emptyOverlay);
|
||||
final OverlayState overlay = overlayKey.currentState! as OverlayState;
|
||||
final List<bool> mountedLog = <bool>[];
|
||||
final OverlayEntry entry = OverlayEntry(
|
||||
builder: (BuildContext context) => Container(),
|
||||
);
|
||||
addTearDown(entry.dispose);
|
||||
|
||||
entry.addListener(() {
|
||||
mountedLog.add(entry.mounted);
|
||||
|
@ -1245,12 +1353,13 @@ void main() {
|
|||
expect(mountedLog, <bool>[true, false, true, false]);
|
||||
});
|
||||
|
||||
testWidgets('throw if disposed before removal', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('throw if disposed before removal', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(emptyOverlay);
|
||||
final OverlayState overlay = overlayKey.currentState! as OverlayState;
|
||||
final OverlayEntry entry = OverlayEntry(
|
||||
builder: (BuildContext context) => Container(),
|
||||
);
|
||||
addTearDown(() => entry..remove()..dispose());
|
||||
|
||||
overlay.insert(entry);
|
||||
Object? error;
|
||||
|
@ -1279,7 +1388,7 @@ void main() {
|
|||
expect(error, isAssertionError);
|
||||
});
|
||||
|
||||
testWidgets('delayed dispose', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('delayed dispose', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(emptyOverlay);
|
||||
final OverlayState overlay = overlayKey.currentState! as OverlayState;
|
||||
final List<bool> mountedLog = <bool>[];
|
||||
|
@ -1315,15 +1424,17 @@ void main() {
|
|||
});
|
||||
|
||||
group('LookupBoundary', () {
|
||||
testWidgets('hides Overlay from Overlay.maybeOf', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('hides Overlay from Overlay.maybeOf', (WidgetTester tester) async {
|
||||
OverlayState? overlay;
|
||||
late final OverlayEntry baseEntry;
|
||||
addTearDown(() => baseEntry..remove()..dispose());
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Overlay(
|
||||
initialEntries: <OverlayEntry>[
|
||||
OverlayEntry(
|
||||
baseEntry = OverlayEntry(
|
||||
builder: (BuildContext context) {
|
||||
return LookupBoundary(
|
||||
child: Builder(
|
||||
|
@ -1343,13 +1454,16 @@ void main() {
|
|||
expect(overlay, isNull);
|
||||
});
|
||||
|
||||
testWidgets('hides Overlay from Overlay.of', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('hides Overlay from Overlay.of', (WidgetTester tester) async {
|
||||
late final OverlayEntry baseEntry;
|
||||
addTearDown(() => baseEntry..remove()..dispose());
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Overlay(
|
||||
initialEntries: <OverlayEntry>[
|
||||
OverlayEntry(
|
||||
baseEntry = OverlayEntry(
|
||||
builder: (BuildContext context) {
|
||||
return LookupBoundary(
|
||||
child: Builder(
|
||||
|
@ -1386,13 +1500,16 @@ void main() {
|
|||
);
|
||||
});
|
||||
|
||||
testWidgets('hides Overlay from debugCheckHasOverlay', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('hides Overlay from debugCheckHasOverlay', (WidgetTester tester) async {
|
||||
late final OverlayEntry baseEntry;
|
||||
addTearDown(() => baseEntry..remove()..dispose());
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Overlay(
|
||||
initialEntries: <OverlayEntry>[
|
||||
OverlayEntry(
|
||||
baseEntry = OverlayEntry(
|
||||
builder: (BuildContext context) {
|
||||
return LookupBoundary(
|
||||
child: Builder(
|
||||
|
|
|
@ -5,9 +5,10 @@
|
|||
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';
|
||||
|
||||
void main() {
|
||||
testWidgets('Router state restoration without RouteInformationProvider', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Router state restoration without RouteInformationProvider', (WidgetTester tester) async {
|
||||
final UniqueKey router = UniqueKey();
|
||||
_TestRouterDelegate delegate() => tester.widget<Router<Object?>>(find.byKey(router)).routerDelegate as _TestRouterDelegate;
|
||||
|
||||
|
@ -39,7 +40,12 @@ void main() {
|
|||
expect(find.text('Current config: /foo'), findsOneWidget);
|
||||
expect(delegate().newRoutePaths, isEmpty);
|
||||
expect(delegate().restoredRoutePaths, <String>['/foo', '/foo']);
|
||||
});
|
||||
},
|
||||
leakTrackingTestConfig: const LeakTrackingTestConfig(
|
||||
// TODO(ksokolovskyi): remove after fixing
|
||||
// https://github.com/flutter/flutter/issues/134205
|
||||
notDisposedAllowList: <String, int?> {'_RestorableRouteInformation': 2},
|
||||
));
|
||||
|
||||
testWidgets('Router state restoration with RouteInformationProvider', (WidgetTester tester) async {
|
||||
final UniqueKey router = UniqueKey();
|
||||
|
@ -152,22 +158,37 @@ class _TestRouteInformationProvider extends RouteInformationProvider with Change
|
|||
}
|
||||
}
|
||||
|
||||
class _TestWidget extends StatelessWidget {
|
||||
class _TestWidget extends StatefulWidget {
|
||||
const _TestWidget({this.withInformationProvider = false, this.routerKey});
|
||||
|
||||
final bool withInformationProvider;
|
||||
final Key? routerKey;
|
||||
|
||||
@override
|
||||
State<_TestWidget> createState() => _TestWidgetState();
|
||||
}
|
||||
|
||||
class _TestWidgetState extends State<_TestWidget> {
|
||||
final _TestRouterDelegate _delegate = _TestRouterDelegate();
|
||||
final _TestRouteInformationProvider _routeInformationProvider = _TestRouteInformationProvider();
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_delegate.dispose();
|
||||
_routeInformationProvider.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return RootRestorationScope(
|
||||
restorationId: 'root',
|
||||
child: Router<String>(
|
||||
key: routerKey,
|
||||
key: widget.routerKey,
|
||||
restorationScopeId: 'router',
|
||||
routerDelegate: _TestRouterDelegate(),
|
||||
routerDelegate: _delegate,
|
||||
routeInformationParser: _TestRouteInformationParser(),
|
||||
routeInformationProvider: withInformationProvider ? _TestRouteInformationProvider() : null,
|
||||
routeInformationProvider: widget.withInformationProvider ? _routeInformationProvider : null,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -861,12 +861,13 @@ 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,
|
||||
vsync: vsync,
|
||||
);
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
|
|
|
@ -13,10 +13,11 @@ import 'dart:ui' as ui;
|
|||
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 'package:vector_math/vector_math_64.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Transform origin', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Transform origin', (WidgetTester tester) async {
|
||||
bool didReceiveTap = false;
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
|
@ -64,7 +65,7 @@ void main() {
|
|||
expect(didReceiveTap, isTrue);
|
||||
});
|
||||
|
||||
testWidgets('Transform alignment', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Transform alignment', (WidgetTester tester) async {
|
||||
bool didReceiveTap = false;
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
|
@ -112,7 +113,7 @@ void main() {
|
|||
expect(didReceiveTap, isTrue);
|
||||
});
|
||||
|
||||
testWidgets('Transform AlignmentDirectional alignment', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Transform AlignmentDirectional alignment', (WidgetTester tester) async {
|
||||
bool didReceiveTap = false;
|
||||
|
||||
Widget buildFrame(TextDirection textDirection, AlignmentGeometry alignment) {
|
||||
|
@ -183,7 +184,7 @@ void main() {
|
|||
expect(didReceiveTap, isTrue);
|
||||
});
|
||||
|
||||
testWidgets('Transform offset + alignment', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Transform offset + alignment', (WidgetTester tester) async {
|
||||
bool didReceiveTap = false;
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
|
@ -232,7 +233,7 @@ void main() {
|
|||
expect(didReceiveTap, isTrue);
|
||||
});
|
||||
|
||||
testWidgets('Composited transform offset', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Composited transform offset', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
Center(
|
||||
child: SizedBox(
|
||||
|
@ -261,7 +262,7 @@ void main() {
|
|||
expect(transform.getTranslation(), equals(Vector3(100.0, 75.0, 0.0)));
|
||||
});
|
||||
|
||||
testWidgets('Transform.rotate', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Transform.rotate', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
Transform.rotate(
|
||||
angle: math.pi / 2.0,
|
||||
|
@ -283,7 +284,7 @@ void main() {
|
|||
]);
|
||||
});
|
||||
|
||||
testWidgets('applyPaintTransform of Transform in Padding', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('applyPaintTransform of Transform in Padding', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
|
@ -301,7 +302,7 @@ void main() {
|
|||
expect(tester.getTopLeft(find.byType(Placeholder)), const Offset(30.0, 20.0));
|
||||
});
|
||||
|
||||
testWidgets('Transform.translate', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Transform.translate', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
Transform.translate(
|
||||
offset: const Offset(100.0, 50.0),
|
||||
|
@ -316,7 +317,7 @@ void main() {
|
|||
expect(tester.getTopLeft(find.byType(Container)), const Offset(100.0, 50.0));
|
||||
});
|
||||
|
||||
testWidgets('Transform.scale', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Transform.scale', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
Transform.scale(
|
||||
scale: 2.0,
|
||||
|
@ -339,7 +340,7 @@ void main() {
|
|||
]);
|
||||
});
|
||||
|
||||
testWidgets('Transform with nan value short-circuits rendering', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Transform with nan value short-circuits rendering', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
Transform(
|
||||
transform: Matrix4.identity()
|
||||
|
@ -351,7 +352,7 @@ void main() {
|
|||
expect(tester.layers, hasLength(1));
|
||||
});
|
||||
|
||||
testWidgets('Transform with inf value short-circuits rendering', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Transform with inf value short-circuits rendering', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
Transform(
|
||||
transform: Matrix4.identity()
|
||||
|
@ -363,7 +364,7 @@ void main() {
|
|||
expect(tester.layers, hasLength(1));
|
||||
});
|
||||
|
||||
testWidgets('Transform with -inf value short-circuits rendering', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Transform with -inf value short-circuits rendering', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
Transform(
|
||||
transform: Matrix4.identity()
|
||||
|
@ -375,7 +376,7 @@ void main() {
|
|||
expect(tester.layers, hasLength(1));
|
||||
});
|
||||
|
||||
testWidgets('Transform.rotate does not remove layers due to singular short-circuit', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Transform.rotate does not remove layers due to singular short-circuit', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
Transform.rotate(
|
||||
angle: math.pi / 2,
|
||||
|
@ -386,7 +387,7 @@ void main() {
|
|||
expect(tester.layers, hasLength(3));
|
||||
});
|
||||
|
||||
testWidgets('Transform.rotate creates nice rotation matrices for 0, 90, 180, 270 degrees', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Transform.rotate creates nice rotation matrices for 0, 90, 180, 270 degrees', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
Transform.rotate(
|
||||
angle: math.pi / 2,
|
||||
|
@ -447,7 +448,7 @@ void main() {
|
|||
expect(tester.layers, hasLength(2));
|
||||
});
|
||||
|
||||
testWidgets('Transform.scale with 0.0 does not paint child layers', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Transform.scale with 0.0 does not paint child layers', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
Transform.scale(
|
||||
scale: 0.0,
|
||||
|
@ -486,7 +487,7 @@ void main() {
|
|||
});
|
||||
|
||||
|
||||
testWidgets('Translated child into translated box - hit test', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Translated child into translated box - hit test', (WidgetTester tester) async {
|
||||
final GlobalKey key1 = GlobalKey();
|
||||
bool pointerDown = false;
|
||||
await tester.pumpWidget(
|
||||
|
@ -524,7 +525,7 @@ void main() {
|
|||
);
|
||||
}
|
||||
|
||||
testWidgets(
|
||||
testWidgetsWithLeakTracking(
|
||||
'3D transform renders the same with or without needsCompositing',
|
||||
(WidgetTester tester) async {
|
||||
for (double angle = 0; angle <= math.pi/4; angle += 0.01) {
|
||||
|
@ -532,6 +533,7 @@ void main() {
|
|||
final RenderBox renderBox = tester.binding.renderView.child!;
|
||||
final OffsetLayer layer = renderBox.debugLayer! as OffsetLayer;
|
||||
final ui.Image imageWithCompositing = await layer.toImage(renderBox.paintBounds);
|
||||
addTearDown(imageWithCompositing.dispose);
|
||||
|
||||
await tester.pumpWidget(RepaintBoundary(child: generateTransform(false, angle)));
|
||||
await expectLater(find.byType(RepaintBoundary).first, matchesReferenceImage(imageWithCompositing));
|
||||
|
@ -545,7 +547,7 @@ void main() {
|
|||
return numbers.map<double>((String str) => double.parse(str.trim())).toList();
|
||||
}
|
||||
|
||||
testWidgets('Transform.translate with FilterQuality produces filter layer', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Transform.translate with FilterQuality produces filter layer', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
Transform.translate(
|
||||
offset: const Offset(25.0, 25.0),
|
||||
|
@ -563,7 +565,7 @@ void main() {
|
|||
]);
|
||||
});
|
||||
|
||||
testWidgets('Transform.scale with FilterQuality produces filter layer', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Transform.scale with FilterQuality produces filter layer', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
Transform.scale(
|
||||
scale: 3.14159,
|
||||
|
@ -581,7 +583,7 @@ void main() {
|
|||
]);
|
||||
});
|
||||
|
||||
testWidgets('Transform.rotate with FilterQuality produces filter layer', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Transform.rotate with FilterQuality produces filter layer', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
Transform.rotate(
|
||||
angle: math.pi / 4,
|
||||
|
@ -599,7 +601,7 @@ void main() {
|
|||
]);
|
||||
});
|
||||
|
||||
testWidgets('Offset Transform.rotate with FilterQuality produces filter layer', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Offset Transform.rotate with FilterQuality produces filter layer', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
SizedBox(width: 400, height: 400,
|
||||
child: Center(
|
||||
|
@ -621,7 +623,7 @@ void main() {
|
|||
]);
|
||||
});
|
||||
|
||||
testWidgets('Transform layers update to match child and filterQuality', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Transform layers update to match child and filterQuality', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
Transform.rotate(
|
||||
angle: math.pi / 4,
|
||||
|
@ -657,7 +659,7 @@ void main() {
|
|||
expect(tester.layers.whereType<ImageFilterLayer>(), hasLength(1));
|
||||
});
|
||||
|
||||
testWidgets('Transform layers with filterQuality golden', (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking('Transform layers with filterQuality golden', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
|
@ -701,7 +703,7 @@ void main() {
|
|||
);
|
||||
});
|
||||
|
||||
testWidgets("Transform.scale() does not accept all three 'scale', 'scaleX' and 'scaleY' parameters to be non-null", (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking("Transform.scale() does not accept all three 'scale', 'scaleX' and 'scaleY' parameters to be non-null", (WidgetTester tester) async {
|
||||
await expectLater(() {
|
||||
tester.pumpWidget(Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
|
@ -719,7 +721,7 @@ void main() {
|
|||
}, throwsAssertionError);
|
||||
});
|
||||
|
||||
testWidgets("Transform.scale() needs at least one of 'scale', 'scaleX' and 'scaleY' to be non-null, otherwise throws AssertionError", (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking("Transform.scale() needs at least one of 'scale', 'scaleX' and 'scaleY' to be non-null, otherwise throws AssertionError", (WidgetTester tester) async {
|
||||
await expectLater(() {
|
||||
tester.pumpWidget(Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
|
@ -734,7 +736,7 @@ void main() {
|
|||
}, throwsAssertionError);
|
||||
});
|
||||
|
||||
testWidgets("Transform.scale() scales widget uniformly with 'scale' parameter", (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking("Transform.scale() scales widget uniformly with 'scale' parameter", (WidgetTester tester) async {
|
||||
const double scale = 1.5;
|
||||
const double height = 100;
|
||||
const double width = 150;
|
||||
|
@ -760,7 +762,7 @@ void main() {
|
|||
expect(tester.getBottomRight(find.byType(Container)), target.bottomRight(tester.getTopLeft(find.byType(Container))));
|
||||
});
|
||||
|
||||
testWidgets("Transform.scale() scales widget according to 'scaleX' and 'scaleY'", (WidgetTester tester) async {
|
||||
testWidgetsWithLeakTracking("Transform.scale() scales widget according to 'scaleX' and 'scaleY'", (WidgetTester tester) async {
|
||||
const double scaleX = 1.5;
|
||||
const double scaleY = 1.2;
|
||||
const double height = 100;
|
||||
|
@ -788,7 +790,7 @@ void main() {
|
|||
expect(tester.getBottomRight(find.byType(Container)), target.bottomRight(tester.getTopLeft(find.byType(Container))));
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
testWidgetsWithLeakTracking(
|
||||
'Transform.flip does flip child correctly',
|
||||
(WidgetTester tester) async {
|
||||
const Offset topRight = Offset(60, 20);
|
||||
|
|
Loading…
Reference in a new issue