Unverified Commit 96a4ae9d authored by Kostia Sokolovskyi's avatar Kostia Sokolovskyi Committed by GitHub

Cover more test/widgets tests with leak tracking #10 (#135143)

parent 9b767e6c
...@@ -5,9 +5,10 @@ ...@@ -5,9 +5,10 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() { void main() {
testWidgets('SliverFillViewport control test', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverFillViewport control test', (WidgetTester tester) async {
final List<Widget> children = List<Widget>.generate(20, (int i) { final List<Widget> children = List<Widget>.generate(20, (int i) {
return ColoredBox(color: Colors.green, child: Text('$i', textDirection: TextDirection.ltr)); return ColoredBox(color: Colors.green, child: Text('$i', textDirection: TextDirection.ltr));
}); });
...@@ -158,7 +159,7 @@ void main() { ...@@ -158,7 +159,7 @@ void main() {
); );
}); });
testWidgets('SliverFillViewport padding test', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverFillViewport padding test', (WidgetTester tester) async {
final SliverChildListDelegate delegate = SliverChildListDelegate( final SliverChildListDelegate delegate = SliverChildListDelegate(
<Widget>[ <Widget>[
const Text('0'), const Text('0'),
......
...@@ -4,15 +4,17 @@ ...@@ -4,15 +4,17 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() { void main() {
testWidgets('SliverList reverse children (with keys)', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverList reverse children (with keys)', (WidgetTester tester) async {
final List<int> items = List<int>.generate(20, (int i) => i); final List<int> items = List<int>.generate(20, (int i) => i);
const double itemHeight = 300.0; const double itemHeight = 300.0;
const double viewportHeight = 500.0; const double viewportHeight = 500.0;
const double scrollPosition = 18 * itemHeight; const double scrollPosition = 18 * itemHeight;
final ScrollController controller = ScrollController(initialScrollOffset: scrollPosition); final ScrollController controller = ScrollController(initialScrollOffset: scrollPosition);
addTearDown(controller.dispose);
await tester.pumpWidget(_buildSliverList( await tester.pumpWidget(_buildSliverList(
items: items, items: items,
...@@ -53,13 +55,14 @@ void main() { ...@@ -53,13 +55,14 @@ void main() {
expect(find.text('Tile 0'), findsNothing); expect(find.text('Tile 0'), findsNothing);
}); });
testWidgets('SliverList replace children (with keys)', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverList replace children (with keys)', (WidgetTester tester) async {
final List<int> items = List<int>.generate(20, (int i) => i); final List<int> items = List<int>.generate(20, (int i) => i);
const double itemHeight = 300.0; const double itemHeight = 300.0;
const double viewportHeight = 500.0; const double viewportHeight = 500.0;
const double scrollPosition = 18 * itemHeight; const double scrollPosition = 18 * itemHeight;
final ScrollController controller = ScrollController(initialScrollOffset: scrollPosition); final ScrollController controller = ScrollController(initialScrollOffset: scrollPosition);
addTearDown(controller.dispose);
await tester.pumpWidget(_buildSliverList( await tester.pumpWidget(_buildSliverList(
items: items, items: items,
...@@ -105,13 +108,14 @@ void main() { ...@@ -105,13 +108,14 @@ void main() {
expect(find.text('Tile 119'), findsNothing); expect(find.text('Tile 119'), findsNothing);
}); });
testWidgets('SliverList replace with shorter children list (with keys)', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverList replace with shorter children list (with keys)', (WidgetTester tester) async {
final List<int> items = List<int>.generate(20, (int i) => i); final List<int> items = List<int>.generate(20, (int i) => i);
const double itemHeight = 300.0; const double itemHeight = 300.0;
const double viewportHeight = 500.0; const double viewportHeight = 500.0;
final double scrollPosition = items.length * itemHeight - viewportHeight; final double scrollPosition = items.length * itemHeight - viewportHeight;
final ScrollController controller = ScrollController(initialScrollOffset: scrollPosition); final ScrollController controller = ScrollController(initialScrollOffset: scrollPosition);
addTearDown(controller.dispose);
await tester.pumpWidget(_buildSliverList( await tester.pumpWidget(_buildSliverList(
items: items, items: items,
...@@ -145,28 +149,33 @@ void main() { ...@@ -145,28 +149,33 @@ void main() {
expect(find.text('Tile 19'), findsNothing); expect(find.text('Tile 19'), findsNothing);
}); });
testWidgets('SliverList should layout first child in case of child reordering', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverList should layout first child in case of child reordering', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/35904. // Regression test for https://github.com/flutter/flutter/issues/35904.
List<String> items = <String>['1', '2']; List<String> items = <String>['1', '2'];
final ScrollController controller1 = ScrollController();
await tester.pumpWidget(_buildSliverListRenderWidgetChild(items)); addTearDown(controller1.dispose);
await tester.pumpWidget(_buildSliverListRenderWidgetChild(items, controller1));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(find.text('Tile 1'), findsOneWidget); expect(find.text('Tile 1'), findsOneWidget);
expect(find.text('Tile 2'), findsOneWidget); expect(find.text('Tile 2'), findsOneWidget);
items = items.reversed.toList(); items = items.reversed.toList();
await tester.pumpWidget(_buildSliverListRenderWidgetChild(items)); final ScrollController controller2 = ScrollController();
addTearDown(controller2.dispose);
await tester.pumpWidget(_buildSliverListRenderWidgetChild(items, controller2));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(find.text('Tile 1'), findsOneWidget); expect(find.text('Tile 1'), findsOneWidget);
expect(find.text('Tile 2'), findsOneWidget); expect(find.text('Tile 2'), findsOneWidget);
}); });
testWidgets('SliverList should recalculate inaccurate layout offset case 1', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverList should recalculate inaccurate layout offset case 1', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/42142. // Regression test for https://github.com/flutter/flutter/issues/42142.
final List<int> items = List<int>.generate(20, (int i) => i); final List<int> items = List<int>.generate(20, (int i) => i);
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
_buildSliverList( _buildSliverList(
items: List<int>.from(items), items: List<int>.from(items),
...@@ -223,10 +232,12 @@ void main() { ...@@ -223,10 +232,12 @@ void main() {
}); });
testWidgets('SliverList should recalculate inaccurate layout offset case 2', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverList should recalculate inaccurate layout offset case 2', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/42142. // Regression test for https://github.com/flutter/flutter/issues/42142.
final List<int> items = List<int>.generate(20, (int i) => i); final List<int> items = List<int>.generate(20, (int i) => i);
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
_buildSliverList( _buildSliverList(
items: List<int>.from(items), items: List<int>.from(items),
...@@ -275,10 +286,12 @@ void main() { ...@@ -275,10 +286,12 @@ void main() {
expect(find.text('Tile 3'), findsOneWidget); expect(find.text('Tile 3'), findsOneWidget);
}); });
testWidgets('SliverList should start to perform layout from the initial child when there is no valid offset', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverList should start to perform layout from the initial child when there is no valid offset', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/66198. // Regression test for https://github.com/flutter/flutter/issues/66198.
bool isShow = true; bool isShow = true;
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
Widget buildSliverList(ScrollController controller) { Widget buildSliverList(ScrollController controller) {
return Directionality( return Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -335,7 +348,7 @@ void main() { ...@@ -335,7 +348,7 @@ void main() {
}); });
} }
Widget _buildSliverListRenderWidgetChild(List<String> items) { Widget _buildSliverListRenderWidgetChild(List<String> items, ScrollController controller) {
return MaterialApp( return MaterialApp(
home: Directionality( home: Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -343,7 +356,7 @@ Widget _buildSliverListRenderWidgetChild(List<String> items) { ...@@ -343,7 +356,7 @@ Widget _buildSliverListRenderWidgetChild(List<String> items) {
child: SizedBox( child: SizedBox(
height: 500, height: 500,
child: CustomScrollView( child: CustomScrollView(
controller: ScrollController(), controller: controller,
slivers: <Widget>[ slivers: <Widget>[
SliverList( SliverList(
delegate: SliverChildListDelegate( delegate: SliverChildListDelegate(
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import '../rendering/sliver_utils.dart'; import '../rendering/sliver_utils.dart';
...@@ -13,9 +14,10 @@ const double VIEWPORT_HEIGHT = 600; ...@@ -13,9 +14,10 @@ const double VIEWPORT_HEIGHT = 600;
const double VIEWPORT_WIDTH = 300; const double VIEWPORT_WIDTH = 300;
void main() { void main() {
testWidgets('SliverMainAxisGroup is laid out properly', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverMainAxisGroup is laid out properly', (WidgetTester tester) async {
final List<int> items = List<int>.generate(20, (int i) => i); final List<int> items = List<int>.generate(20, (int i) => i);
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
_buildSliverMainAxisGroup( _buildSliverMainAxisGroup(
...@@ -64,9 +66,10 @@ void main() { ...@@ -64,9 +66,10 @@ void main() {
expect(renderGroup.geometry!.hasVisualOverflow, isTrue); expect(renderGroup.geometry!.hasVisualOverflow, isTrue);
}); });
testWidgets('SliverMainAxisGroup is laid out properly when reversed', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverMainAxisGroup is laid out properly when reversed', (WidgetTester tester) async {
final List<int> items = List<int>.generate(20, (int i) => i); final List<int> items = List<int>.generate(20, (int i) => i);
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
_buildSliverMainAxisGroup( _buildSliverMainAxisGroup(
...@@ -116,9 +119,10 @@ void main() { ...@@ -116,9 +119,10 @@ void main() {
expect(renderGroup.geometry!.hasVisualOverflow, isTrue); expect(renderGroup.geometry!.hasVisualOverflow, isTrue);
}); });
testWidgets('SliverMainAxisGroup is laid out properly when horizontal', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverMainAxisGroup is laid out properly when horizontal', (WidgetTester tester) async {
final List<int> items = List<int>.generate(20, (int i) => i); final List<int> items = List<int>.generate(20, (int i) => i);
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
_buildSliverMainAxisGroup( _buildSliverMainAxisGroup(
...@@ -173,9 +177,10 @@ void main() { ...@@ -173,9 +177,10 @@ void main() {
expect(renderGroup.geometry!.hasVisualOverflow, isTrue); expect(renderGroup.geometry!.hasVisualOverflow, isTrue);
}); });
testWidgets('SliverMainAxisGroup is laid out properly when horizontal, reversed', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverMainAxisGroup is laid out properly when horizontal, reversed', (WidgetTester tester) async {
final List<int> items = List<int>.generate(20, (int i) => i); final List<int> items = List<int>.generate(20, (int i) => i);
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
_buildSliverMainAxisGroup( _buildSliverMainAxisGroup(
...@@ -231,9 +236,10 @@ void main() { ...@@ -231,9 +236,10 @@ void main() {
expect(renderGroup.geometry!.hasVisualOverflow, isTrue); expect(renderGroup.geometry!.hasVisualOverflow, isTrue);
}); });
testWidgets('Hit test works properly on various parts of SliverMainAxisGroup', (WidgetTester tester) async { testWidgetsWithLeakTracking('Hit test works properly on various parts of SliverMainAxisGroup', (WidgetTester tester) async {
final List<int> items = List<int>.generate(20, (int i) => i); final List<int> items = List<int>.generate(20, (int i) => i);
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
String? clickedTile; String? clickedTile;
...@@ -303,7 +309,7 @@ void main() { ...@@ -303,7 +309,7 @@ void main() {
expect(clickedTile, equals('Group 1 Tile 2')); expect(clickedTile, equals('Group 1 Tile 2'));
}); });
testWidgets('applyPaintTransform is implemented properly', (WidgetTester tester) async { testWidgetsWithLeakTracking('applyPaintTransform is implemented properly', (WidgetTester tester) async {
await tester.pumpWidget(_buildSliverMainAxisGroup( await tester.pumpWidget(_buildSliverMainAxisGroup(
slivers: <Widget>[ slivers: <Widget>[
const SliverToBoxAdapter(child: Text('first box')), const SliverToBoxAdapter(child: Text('first box')),
...@@ -319,8 +325,10 @@ void main() { ...@@ -319,8 +325,10 @@ void main() {
expect(second.localToGlobal(Offset.zero), Offset(0, first.size.height)); expect(second.localToGlobal(Offset.zero), Offset(0, first.size.height));
}); });
testWidgets('visitChildrenForSemantics visits children in the correct order', (WidgetTester tester) async { testWidgetsWithLeakTracking('visitChildrenForSemantics visits children in the correct order', (WidgetTester tester) async {
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(_buildSliverMainAxisGroup( await tester.pumpWidget(_buildSliverMainAxisGroup(
controller: controller, controller: controller,
slivers: const <Widget>[ slivers: const <Widget>[
...@@ -344,8 +352,10 @@ void main() { ...@@ -344,8 +352,10 @@ void main() {
expect(visitedChildren[1].geometry!.scrollExtent, equals(500)); expect(visitedChildren[1].geometry!.scrollExtent, equals(500));
}); });
testWidgets('SliverPinnedPersistentHeader is painted within bounds of SliverMainAxisGroup', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverPinnedPersistentHeader is painted within bounds of SliverMainAxisGroup', (WidgetTester tester) async {
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(_buildSliverMainAxisGroup( await tester.pumpWidget(_buildSliverMainAxisGroup(
controller: controller, controller: controller,
slivers: <Widget>[ slivers: <Widget>[
...@@ -371,8 +381,10 @@ void main() { ...@@ -371,8 +381,10 @@ void main() {
}); });
testWidgets('SliverFloatingPersistentHeader is painted within bounds of SliverMainAxisGroup', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverFloatingPersistentHeader is painted within bounds of SliverMainAxisGroup', (WidgetTester tester) async {
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(_buildSliverMainAxisGroup( await tester.pumpWidget(_buildSliverMainAxisGroup(
controller: controller, controller: controller,
slivers: <Widget>[ slivers: <Widget>[
...@@ -400,8 +412,10 @@ void main() { ...@@ -400,8 +412,10 @@ void main() {
expect((renderHeader.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(0.0)); expect((renderHeader.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(0.0));
}); });
testWidgets('SliverPinnedPersistentHeader is painted within bounds of SliverMainAxisGroup with different minExtent/maxExtent', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverPinnedPersistentHeader is painted within bounds of SliverMainAxisGroup with different minExtent/maxExtent', (WidgetTester tester) async {
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(_buildSliverMainAxisGroup( await tester.pumpWidget(_buildSliverMainAxisGroup(
controller: controller, controller: controller,
slivers: <Widget>[ slivers: <Widget>[
...@@ -429,8 +443,10 @@ void main() { ...@@ -429,8 +443,10 @@ void main() {
expect((renderHeader.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(0.0)); expect((renderHeader.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(0.0));
}); });
testWidgets('SliverFloatingPersistentHeader is painted within bounds of SliverMainAxisGroup with different minExtent/maxExtent', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverFloatingPersistentHeader is painted within bounds of SliverMainAxisGroup with different minExtent/maxExtent', (WidgetTester tester) async {
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(_buildSliverMainAxisGroup( await tester.pumpWidget(_buildSliverMainAxisGroup(
controller: controller, controller: controller,
slivers: <Widget>[ slivers: <Widget>[
...@@ -465,8 +481,10 @@ void main() { ...@@ -465,8 +481,10 @@ void main() {
expect((renderHeader.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(0.0)); expect((renderHeader.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(0.0));
}); });
testWidgets('SliverPinnedFloatingPersistentHeader is painted within bounds of SliverMainAxisGroup with different minExtent/maxExtent', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverPinnedFloatingPersistentHeader is painted within bounds of SliverMainAxisGroup with different minExtent/maxExtent', (WidgetTester tester) async {
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(_buildSliverMainAxisGroup( await tester.pumpWidget(_buildSliverMainAxisGroup(
controller: controller, controller: controller,
slivers: <Widget>[ slivers: <Widget>[
...@@ -502,8 +520,10 @@ void main() { ...@@ -502,8 +520,10 @@ void main() {
expect((renderHeader.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(0.0)); expect((renderHeader.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(0.0));
}); });
testWidgets('SliverAppBar with floating: false, pinned: false, snap: false is painted within bounds of SliverMainAxisGroup', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverAppBar with floating: false, pinned: false, snap: false is painted within bounds of SliverMainAxisGroup', (WidgetTester tester) async {
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(_buildSliverMainAxisGroup( await tester.pumpWidget(_buildSliverMainAxisGroup(
controller: controller, controller: controller,
slivers: <Widget>[ slivers: <Widget>[
...@@ -532,8 +552,10 @@ void main() { ...@@ -532,8 +552,10 @@ void main() {
expect(renderHeader.geometry!.layoutExtent, equals(0.0)); expect(renderHeader.geometry!.layoutExtent, equals(0.0));
}); });
testWidgets('SliverAppBar with floating: true, pinned: false, snap: true is painted within bounds of SliverMainAxisGroup', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverAppBar with floating: true, pinned: false, snap: true is painted within bounds of SliverMainAxisGroup', (WidgetTester tester) async {
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(_buildSliverMainAxisGroup( await tester.pumpWidget(_buildSliverMainAxisGroup(
controller: controller, controller: controller,
slivers: <Widget>[ slivers: <Widget>[
...@@ -572,8 +594,10 @@ void main() { ...@@ -572,8 +594,10 @@ void main() {
expect((renderHeader.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(-50.0)); expect((renderHeader.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(-50.0));
}); });
testWidgets('SliverAppBar with floating: true, pinned: true, snap: true is painted within bounds of SliverMainAxisGroup', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverAppBar with floating: true, pinned: true, snap: true is painted within bounds of SliverMainAxisGroup', (WidgetTester tester) async {
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget(_buildSliverMainAxisGroup( await tester.pumpWidget(_buildSliverMainAxisGroup(
controller: controller, controller: controller,
slivers: <Widget>[ slivers: <Widget>[
...@@ -612,8 +636,9 @@ void main() { ...@@ -612,8 +636,9 @@ void main() {
expect((renderHeader.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(-50.0)); expect((renderHeader.parentData! as SliverPhysicalParentData).paintOffset.dy, equals(-50.0));
}); });
testWidgets('SliverMainAxisGroup skips painting invisible children', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverMainAxisGroup skips painting invisible children', (WidgetTester tester) async {
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
int counter = 0; int counter = 0;
void incrementCounter() { void incrementCounter() {
......
...@@ -5,9 +5,10 @@ ...@@ -5,9 +5,10 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/src/rendering/sliver_persistent_header.dart'; import 'package:flutter/src/rendering/sliver_persistent_header.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() { void main() {
testWidgets( testWidgetsWithLeakTracking(
'_SliverScrollingPersistentHeader should update stretchConfiguration', '_SliverScrollingPersistentHeader should update stretchConfiguration',
(WidgetTester tester) async { (WidgetTester tester) async {
for (final double stretchTriggerOffset in <double>[10.0, 20.0]) { for (final double stretchTriggerOffset in <double>[10.0, 20.0]) {
...@@ -37,7 +38,7 @@ void main() { ...@@ -37,7 +38,7 @@ void main() {
expect(render.stretchConfiguration?.stretchTriggerOffset, 20); expect(render.stretchConfiguration?.stretchTriggerOffset, 20);
}); });
testWidgets( testWidgetsWithLeakTracking(
'_SliverPinnedPersistentHeader should update stretchConfiguration', '_SliverPinnedPersistentHeader should update stretchConfiguration',
(WidgetTester tester) async { (WidgetTester tester) async {
for (final double stretchTriggerOffset in <double>[10.0, 20.0]) { for (final double stretchTriggerOffset in <double>[10.0, 20.0]) {
...@@ -68,7 +69,7 @@ void main() { ...@@ -68,7 +69,7 @@ void main() {
expect(render.stretchConfiguration?.stretchTriggerOffset, 20); expect(render.stretchConfiguration?.stretchTriggerOffset, 20);
}); });
testWidgets( testWidgetsWithLeakTracking(
'_SliverPinnedPersistentHeader should update showOnScreenConfiguration', '_SliverPinnedPersistentHeader should update showOnScreenConfiguration',
(WidgetTester tester) async { (WidgetTester tester) async {
for (final double maxShowOnScreenExtent in <double>[1000, 2000]) { for (final double maxShowOnScreenExtent in <double>[1000, 2000]) {
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
class TestItem extends StatelessWidget { class TestItem extends StatelessWidget {
const TestItem({ super.key, required this.item, this.width, this.height }); const TestItem({ super.key, required this.item, this.width, this.height });
...@@ -40,7 +41,7 @@ Widget buildFrame({ int? count, double? width, double? height, Axis? scrollDirec ...@@ -40,7 +41,7 @@ Widget buildFrame({ int? count, double? width, double? height, Axis? scrollDirec
} }
void main() { void main() {
testWidgets('SliverPrototypeExtentList.builder test', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverPrototypeExtentList.builder test', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
home: Scaffold( home: Scaffold(
...@@ -69,7 +70,7 @@ void main() { ...@@ -69,7 +70,7 @@ void main() {
} }
}); });
testWidgets('SliverPrototypeExtentList.builder test', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverPrototypeExtentList.builder test', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
home: Scaffold( home: Scaffold(
...@@ -95,7 +96,7 @@ void main() { ...@@ -95,7 +96,7 @@ void main() {
expect(find.text('Item 7'), findsNothing); expect(find.text('Item 7'), findsNothing);
}); });
testWidgets('SliverPrototypeExtentList vertical scrolling basics', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverPrototypeExtentList vertical scrolling basics', (WidgetTester tester) async {
await tester.pumpWidget(buildFrame(count: 20, height: 100.0)); await tester.pumpWidget(buildFrame(count: 20, height: 100.0));
// The viewport is 600 pixels high, lazily created items are 100 pixels high. // The viewport is 600 pixels high, lazily created items are 100 pixels high.
...@@ -121,7 +122,7 @@ void main() { ...@@ -121,7 +122,7 @@ void main() {
} }
}); });
testWidgets('SliverPrototypeExtentList horizontal scrolling basics', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverPrototypeExtentList horizontal scrolling basics', (WidgetTester tester) async {
await tester.pumpWidget(buildFrame(count: 20, width: 100.0, scrollDirection: Axis.horizontal)); await tester.pumpWidget(buildFrame(count: 20, width: 100.0, scrollDirection: Axis.horizontal));
// The viewport is 800 pixels wide, lazily created items are 100 pixels wide. // The viewport is 800 pixels wide, lazily created items are 100 pixels wide.
...@@ -147,7 +148,7 @@ void main() { ...@@ -147,7 +148,7 @@ void main() {
} }
}); });
testWidgets('SliverPrototypeExtentList change the prototype item', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverPrototypeExtentList change the prototype item', (WidgetTester tester) async {
await tester.pumpWidget(buildFrame(count: 10, height: 60.0)); await tester.pumpWidget(buildFrame(count: 10, height: 60.0));
// The viewport is 600 pixels high, each of the 10 items is 60 pixels high // The viewport is 600 pixels high, each of the 10 items is 60 pixels high
...@@ -173,7 +174,7 @@ void main() { ...@@ -173,7 +174,7 @@ void main() {
} }
}); });
testWidgets('SliverPrototypeExtentList first item is also the prototype', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverPrototypeExtentList first item is also the prototype', (WidgetTester tester) async {
final List<Widget> items = List<Widget>.generate(10, (int index) { final List<Widget> items = List<Widget>.generate(10, (int index) {
return TestItem(key: ValueKey<int>(index), item: index, height: index == 0 ? 60.0 : null); return TestItem(key: ValueKey<int>(index), item: index, height: index == 0 ? 60.0 : null);
}).toList(); }).toList();
...@@ -203,7 +204,7 @@ void main() { ...@@ -203,7 +204,7 @@ void main() {
} }
}); });
testWidgets('SliverPrototypeExtentList prototypeItem paint transform is zero.', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverPrototypeExtentList prototypeItem paint transform is zero.', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/67117 // Regression test for https://github.com/flutter/flutter/issues/67117
// This test ensures that the SliverPrototypeExtentList does not cause an // This test ensures that the SliverPrototypeExtentList does not cause an
// assertion error when calculating the paint transform of its prototypeItem. // assertion error when calculating the paint transform of its prototypeItem.
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import 'semantics_tester.dart'; import 'semantics_tester.dart';
...@@ -19,12 +20,13 @@ void main() { ...@@ -19,12 +20,13 @@ void main() {
} }
void _tests() { void _tests() {
testWidgets('excludeFromScrollable works correctly', (WidgetTester tester) async { testWidgetsWithLeakTracking('excludeFromScrollable works correctly', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
const double appBarExpandedHeight = 200.0; const double appBarExpandedHeight = 200.0;
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
final List<Widget> listChildren = List<Widget>.generate(30, (int i) { final List<Widget> listChildren = List<Widget>.generate(30, (int i) {
return SizedBox( return SizedBox(
height: appBarExpandedHeight, height: appBarExpandedHeight,
...@@ -281,7 +283,7 @@ void _tests() { ...@@ -281,7 +283,7 @@ void _tests() {
semantics.dispose(); semantics.dispose();
}); });
testWidgets('Offscreen sliver are hidden in semantics tree', (WidgetTester tester) async { testWidgetsWithLeakTracking('Offscreen sliver are hidden in semantics tree', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
const double containerHeight = 200.0; const double containerHeight = 200.0;
...@@ -289,6 +291,7 @@ void _tests() { ...@@ -289,6 +291,7 @@ void _tests() {
final ScrollController scrollController = ScrollController( final ScrollController scrollController = ScrollController(
initialScrollOffset: containerHeight * 1.5, initialScrollOffset: containerHeight * 1.5,
); );
addTearDown(scrollController.dispose);
final List<Widget> slivers = List<Widget>.generate(30, (int i) { final List<Widget> slivers = List<Widget>.generate(30, (int i) {
return SliverToBoxAdapter( return SliverToBoxAdapter(
child: SizedBox( child: SizedBox(
...@@ -373,7 +376,7 @@ void _tests() { ...@@ -373,7 +376,7 @@ void _tests() {
semantics.dispose(); semantics.dispose();
}); });
testWidgets('SemanticsNodes of Slivers are in paint order', (WidgetTester tester) async { testWidgetsWithLeakTracking('SemanticsNodes of Slivers are in paint order', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
final List<Widget> slivers = List<Widget>.generate(5, (int i) { final List<Widget> slivers = List<Widget>.generate(5, (int i) {
...@@ -453,7 +456,7 @@ void _tests() { ...@@ -453,7 +456,7 @@ void _tests() {
semantics.dispose(); semantics.dispose();
}); });
testWidgets('SemanticsNodes of a sliver fully covered by another overlapping sliver are excluded', (WidgetTester tester) async { testWidgetsWithLeakTracking('SemanticsNodes of a sliver fully covered by another overlapping sliver are excluded', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
final List<Widget> listChildren = List<Widget>.generate(10, (int i) { final List<Widget> listChildren = List<Widget>.generate(10, (int i) {
...@@ -463,6 +466,7 @@ void _tests() { ...@@ -463,6 +466,7 @@ void _tests() {
); );
}); });
final ScrollController controller = ScrollController(initialScrollOffset: 280.0); final ScrollController controller = ScrollController(initialScrollOffset: 280.0);
addTearDown(controller.dispose);
await tester.pumpWidget(Semantics( await tester.pumpWidget(Semantics(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: Localizations( child: Localizations(
...@@ -564,10 +568,11 @@ void _tests() { ...@@ -564,10 +568,11 @@ void _tests() {
semantics.dispose(); semantics.dispose();
}); });
testWidgets('Slivers fully covered by another overlapping sliver are hidden', (WidgetTester tester) async { testWidgetsWithLeakTracking('Slivers fully covered by another overlapping sliver are hidden', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
final ScrollController controller = ScrollController(initialScrollOffset: 280.0); final ScrollController controller = ScrollController(initialScrollOffset: 280.0);
addTearDown(controller.dispose);
final List<Widget> slivers = List<Widget>.generate(10, (int i) { final List<Widget> slivers = List<Widget>.generate(10, (int i) {
return SliverToBoxAdapter( return SliverToBoxAdapter(
child: SizedBox( child: SizedBox(
...@@ -675,7 +680,7 @@ void _tests() { ...@@ -675,7 +680,7 @@ void _tests() {
semantics.dispose(); semantics.dispose();
}); });
testWidgets('SemanticsNodes of a sliver fully covered by another overlapping sliver are excluded (reverse)', (WidgetTester tester) async { testWidgetsWithLeakTracking('SemanticsNodes of a sliver fully covered by another overlapping sliver are excluded (reverse)', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
final List<Widget> listChildren = List<Widget>.generate(10, (int i) { final List<Widget> listChildren = List<Widget>.generate(10, (int i) {
...@@ -685,6 +690,7 @@ void _tests() { ...@@ -685,6 +690,7 @@ void _tests() {
); );
}); });
final ScrollController controller = ScrollController(initialScrollOffset: 280.0); final ScrollController controller = ScrollController(initialScrollOffset: 280.0);
addTearDown(controller.dispose);
await tester.pumpWidget(Semantics( await tester.pumpWidget(Semantics(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: Localizations( child: Localizations(
...@@ -789,10 +795,11 @@ void _tests() { ...@@ -789,10 +795,11 @@ void _tests() {
semantics.dispose(); semantics.dispose();
}); });
testWidgets('Slivers fully covered by another overlapping sliver are hidden (reverse)', (WidgetTester tester) async { testWidgetsWithLeakTracking('Slivers fully covered by another overlapping sliver are hidden (reverse)', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
final ScrollController controller = ScrollController(initialScrollOffset: 280.0); final ScrollController controller = ScrollController(initialScrollOffset: 280.0);
addTearDown(controller.dispose);
final List<Widget> slivers = List<Widget>.generate(10, (int i) { final List<Widget> slivers = List<Widget>.generate(10, (int i) {
return SliverToBoxAdapter( return SliverToBoxAdapter(
child: SizedBox( child: SizedBox(
...@@ -903,10 +910,11 @@ void _tests() { ...@@ -903,10 +910,11 @@ void _tests() {
semantics.dispose(); semantics.dispose();
}); });
testWidgets('Slivers fully covered by another overlapping sliver are hidden (with center sliver)', (WidgetTester tester) async { testWidgetsWithLeakTracking('Slivers fully covered by another overlapping sliver are hidden (with center sliver)', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
final ScrollController controller = ScrollController(initialScrollOffset: 280.0); final ScrollController controller = ScrollController(initialScrollOffset: 280.0);
addTearDown(controller.dispose);
final GlobalKey forwardAppBarKey = GlobalKey(debugLabel: 'forward app bar'); final GlobalKey forwardAppBarKey = GlobalKey(debugLabel: 'forward app bar');
final List<Widget> forwardChildren = List<Widget>.generate(10, (int i) { final List<Widget> forwardChildren = List<Widget>.generate(10, (int i) {
return SizedBox( return SizedBox(
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import 'semantics_tester.dart'; import 'semantics_tester.dart';
...@@ -29,7 +30,7 @@ class _TestStateState extends State<TestState> { ...@@ -29,7 +30,7 @@ class _TestStateState extends State<TestState> {
} }
void main() { void main() {
testWidgets('SliverVisibility', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverVisibility', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
final List<String> log = <String>[]; final List<String> log = <String>[];
const Key anchor = Key('drag'); const Key anchor = Key('drag');
......
...@@ -5,11 +5,12 @@ ...@@ -5,11 +5,12 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import 'semantics_tester.dart'; import 'semantics_tester.dart';
void main() { void main() {
testWidgets('Sliver appBars - floating and pinned - correct elevation', (WidgetTester tester) async { testWidgetsWithLeakTracking('Sliver appBars - floating and pinned - correct elevation', (WidgetTester tester) async {
await tester.pumpWidget(Localizations( await tester.pumpWidget(Localizations(
locale: const Locale('en', 'us'), locale: const Locale('en', 'us'),
delegates: const <LocalizationsDelegate<dynamic>>[ delegates: const <LocalizationsDelegate<dynamic>>[
...@@ -46,7 +47,7 @@ void main() { ...@@ -46,7 +47,7 @@ void main() {
expect(renderObject.elevation, 0.0); expect(renderObject.elevation, 0.0);
}); });
testWidgets('Sliver appbars - floating and pinned - correct semantics', (WidgetTester tester) async { testWidgetsWithLeakTracking('Sliver appbars - floating and pinned - correct semantics', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Localizations( Localizations(
locale: const Locale('en', 'us'), locale: const Locale('en', 'us'),
...@@ -241,8 +242,10 @@ void main() { ...@@ -241,8 +242,10 @@ void main() {
semantics.dispose(); semantics.dispose();
}); });
testWidgets('Sliver appbars - floating and pinned - second app bar stacks below', (WidgetTester tester) async { testWidgetsWithLeakTracking('Sliver appbars - floating and pinned - second app bar stacks below', (WidgetTester tester) async {
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
theme: ThemeData(useMaterial3: false), theme: ThemeData(useMaterial3: false),
...@@ -292,10 +295,12 @@ void main() { ...@@ -292,10 +295,12 @@ void main() {
expect(tester.getTopLeft(find.text('E')), Offset(0.0, 200.0 + 56.0 + cSize.height * 2.0 + 500.0 - 600.0)); expect(tester.getTopLeft(find.text('E')), Offset(0.0, 200.0 + 56.0 + cSize.height * 2.0 + 500.0 - 600.0));
}); });
testWidgets('Does not crash when there is less than minExtent remainingPaintExtent', (WidgetTester tester) async { testWidgetsWithLeakTracking('Does not crash when there is less than minExtent remainingPaintExtent', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/21887. // Regression test for https://github.com/flutter/flutter/issues/21887.
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose);
const double availableHeight = 50.0; const double availableHeight = 50.0;
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
home: Center( home: Center(
...@@ -337,7 +342,7 @@ void main() { ...@@ -337,7 +342,7 @@ void main() {
expect(render.geometry!.layoutExtent, 0.0); expect(render.geometry!.layoutExtent, 0.0);
}); });
testWidgets('Pinned and floating SliverAppBar sticks to top the content is scroll down', (WidgetTester tester) async { testWidgetsWithLeakTracking('Pinned and floating SliverAppBar sticks to top the content is scroll down', (WidgetTester tester) async {
const Key anchor = Key('drag'); const Key anchor = Key('drag');
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
...@@ -371,7 +376,7 @@ void main() { ...@@ -371,7 +376,7 @@ void main() {
expect(render.geometry!.paintOrigin, -scrollDistance); expect(render.geometry!.paintOrigin, -scrollDistance);
}); });
testWidgets('Floating SliverAppBar sticks to top the content is scroll down', (WidgetTester tester) async { testWidgetsWithLeakTracking('Floating SliverAppBar sticks to top the content is scroll down', (WidgetTester tester) async {
const Key anchor = Key('drag'); const Key anchor = Key('drag');
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
...@@ -404,7 +409,7 @@ void main() { ...@@ -404,7 +409,7 @@ void main() {
expect(render.geometry!.paintOrigin, -scrollDistance); expect(render.geometry!.paintOrigin, -scrollDistance);
}); });
testWidgets('Pinned SliverAppBar sticks to top the content is scroll down', (WidgetTester tester) async { testWidgetsWithLeakTracking('Pinned SliverAppBar sticks to top the content is scroll down', (WidgetTester tester) async {
const Key anchor = Key('drag'); const Key anchor = Key('drag');
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
......
...@@ -7,6 +7,7 @@ import 'dart:ui' as ui; ...@@ -7,6 +7,7 @@ import 'dart:ui' as ui;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void verifyPaintPosition(GlobalKey key, Offset ideal, bool visible) { void verifyPaintPosition(GlobalKey key, Offset ideal, bool visible) {
final RenderSliver target = key.currentContext!.findRenderObject()! as RenderSliver; final RenderSliver target = key.currentContext!.findRenderObject()! as RenderSliver;
...@@ -25,7 +26,7 @@ void verifyActualBoxPosition(WidgetTester tester, Finder finder, int index, Rect ...@@ -25,7 +26,7 @@ void verifyActualBoxPosition(WidgetTester tester, Finder finder, int index, Rect
} }
void main() { void main() {
testWidgets("Sliver appbars - floating - scroll offset doesn't change", (WidgetTester tester) async { testWidgetsWithLeakTracking("Sliver appbars - floating - scroll offset doesn't change", (WidgetTester tester) async {
const double bigHeight = 1000.0; const double bigHeight = 1000.0;
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
...@@ -53,7 +54,7 @@ void main() { ...@@ -53,7 +54,7 @@ void main() {
expect(position.maxScrollExtent, max); expect(position.maxScrollExtent, max);
}); });
testWidgets('Sliver appbars - floating - normal behavior works', (WidgetTester tester) async { testWidgetsWithLeakTracking('Sliver appbars - floating - normal behavior works', (WidgetTester tester) async {
final TestDelegate delegate = TestDelegate(); final TestDelegate delegate = TestDelegate();
const double bigHeight = 1000.0; const double bigHeight = 1000.0;
GlobalKey key1, key2, key3; GlobalKey key1, key2, key3;
...@@ -125,7 +126,7 @@ void main() { ...@@ -125,7 +126,7 @@ void main() {
verifyPaintPosition(key3, Offset.zero, true); verifyPaintPosition(key3, Offset.zero, true);
}); });
testWidgets('Sliver appbars - floating - no floating behavior when animating', (WidgetTester tester) async { testWidgetsWithLeakTracking('Sliver appbars - floating - no floating behavior when animating', (WidgetTester tester) async {
final TestDelegate delegate = TestDelegate(); final TestDelegate delegate = TestDelegate();
const double bigHeight = 1000.0; const double bigHeight = 1000.0;
GlobalKey key1, key2, key3; GlobalKey key1, key2, key3;
...@@ -160,7 +161,7 @@ void main() { ...@@ -160,7 +161,7 @@ void main() {
verifyPaintPosition(key3, Offset.zero, true); verifyPaintPosition(key3, Offset.zero, true);
}); });
testWidgets('Sliver appbars - floating - floating behavior when dragging down', (WidgetTester tester) async { testWidgetsWithLeakTracking('Sliver appbars - floating - floating behavior when dragging down', (WidgetTester tester) async {
final TestDelegate delegate = TestDelegate(); final TestDelegate delegate = TestDelegate();
const double bigHeight = 1000.0; const double bigHeight = 1000.0;
GlobalKey key1, key2, key3; GlobalKey key1, key2, key3;
...@@ -197,7 +198,7 @@ void main() { ...@@ -197,7 +198,7 @@ void main() {
verifyPaintPosition(key3, Offset.zero, true); verifyPaintPosition(key3, Offset.zero, true);
}); });
testWidgets('Sliver appbars - floating - overscroll gap is below header', (WidgetTester tester) async { testWidgetsWithLeakTracking('Sliver appbars - floating - overscroll gap is below header', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -258,7 +259,7 @@ void main() { ...@@ -258,7 +259,7 @@ void main() {
expect(geometry.paintExtent, paintExtent); expect(geometry.paintExtent, paintExtent);
} }
testWidgets('SliverAppBar', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverAppBar', (WidgetTester tester) async {
final GlobalKey appBarKey = GlobalKey(); final GlobalKey appBarKey = GlobalKey();
await tester.pumpWidget(buildTest(SliverAppBar( await tester.pumpWidget(buildTest(SliverAppBar(
key: appBarKey, key: appBarKey,
...@@ -312,7 +313,7 @@ void main() { ...@@ -312,7 +313,7 @@ void main() {
verifyGeometry(key: appBarKey, paintExtent: 56.0, visible: true); verifyGeometry(key: appBarKey, paintExtent: 56.0, visible: true);
}); });
testWidgets('SliverPersistentHeader', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverPersistentHeader', (WidgetTester tester) async {
final GlobalKey headerKey = GlobalKey(); final GlobalKey headerKey = GlobalKey();
await tester.pumpWidget(buildTest(SliverPersistentHeader( await tester.pumpWidget(buildTest(SliverPersistentHeader(
key: headerKey, key: headerKey,
...@@ -354,7 +355,7 @@ void main() { ...@@ -354,7 +355,7 @@ void main() {
verifyGeometry(key: headerKey, paintExtent: 56.0, visible: true); verifyGeometry(key: headerKey, paintExtent: 56.0, visible: true);
}); });
testWidgets('and snapping SliverAppBar', (WidgetTester tester) async { testWidgetsWithLeakTracking('and snapping SliverAppBar', (WidgetTester tester) async {
final GlobalKey appBarKey = GlobalKey(); final GlobalKey appBarKey = GlobalKey();
await tester.pumpWidget(buildTest(SliverAppBar( await tester.pumpWidget(buildTest(SliverAppBar(
key: appBarKey, key: appBarKey,
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void verifyPaintPosition(GlobalKey key, Offset ideal, bool visible) { void verifyPaintPosition(GlobalKey key, Offset ideal, bool visible) {
final RenderSliver target = key.currentContext!.findRenderObject()! as RenderSliver; final RenderSliver target = key.currentContext!.findRenderObject()! as RenderSliver;
...@@ -23,7 +24,7 @@ void verifyActualBoxPosition(WidgetTester tester, Finder finder, int index, Rect ...@@ -23,7 +24,7 @@ void verifyActualBoxPosition(WidgetTester tester, Finder finder, int index, Rect
} }
void main() { void main() {
testWidgets('Sliver appbars - pinned', (WidgetTester tester) async { testWidgetsWithLeakTracking('Sliver appbars - pinned', (WidgetTester tester) async {
const double bigHeight = 550.0; const double bigHeight = 550.0;
GlobalKey key1, key2, key3, key4, key5; GlobalKey key1, key2, key3, key4, key5;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -59,7 +60,7 @@ void main() { ...@@ -59,7 +60,7 @@ void main() {
verifyPaintPosition(key5, const Offset(0.0, 50.0), true); verifyPaintPosition(key5, const Offset(0.0, 50.0), true);
}); });
testWidgets('Sliver appbars - toStringDeep of maxExtent that throws', (WidgetTester tester) async { testWidgetsWithLeakTracking('Sliver appbars - toStringDeep of maxExtent that throws', (WidgetTester tester) async {
final TestDelegateThatCanThrow delegateThatCanThrow = TestDelegateThatCanThrow(); final TestDelegateThatCanThrow delegateThatCanThrow = TestDelegateThatCanThrow();
GlobalKey key; GlobalKey key;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -121,7 +122,7 @@ void main() { ...@@ -121,7 +122,7 @@ void main() {
); );
}); });
testWidgets('Sliver appbars - pinned with slow scroll', (WidgetTester tester) async { testWidgetsWithLeakTracking('Sliver appbars - pinned with slow scroll', (WidgetTester tester) async {
const double bigHeight = 550.0; const double bigHeight = 550.0;
GlobalKey key1, key2, key3, key4, key5; GlobalKey key1, key2, key3, key4, key5;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -214,7 +215,7 @@ void main() { ...@@ -214,7 +215,7 @@ void main() {
verifyPaintPosition(key5, const Offset(0.0, 550.0), true); verifyPaintPosition(key5, const Offset(0.0, 550.0), true);
}); });
testWidgets('Sliver appbars - pinned with less overlap', (WidgetTester tester) async { testWidgetsWithLeakTracking('Sliver appbars - pinned with less overlap', (WidgetTester tester) async {
const double bigHeight = 650.0; const double bigHeight = 650.0;
GlobalKey key1, key2, key3, key4, key5; GlobalKey key1, key2, key3, key4, key5;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -250,7 +251,7 @@ void main() { ...@@ -250,7 +251,7 @@ void main() {
verifyPaintPosition(key5, Offset.zero, true); verifyPaintPosition(key5, Offset.zero, true);
}); });
testWidgets('Sliver appbars - overscroll gap is below header', (WidgetTester tester) async { testWidgetsWithLeakTracking('Sliver appbars - overscroll gap is below header', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void verifyPaintPosition(GlobalKey key, Offset ideal) { void verifyPaintPosition(GlobalKey key, Offset ideal) {
final RenderObject target = key.currentContext!.findRenderObject()!; final RenderObject target = key.currentContext!.findRenderObject()!;
...@@ -15,7 +16,7 @@ void verifyPaintPosition(GlobalKey key, Offset ideal) { ...@@ -15,7 +16,7 @@ void verifyPaintPosition(GlobalKey key, Offset ideal) {
} }
void main() { void main() {
testWidgets('Sliver appbars - scrolling', (WidgetTester tester) async { testWidgetsWithLeakTracking('Sliver appbars - scrolling', (WidgetTester tester) async {
GlobalKey key1, key2, key3, key4, key5; GlobalKey key1, key2, key3, key4, key5;
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
...@@ -50,7 +51,7 @@ void main() { ...@@ -50,7 +51,7 @@ void main() {
verifyPaintPosition(key5, const Offset(0.0, 50.0)); verifyPaintPosition(key5, const Offset(0.0, 50.0));
}); });
testWidgets('Sliver appbars - scrolling off screen', (WidgetTester tester) async { testWidgetsWithLeakTracking('Sliver appbars - scrolling off screen', (WidgetTester tester) async {
final GlobalKey key = GlobalKey(); final GlobalKey key = GlobalKey();
final TestDelegate delegate = TestDelegate(); final TestDelegate delegate = TestDelegate();
await tester.pumpWidget( await tester.pumpWidget(
...@@ -74,7 +75,7 @@ void main() { ...@@ -74,7 +75,7 @@ void main() {
expect(rect, equals(const Rect.fromLTWH(0.0, -195.0, 800.0, 200.0))); expect(rect, equals(const Rect.fromLTWH(0.0, -195.0, 800.0, 200.0)));
}); });
testWidgets('Sliver appbars - scrolling - overscroll gap is below header', (WidgetTester tester) async { testWidgetsWithLeakTracking('Sliver appbars - scrolling - overscroll gap is below header', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -106,7 +107,7 @@ void main() { ...@@ -106,7 +107,7 @@ void main() {
expect(tester.getTopLeft(find.text('X')), const Offset(0.0, 250.0)); expect(tester.getTopLeft(find.text('X')), const Offset(0.0, 250.0));
}); });
testWidgets('Sliver appbars const child delegate - scrolling - overscroll gap is below header', (WidgetTester tester) async { testWidgetsWithLeakTracking('Sliver appbars const child delegate - scrolling - overscroll gap is below header', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
......
...@@ -5,10 +5,11 @@ ...@@ -5,10 +5,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() { void main() {
group('SliverAppBar - Stretch', () { group('SliverAppBar - Stretch', () {
testWidgets('fills overscroll', (WidgetTester tester) async { testWidgetsWithLeakTracking('fills overscroll', (WidgetTester tester) async {
const Key anchor = Key('drag'); const Key anchor = Key('drag');
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
...@@ -43,7 +44,7 @@ void main() { ...@@ -43,7 +44,7 @@ void main() {
expect(header.child!.size.height, equals(200.0)); expect(header.child!.size.height, equals(200.0));
}); });
testWidgets('fills overscroll after reverse direction input - scrolling header', (WidgetTester tester) async { testWidgetsWithLeakTracking('fills overscroll after reverse direction input - scrolling header', (WidgetTester tester) async {
const Key anchor = Key('drag'); const Key anchor = Key('drag');
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
...@@ -92,7 +93,7 @@ void main() { ...@@ -92,7 +93,7 @@ void main() {
await tester.pumpAndSettle(); await tester.pumpAndSettle();
}); });
testWidgets('fills overscroll after reverse direction input - floating header', (WidgetTester tester) async { testWidgetsWithLeakTracking('fills overscroll after reverse direction input - floating header', (WidgetTester tester) async {
const Key anchor = Key('drag'); const Key anchor = Key('drag');
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
...@@ -142,7 +143,7 @@ void main() { ...@@ -142,7 +143,7 @@ void main() {
await tester.pumpAndSettle(); await tester.pumpAndSettle();
}); });
testWidgets('does not stretch without overscroll physics', (WidgetTester tester) async { testWidgetsWithLeakTracking('does not stretch without overscroll physics', (WidgetTester tester) async {
const Key anchor = Key('drag'); const Key anchor = Key('drag');
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
...@@ -177,7 +178,7 @@ void main() { ...@@ -177,7 +178,7 @@ void main() {
expect(header.child!.size.height, equals(100.0)); expect(header.child!.size.height, equals(100.0));
}); });
testWidgets('default trigger offset', (WidgetTester tester) async { testWidgetsWithLeakTracking('default trigger offset', (WidgetTester tester) async {
bool didTrigger = false; bool didTrigger = false;
const Key anchor = Key('drag'); const Key anchor = Key('drag');
await tester.pumpWidget( await tester.pumpWidget(
...@@ -215,7 +216,7 @@ void main() { ...@@ -215,7 +216,7 @@ void main() {
expect(didTrigger, isTrue); expect(didTrigger, isTrue);
}); });
testWidgets('custom trigger offset', (WidgetTester tester) async { testWidgetsWithLeakTracking('custom trigger offset', (WidgetTester tester) async {
bool didTrigger = false; bool didTrigger = false;
const Key anchor = Key('drag'); const Key anchor = Key('drag');
await tester.pumpWidget( await tester.pumpWidget(
...@@ -254,7 +255,7 @@ void main() { ...@@ -254,7 +255,7 @@ void main() {
expect(didTrigger, isTrue); expect(didTrigger, isTrue);
}); });
testWidgets('stretch callback not triggered without overscroll physics', (WidgetTester tester) async { testWidgetsWithLeakTracking('stretch callback not triggered without overscroll physics', (WidgetTester tester) async {
bool didTrigger = false; bool didTrigger = false;
const Key anchor = Key('drag'); const Key anchor = Key('drag');
await tester.pumpWidget( await tester.pumpWidget(
...@@ -293,7 +294,7 @@ void main() { ...@@ -293,7 +294,7 @@ void main() {
expect(didTrigger, isFalse); expect(didTrigger, isFalse);
}); });
testWidgets('asserts reasonable trigger offset', (WidgetTester tester) async { testWidgetsWithLeakTracking('asserts reasonable trigger offset', (WidgetTester tester) async {
expect( expect(
() { () {
return MaterialApp( return MaterialApp(
...@@ -325,7 +326,7 @@ void main() { ...@@ -325,7 +326,7 @@ void main() {
}); });
group('SliverAppBar - Stretch, Pinned', () { group('SliverAppBar - Stretch, Pinned', () {
testWidgets('fills overscroll', (WidgetTester tester) async { testWidgetsWithLeakTracking('fills overscroll', (WidgetTester tester) async {
const Key anchor = Key('drag'); const Key anchor = Key('drag');
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
...@@ -360,7 +361,7 @@ void main() { ...@@ -360,7 +361,7 @@ void main() {
expect(header.child!.size.height, equals(200.0)); expect(header.child!.size.height, equals(200.0));
}); });
testWidgets('does not stretch without overscroll physics', (WidgetTester tester) async { testWidgetsWithLeakTracking('does not stretch without overscroll physics', (WidgetTester tester) async {
const Key anchor = Key('drag'); const Key anchor = Key('drag');
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
...@@ -397,7 +398,7 @@ void main() { ...@@ -397,7 +398,7 @@ void main() {
}); });
group('SliverAppBar - Stretch, Floating', () { group('SliverAppBar - Stretch, Floating', () {
testWidgets('fills overscroll', (WidgetTester tester) async { testWidgetsWithLeakTracking('fills overscroll', (WidgetTester tester) async {
const Key anchor = Key('drag'); const Key anchor = Key('drag');
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
...@@ -432,7 +433,7 @@ void main() { ...@@ -432,7 +433,7 @@ void main() {
expect(header.child!.size.height, equals(200.0)); expect(header.child!.size.height, equals(200.0));
}); });
testWidgets('does not fill overscroll without proper physics', (WidgetTester tester) async { testWidgetsWithLeakTracking('does not fill overscroll without proper physics', (WidgetTester tester) async {
const Key anchor = Key('drag'); const Key anchor = Key('drag');
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
...@@ -469,7 +470,7 @@ void main() { ...@@ -469,7 +470,7 @@ void main() {
}); });
group('SliverAppBar - Stretch, Floating, Pinned', () { group('SliverAppBar - Stretch, Floating, Pinned', () {
testWidgets('fills overscroll', (WidgetTester tester) async { testWidgetsWithLeakTracking('fills overscroll', (WidgetTester tester) async {
const Key anchor = Key('drag'); const Key anchor = Key('drag');
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
...@@ -505,7 +506,7 @@ void main() { ...@@ -505,7 +506,7 @@ void main() {
expect(header.child!.size.height, equals(200.0)); expect(header.child!.size.height, equals(200.0));
}); });
testWidgets('does not fill overscroll without proper physics', (WidgetTester tester) async { testWidgetsWithLeakTracking('does not fill overscroll without proper physics', (WidgetTester tester) async {
const Key anchor = Key('drag'); const Key anchor = Key('drag');
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
int globalGeneration = 0; int globalGeneration = 0;
...@@ -25,13 +26,15 @@ class _GenerationTextState extends State<GenerationText> { ...@@ -25,13 +26,15 @@ class _GenerationTextState extends State<GenerationText> {
// Creates a SliverList with `keys.length` children and each child having a key from `keys` and a text of `key:generation`. // Creates a SliverList with `keys.length` children and each child having a key from `keys` and a text of `key:generation`.
// The generation is increased with every call to this method. // The generation is increased with every call to this method.
Future<void> test(WidgetTester tester, double offset, List<int> keys) { Future<void> test(WidgetTester tester, double offset, List<int> keys) {
final ViewportOffset viewportOffset = ViewportOffset.fixed(offset);
addTearDown(viewportOffset.dispose);
globalGeneration += 1; globalGeneration += 1;
return tester.pumpWidget( return tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: Viewport( child: Viewport(
cacheExtent: 0.0, cacheExtent: 0.0,
offset: ViewportOffset.fixed(offset), offset: viewportOffset,
slivers: <Widget>[ slivers: <Widget>[
SliverList( SliverList(
delegate: SliverChildListDelegate(keys.map<Widget>((int key) { delegate: SliverChildListDelegate(keys.map<Widget>((int key) {
...@@ -59,7 +62,7 @@ void verify(WidgetTester tester, List<Offset> answerKey, String text) { ...@@ -59,7 +62,7 @@ void verify(WidgetTester tester, List<Offset> answerKey, String text) {
} }
void main() { void main() {
testWidgets('Viewport+SliverBlock with GlobalKey reparenting', (WidgetTester tester) async { testWidgetsWithLeakTracking('Viewport+SliverBlock with GlobalKey reparenting', (WidgetTester tester) async {
await test(tester, 0.0, <int>[1,2,3,4,5,6,7,8,9]); await test(tester, 0.0, <int>[1,2,3,4,5,6,7,8,9]);
verify(tester, <Offset>[ verify(tester, <Offset>[
Offset.zero, Offset.zero,
......
...@@ -5,13 +5,16 @@ ...@@ -5,13 +5,16 @@
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
Future<void> test(WidgetTester tester, double offset) { Future<void> test(WidgetTester tester, double offset) {
final ViewportOffset viewportOffset = ViewportOffset.fixed(offset);
addTearDown(viewportOffset.dispose);
return tester.pumpWidget( return tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: Viewport( child: Viewport(
offset: ViewportOffset.fixed(offset), offset: viewportOffset,
slivers: <Widget>[ slivers: <Widget>[
SliverList( SliverList(
delegate: SliverChildListDelegate(const <Widget>[ delegate: SliverChildListDelegate(const <Widget>[
...@@ -29,11 +32,13 @@ Future<void> test(WidgetTester tester, double offset) { ...@@ -29,11 +32,13 @@ Future<void> test(WidgetTester tester, double offset) {
} }
Future<void> testWithConstChildDelegate(WidgetTester tester, double offset) { Future<void> testWithConstChildDelegate(WidgetTester tester, double offset) {
final ViewportOffset viewportOffset = ViewportOffset.fixed(offset);
addTearDown(viewportOffset.dispose);
return tester.pumpWidget( return tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: Viewport( child: Viewport(
offset: ViewportOffset.fixed(offset), offset: viewportOffset,
slivers: const <Widget>[ slivers: const <Widget>[
SliverList( SliverList(
delegate: SliverChildListDelegate.fixed(<Widget>[ delegate: SliverChildListDelegate.fixed(<Widget>[
...@@ -63,7 +68,7 @@ void verify(WidgetTester tester, List<Offset> answerKey, String text) { ...@@ -63,7 +68,7 @@ void verify(WidgetTester tester, List<Offset> answerKey, String text) {
} }
void main() { void main() {
testWidgets('Viewport+SliverBlock basic test', (WidgetTester tester) async { testWidgetsWithLeakTracking('Viewport+SliverBlock basic test', (WidgetTester tester) async {
await test(tester, 0.0); await test(tester, 0.0);
expect(tester.renderObject<RenderBox>(find.byType(Viewport)).size, equals(const Size(800.0, 600.0))); expect(tester.renderObject<RenderBox>(find.byType(Viewport)).size, equals(const Size(800.0, 600.0)));
verify(tester, <Offset>[ verify(tester, <Offset>[
...@@ -96,7 +101,7 @@ void main() { ...@@ -96,7 +101,7 @@ void main() {
], 'ab'); ], 'ab');
}); });
testWidgets('Viewport+SliverBlock basic test with constant SliverChildListDelegate', (WidgetTester tester) async { testWidgetsWithLeakTracking('Viewport+SliverBlock basic test with constant SliverChildListDelegate', (WidgetTester tester) async {
await testWithConstChildDelegate(tester, 0.0); await testWithConstChildDelegate(tester, 0.0);
expect(tester.renderObject<RenderBox>(find.byType(Viewport)).size, equals(const Size(800.0, 600.0))); expect(tester.renderObject<RenderBox>(find.byType(Viewport)).size, equals(const Size(800.0, 600.0)));
verify(tester, <Offset>[ verify(tester, <Offset>[
...@@ -129,9 +134,10 @@ void main() { ...@@ -129,9 +134,10 @@ void main() {
], 'ab'); ], 'ab');
}); });
testWidgets('Viewport with GlobalKey reparenting', (WidgetTester tester) async { testWidgetsWithLeakTracking('Viewport with GlobalKey reparenting', (WidgetTester tester) async {
final Key key1 = GlobalKey(); final Key key1 = GlobalKey();
final ViewportOffset offset = ViewportOffset.zero(); final ViewportOffset offset = ViewportOffset.zero();
addTearDown(offset.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -242,12 +248,15 @@ void main() { ...@@ -242,12 +248,15 @@ void main() {
], 'acb'); ], 'acb');
}); });
testWidgets('Viewport overflow clipping of SliverToBoxAdapter', (WidgetTester tester) async { testWidgetsWithLeakTracking('Viewport overflow clipping of SliverToBoxAdapter', (WidgetTester tester) async {
final ViewportOffset offset1 = ViewportOffset.zero();
addTearDown(offset1.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: Viewport( child: Viewport(
offset: ViewportOffset.zero(), offset: offset1,
slivers: const <Widget>[ slivers: const <Widget>[
SliverToBoxAdapter( SliverToBoxAdapter(
child: SizedBox(height: 400.0, child: Text('a')), child: SizedBox(height: 400.0, child: Text('a')),
...@@ -259,11 +268,14 @@ void main() { ...@@ -259,11 +268,14 @@ void main() {
expect(find.byType(Viewport), isNot(paints..clipRect())); expect(find.byType(Viewport), isNot(paints..clipRect()));
final ViewportOffset offset2 = ViewportOffset.fixed(100.0);
addTearDown(offset2.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: Viewport( child: Viewport(
offset: ViewportOffset.fixed(100.0), offset: offset2,
slivers: const <Widget>[ slivers: const <Widget>[
SliverToBoxAdapter( SliverToBoxAdapter(
child: SizedBox(height: 400.0, child: Text('a')), child: SizedBox(height: 400.0, child: Text('a')),
...@@ -275,11 +287,14 @@ void main() { ...@@ -275,11 +287,14 @@ void main() {
expect(find.byType(Viewport), paints..clipRect()); expect(find.byType(Viewport), paints..clipRect());
final ViewportOffset offset3 = ViewportOffset.fixed(100.0);
addTearDown(offset3.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: Viewport( child: Viewport(
offset: ViewportOffset.fixed(100.0), offset: offset3,
slivers: const <Widget>[ slivers: const <Widget>[
SliverToBoxAdapter( SliverToBoxAdapter(
child: SizedBox(height: 4000.0, child: Text('a')), child: SizedBox(height: 4000.0, child: Text('a')),
...@@ -291,11 +306,14 @@ void main() { ...@@ -291,11 +306,14 @@ void main() {
expect(find.byType(Viewport), paints..clipRect()); expect(find.byType(Viewport), paints..clipRect());
final ViewportOffset offset4 = ViewportOffset.zero();
addTearDown(offset4.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: Viewport( child: Viewport(
offset: ViewportOffset.zero(), offset: offset4,
slivers: const <Widget>[ slivers: const <Widget>[
SliverToBoxAdapter( SliverToBoxAdapter(
child: SizedBox(height: 4000.0, child: Text('a')), child: SizedBox(height: 4000.0, child: Text('a')),
...@@ -308,12 +326,15 @@ void main() { ...@@ -308,12 +326,15 @@ void main() {
expect(find.byType(Viewport), paints..clipRect()); expect(find.byType(Viewport), paints..clipRect());
}); });
testWidgets('Viewport overflow clipping of SliverBlock', (WidgetTester tester) async { testWidgetsWithLeakTracking('Viewport overflow clipping of SliverBlock', (WidgetTester tester) async {
final ViewportOffset offset1 = ViewportOffset.zero();
addTearDown(offset1.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: Viewport( child: Viewport(
offset: ViewportOffset.zero(), offset: offset1,
slivers: <Widget>[ slivers: <Widget>[
SliverList( SliverList(
delegate: SliverChildListDelegate(const <Widget>[ delegate: SliverChildListDelegate(const <Widget>[
...@@ -327,11 +348,14 @@ void main() { ...@@ -327,11 +348,14 @@ void main() {
expect(find.byType(Viewport), isNot(paints..clipRect())); expect(find.byType(Viewport), isNot(paints..clipRect()));
final ViewportOffset offset2 = ViewportOffset.fixed(100.0);
addTearDown(offset2.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: Viewport( child: Viewport(
offset: ViewportOffset.fixed(100.0), offset: offset2,
slivers: <Widget>[ slivers: <Widget>[
SliverList( SliverList(
delegate: SliverChildListDelegate(const <Widget>[ delegate: SliverChildListDelegate(const <Widget>[
...@@ -345,11 +369,14 @@ void main() { ...@@ -345,11 +369,14 @@ void main() {
expect(find.byType(Viewport), paints..clipRect()); expect(find.byType(Viewport), paints..clipRect());
final ViewportOffset offset3 = ViewportOffset.fixed(100.0);
addTearDown(offset3.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: Viewport( child: Viewport(
offset: ViewportOffset.fixed(100.0), offset: offset3,
slivers: <Widget>[ slivers: <Widget>[
SliverList( SliverList(
delegate: SliverChildListDelegate(const <Widget>[ delegate: SliverChildListDelegate(const <Widget>[
...@@ -363,11 +390,14 @@ void main() { ...@@ -363,11 +390,14 @@ void main() {
expect(find.byType(Viewport), paints..clipRect()); expect(find.byType(Viewport), paints..clipRect());
final ViewportOffset offset4 = ViewportOffset.zero();
addTearDown(offset4.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: Viewport( child: Viewport(
offset: ViewportOffset.zero(), offset: offset4,
slivers: <Widget>[ slivers: <Widget>[
SliverList( SliverList(
delegate: SliverChildListDelegate(const <Widget>[ delegate: SliverChildListDelegate(const <Widget>[
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
class TestSliverPersistentHeaderDelegate extends SliverPersistentHeaderDelegate { class TestSliverPersistentHeaderDelegate extends SliverPersistentHeaderDelegate {
TestSliverPersistentHeaderDelegate(this._maxExtent); TestSliverPersistentHeaderDelegate(this._maxExtent);
...@@ -57,7 +58,7 @@ class TestScrollPhysics extends ClampingScrollPhysics { ...@@ -57,7 +58,7 @@ class TestScrollPhysics extends ClampingScrollPhysics {
} }
void main() { void main() {
testWidgets('Evil test of sliver features - 1', (WidgetTester tester) async { testWidgetsWithLeakTracking('Evil test of sliver features - 1', (WidgetTester tester) async {
final GlobalKey centerKey = GlobalKey(); final GlobalKey centerKey = GlobalKey();
await tester.pumpWidget( await tester.pumpWidget(
MediaQuery( MediaQuery(
...@@ -184,7 +185,7 @@ void main() { ...@@ -184,7 +185,7 @@ void main() {
}); });
testWidgets('Removing offscreen items above and rescrolling does not crash', (WidgetTester tester) async { testWidgetsWithLeakTracking('Removing offscreen items above and rescrolling does not crash', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
home: CustomScrollView( home: CustomScrollView(
cacheExtent: 0.0, cacheExtent: 0.0,
......
...@@ -4,9 +4,10 @@ ...@@ -4,9 +4,10 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() { void main() {
testWidgets('Sliver with keep alive without key - should dispose after reordering', (WidgetTester tester) async { testWidgetsWithLeakTracking('Sliver with keep alive without key - should dispose after reordering', (WidgetTester tester) async {
List<Widget> childList= <Widget>[ List<Widget> childList= <Widget>[
const WidgetTest0(text: 'child 0', keepAlive: true), const WidgetTest0(text: 'child 0', keepAlive: true),
const WidgetTest1(text: 'child 1', keepAlive: true), const WidgetTest1(text: 'child 1', keepAlive: true),
...@@ -29,7 +30,7 @@ void main() { ...@@ -29,7 +30,7 @@ void main() {
expect(state2.hasBeenDisposed, false); expect(state2.hasBeenDisposed, false);
}); });
testWidgets('Sliver without keep alive without key - should dispose after reordering', (WidgetTester tester) async { testWidgetsWithLeakTracking('Sliver without keep alive without key - should dispose after reordering', (WidgetTester tester) async {
List<Widget> childList= <Widget>[ List<Widget> childList= <Widget>[
const WidgetTest0(text: 'child 0'), const WidgetTest0(text: 'child 0'),
const WidgetTest1(text: 'child 1'), const WidgetTest1(text: 'child 1'),
...@@ -52,7 +53,7 @@ void main() { ...@@ -52,7 +53,7 @@ void main() {
expect(state2.hasBeenDisposed, false); expect(state2.hasBeenDisposed, false);
}); });
testWidgets('Sliver without keep alive with key - should dispose after reordering', (WidgetTester tester) async { testWidgetsWithLeakTracking('Sliver without keep alive with key - should dispose after reordering', (WidgetTester tester) async {
List<Widget> childList= <Widget>[ List<Widget> childList= <Widget>[
WidgetTest0(text: 'child 0', key: GlobalKey()), WidgetTest0(text: 'child 0', key: GlobalKey()),
WidgetTest1(text: 'child 1', key: GlobalKey()), WidgetTest1(text: 'child 1', key: GlobalKey()),
...@@ -75,7 +76,7 @@ void main() { ...@@ -75,7 +76,7 @@ void main() {
expect(state2.hasBeenDisposed, false); expect(state2.hasBeenDisposed, false);
}); });
testWidgets('Sliver with keep alive with key - should not dispose after reordering', (WidgetTester tester) async { testWidgetsWithLeakTracking('Sliver with keep alive with key - should not dispose after reordering', (WidgetTester tester) async {
List<Widget> childList= <Widget>[ List<Widget> childList= <Widget>[
WidgetTest0(text: 'child 0', key: GlobalKey(), keepAlive: true), WidgetTest0(text: 'child 0', key: GlobalKey(), keepAlive: true),
WidgetTest1(text: 'child 1', key: GlobalKey(), keepAlive: true), WidgetTest1(text: 'child 1', key: GlobalKey(), keepAlive: true),
...@@ -97,7 +98,7 @@ void main() { ...@@ -97,7 +98,7 @@ void main() {
expect(state2.hasBeenDisposed, false); expect(state2.hasBeenDisposed, false);
}); });
testWidgets('Sliver with keep alive with Unique key - should not dispose after reordering', (WidgetTester tester) async { testWidgetsWithLeakTracking('Sliver with keep alive with Unique key - should not dispose after reordering', (WidgetTester tester) async {
List<Widget> childList= <Widget>[ List<Widget> childList= <Widget>[
WidgetTest0(text: 'child 0', key: UniqueKey(), keepAlive: true), WidgetTest0(text: 'child 0', key: UniqueKey(), keepAlive: true),
WidgetTest1(text: 'child 1', key: UniqueKey(), keepAlive: true), WidgetTest1(text: 'child 1', key: UniqueKey(), keepAlive: true),
...@@ -119,7 +120,7 @@ void main() { ...@@ -119,7 +120,7 @@ void main() {
expect(state2.hasBeenDisposed, false); expect(state2.hasBeenDisposed, false);
}); });
testWidgets('Sliver with keep alive with Value key - should not dispose after reordering', (WidgetTester tester) async { testWidgetsWithLeakTracking('Sliver with keep alive with Value key - should not dispose after reordering', (WidgetTester tester) async {
List<Widget> childList= <Widget>[ List<Widget> childList= <Widget>[
const WidgetTest0(text: 'child 0', key: ValueKey<int>(0), keepAlive: true), const WidgetTest0(text: 'child 0', key: ValueKey<int>(0), keepAlive: true),
const WidgetTest1(text: 'child 1', key: ValueKey<int>(1), keepAlive: true), const WidgetTest1(text: 'child 1', key: ValueKey<int>(1), keepAlive: true),
...@@ -141,7 +142,7 @@ void main() { ...@@ -141,7 +142,7 @@ void main() {
expect(state2.hasBeenDisposed, false); expect(state2.hasBeenDisposed, false);
}); });
testWidgets('Sliver complex case 1', (WidgetTester tester) async { testWidgetsWithLeakTracking('Sliver complex case 1', (WidgetTester tester) async {
List<Widget> childList= <Widget>[ List<Widget> childList= <Widget>[
WidgetTest0(text: 'child 0', key: GlobalKey(), keepAlive: true), WidgetTest0(text: 'child 0', key: GlobalKey(), keepAlive: true),
WidgetTest1(text: 'child 1', key: GlobalKey(), keepAlive: true), WidgetTest1(text: 'child 1', key: GlobalKey(), keepAlive: true),
...@@ -185,7 +186,7 @@ void main() { ...@@ -185,7 +186,7 @@ void main() {
expect(state2.hasBeenDisposed, true); expect(state2.hasBeenDisposed, true);
}); });
testWidgets('Sliver complex case 2', (WidgetTester tester) async { testWidgetsWithLeakTracking('Sliver complex case 2', (WidgetTester tester) async {
List<Widget> childList= <Widget>[ List<Widget> childList= <Widget>[
WidgetTest0(text: 'child 0', key: GlobalKey(), keepAlive: true), WidgetTest0(text: 'child 0', key: GlobalKey(), keepAlive: true),
WidgetTest1(text: 'child 1', key: UniqueKey()), WidgetTest1(text: 'child 1', key: UniqueKey()),
...@@ -228,7 +229,7 @@ void main() { ...@@ -228,7 +229,7 @@ void main() {
expect(state2.hasBeenDisposed, true); expect(state2.hasBeenDisposed, true);
}); });
testWidgets('Sliver with SliverChildBuilderDelegate', (WidgetTester tester) async { testWidgetsWithLeakTracking('Sliver with SliverChildBuilderDelegate', (WidgetTester tester) async {
List<Widget> childList= <Widget>[ List<Widget> childList= <Widget>[
WidgetTest0(text: 'child 0', key: UniqueKey(), keepAlive: true), WidgetTest0(text: 'child 0', key: UniqueKey(), keepAlive: true),
WidgetTest1(text: 'child 1', key: GlobalKey()), WidgetTest1(text: 'child 1', key: GlobalKey()),
...@@ -271,7 +272,7 @@ void main() { ...@@ -271,7 +272,7 @@ void main() {
expect(state2.hasBeenDisposed, true); expect(state2.hasBeenDisposed, true);
}); });
testWidgets('SliverFillViewport should not dispose widget with key during in screen reordering', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverFillViewport should not dispose widget with key during in screen reordering', (WidgetTester tester) async {
List<Widget> childList= <Widget>[ List<Widget> childList= <Widget>[
WidgetTest0(text: 'child 0', key: UniqueKey(), keepAlive: true), WidgetTest0(text: 'child 0', key: UniqueKey(), keepAlive: true),
WidgetTest1(text: 'child 1', key: UniqueKey()), WidgetTest1(text: 'child 1', key: UniqueKey()),
...@@ -312,7 +313,7 @@ void main() { ...@@ -312,7 +313,7 @@ void main() {
expect(state2.hasBeenDisposed, true); expect(state2.hasBeenDisposed, true);
}); });
testWidgets('SliverList should not dispose widget with key during in screen reordering', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverList should not dispose widget with key during in screen reordering', (WidgetTester tester) async {
List<Widget> childList= <Widget>[ List<Widget> childList= <Widget>[
WidgetTest0(text: 'child 0', key: UniqueKey(), keepAlive: true), WidgetTest0(text: 'child 0', key: UniqueKey(), keepAlive: true),
const WidgetTest1(text: 'child 1', keepAlive: true), const WidgetTest1(text: 'child 1', keepAlive: true),
...@@ -362,7 +363,7 @@ void main() { ...@@ -362,7 +363,7 @@ void main() {
expect(state2.hasBeenDisposed, false); expect(state2.hasBeenDisposed, false);
}); });
testWidgets('SliverList remove child from child list', (WidgetTester tester) async { testWidgetsWithLeakTracking('SliverList remove child from child list', (WidgetTester tester) async {
List<Widget> childList= <Widget>[ List<Widget> childList= <Widget>[
WidgetTest0(text: 'child 0', key: UniqueKey(), keepAlive: true), WidgetTest0(text: 'child 0', key: UniqueKey(), keepAlive: true),
const WidgetTest1(text: 'child 1', keepAlive: true), const WidgetTest1(text: 'child 1', keepAlive: true),
......
...@@ -7,6 +7,7 @@ import 'dart:math' as math; ...@@ -7,6 +7,7 @@ import 'dart:math' as math;
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void verifyPaintPosition(GlobalKey key, Offset ideal) { void verifyPaintPosition(GlobalKey key, Offset ideal) {
final RenderObject target = key.currentContext!.findRenderObject()!; final RenderObject target = key.currentContext!.findRenderObject()!;
...@@ -17,7 +18,7 @@ void verifyPaintPosition(GlobalKey key, Offset ideal) { ...@@ -17,7 +18,7 @@ void verifyPaintPosition(GlobalKey key, Offset ideal) {
} }
void main() { void main() {
testWidgets('Sliver protocol', (WidgetTester tester) async { testWidgetsWithLeakTracking('Sliver protocol', (WidgetTester tester) async {
GlobalKey key1, key2, key3, key4, key5; GlobalKey key1, key2, key3, key4, key5;
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
......
...@@ -7,12 +7,13 @@ import 'package:flutter/material.dart'; ...@@ -7,12 +7,13 @@ import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
const Color green = Color(0xFF00FF00); const Color green = Color(0xFF00FF00);
const Color yellow = Color(0xFFFFFF00); const Color yellow = Color(0xFFFFFF00);
void main() { void main() {
testWidgets('SlottedRenderObjectWidget test', (WidgetTester tester) async { testWidgetsWithLeakTracking('SlottedRenderObjectWidget test', (WidgetTester tester) async {
await tester.pumpWidget(buildWidget( await tester.pumpWidget(buildWidget(
topLeft: Container( topLeft: Container(
height: 100, height: 100,
...@@ -137,7 +138,7 @@ void main() { ...@@ -137,7 +138,7 @@ void main() {
expect(_RenderTest().publicNameForSlot(slot), slot.toString()); expect(_RenderTest().publicNameForSlot(slot), slot.toString());
}); });
testWidgets('key reparenting', (WidgetTester tester) async { testWidgetsWithLeakTracking('key reparenting', (WidgetTester tester) async {
const Widget widget1 = SizedBox(key: ValueKey<String>('smol'), height: 10, width: 10); const Widget widget1 = SizedBox(key: ValueKey<String>('smol'), height: 10, width: 10);
const Widget widget2 = SizedBox(key: ValueKey<String>('big'), height: 100, width: 100); const Widget widget2 = SizedBox(key: ValueKey<String>('big'), height: 100, width: 100);
const Widget nullWidget = SizedBox(key: ValueKey<String>('null'), height: 50, width: 50); const Widget nullWidget = SizedBox(key: ValueKey<String>('null'), height: 50, width: 50);
...@@ -203,7 +204,7 @@ void main() { ...@@ -203,7 +204,7 @@ void main() {
)); ));
}); });
testWidgets('debugDescribeChildren', (WidgetTester tester) async { testWidgetsWithLeakTracking('debugDescribeChildren', (WidgetTester tester) async {
await tester.pumpWidget(buildWidget( await tester.pumpWidget(buildWidget(
topLeft: const SizedBox( topLeft: const SizedBox(
height: 100, height: 100,
......
...@@ -13,11 +13,14 @@ import 'package:flutter/foundation.dart'; ...@@ -13,11 +13,14 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() { void main() {
testWidgets('SnapshotWidget can rasterize child', (WidgetTester tester) async { testWidgetsWithLeakTracking('SnapshotWidget can rasterize child', (WidgetTester tester) async {
final SnapshotController controller = SnapshotController(allowSnapshotting: true); final SnapshotController controller = SnapshotController(allowSnapshotting: true);
addTearDown(controller.dispose);
final Key key = UniqueKey(); final Key key = UniqueKey();
await tester.pumpWidget(RepaintBoundary( await tester.pumpWidget(RepaintBoundary(
key: key, key: key,
child: TestDependencies( child: TestDependencies(
...@@ -56,9 +59,11 @@ void main() { ...@@ -56,9 +59,11 @@ void main() {
await expectLater(find.byKey(key), matchesGoldenFile('raster_widget.red.png')); await expectLater(find.byKey(key), matchesGoldenFile('raster_widget.red.png'));
}, skip: kIsWeb); // TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689 }, skip: kIsWeb); // TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
testWidgets('Changing devicePixelRatio does not repaint if snapshotting is not enabled', (WidgetTester tester) async { testWidgetsWithLeakTracking('Changing devicePixelRatio does not repaint if snapshotting is not enabled', (WidgetTester tester) async {
final SnapshotController controller = SnapshotController(); final SnapshotController controller = SnapshotController();
addTearDown(controller.dispose);
final TestPainter painter = TestPainter(); final TestPainter painter = TestPainter();
addTearDown(painter.dispose);
double devicePixelRatio = 1.0; double devicePixelRatio = 1.0;
late StateSetter localSetState; late StateSetter localSetState;
...@@ -89,9 +94,11 @@ void main() { ...@@ -89,9 +94,11 @@ void main() {
expect(painter.count, 1); expect(painter.count, 1);
}, skip: kIsWeb); // TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689 }, skip: kIsWeb); // TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
testWidgets('Changing devicePixelRatio forces raster regeneration', (WidgetTester tester) async { testWidgetsWithLeakTracking('Changing devicePixelRatio forces raster regeneration', (WidgetTester tester) async {
final SnapshotController controller = SnapshotController(allowSnapshotting: true); final SnapshotController controller = SnapshotController(allowSnapshotting: true);
addTearDown(controller.dispose);
final TestPainter painter = TestPainter(); final TestPainter painter = TestPainter();
addTearDown(painter.dispose);
double devicePixelRatio = 1.0; double devicePixelRatio = 1.0;
late StateSetter localSetState; late StateSetter localSetState;
...@@ -126,8 +133,10 @@ void main() { ...@@ -126,8 +133,10 @@ void main() {
expect(raster, isNot(newRaster)); expect(raster, isNot(newRaster));
}, skip: kIsWeb); // TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689 }, skip: kIsWeb); // TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
testWidgets('SnapshotWidget paints its child as a single picture layer', (WidgetTester tester) async { testWidgetsWithLeakTracking('SnapshotWidget paints its child as a single picture layer', (WidgetTester tester) async {
final SnapshotController controller = SnapshotController(allowSnapshotting: true); final SnapshotController controller = SnapshotController(allowSnapshotting: true);
addTearDown(controller.dispose);
await tester.pumpWidget(RepaintBoundary( await tester.pumpWidget(RepaintBoundary(
child: Center( child: Center(
child: TestDependencies( child: TestDependencies(
...@@ -153,14 +162,21 @@ void main() { ...@@ -153,14 +162,21 @@ void main() {
expect(tester.layers.last, isA<PictureLayer>()); expect(tester.layers.last, isA<PictureLayer>());
}, skip: kIsWeb); // TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689 }, skip: kIsWeb); // TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
testWidgets('SnapshotWidget can update the painter type', (WidgetTester tester) async { testWidgetsWithLeakTracking('SnapshotWidget can update the painter type', (WidgetTester tester) async {
final SnapshotController controller = SnapshotController(allowSnapshotting: true); final SnapshotController controller = SnapshotController(allowSnapshotting: true);
addTearDown(controller.dispose);
final TestPainter painter1 = TestPainter();
addTearDown(painter1.dispose);
final TestPainter2 painter2 = TestPainter2();
addTearDown(painter2.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Center( Center(
child: TestDependencies( child: TestDependencies(
child: SnapshotWidget( child: SnapshotWidget(
controller: controller, controller: controller,
painter: TestPainter(), painter: painter1,
child: const SizedBox(), child: const SizedBox(),
), ),
), ),
...@@ -172,7 +188,7 @@ void main() { ...@@ -172,7 +188,7 @@ void main() {
child: TestDependencies( child: TestDependencies(
child: SnapshotWidget( child: SnapshotWidget(
controller: controller, controller: controller,
painter: TestPainter2(), painter: painter2,
child: const SizedBox(), child: const SizedBox(),
), ),
), ),
...@@ -182,8 +198,10 @@ void main() { ...@@ -182,8 +198,10 @@ void main() {
expect(tester.takeException(), isNull); expect(tester.takeException(), isNull);
}, skip: kIsWeb); // TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689 }, skip: kIsWeb); // TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
testWidgets('RenderSnapshotWidget does not error on rasterization of child with empty size', (WidgetTester tester) async { testWidgetsWithLeakTracking('RenderSnapshotWidget does not error on rasterization of child with empty size', (WidgetTester tester) async {
final SnapshotController controller = SnapshotController(allowSnapshotting: true); final SnapshotController controller = SnapshotController(allowSnapshotting: true);
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Center( Center(
child: TestDependencies( child: TestDependencies(
...@@ -201,6 +219,8 @@ void main() { ...@@ -201,6 +219,8 @@ void main() {
testWidgets('RenderSnapshotWidget throws assertion if platform view is encountered', (WidgetTester tester) async { testWidgets('RenderSnapshotWidget throws assertion if platform view is encountered', (WidgetTester tester) async {
final SnapshotController controller = SnapshotController(allowSnapshotting: true); final SnapshotController controller = SnapshotController(allowSnapshotting: true);
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Center( Center(
child: TestDependencies( child: TestDependencies(
...@@ -220,8 +240,10 @@ void main() { ...@@ -220,8 +240,10 @@ void main() {
.having((FlutterError error) => error.message, 'message', contains('SnapshotWidget used with a child that contains a PlatformView'))); .having((FlutterError error) => error.message, 'message', contains('SnapshotWidget used with a child that contains a PlatformView')));
}, skip: kIsWeb); // TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689 }, skip: kIsWeb); // TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
testWidgets('RenderSnapshotWidget does not assert if SnapshotMode.forced', (WidgetTester tester) async { testWidgetsWithLeakTracking('RenderSnapshotWidget does not assert if SnapshotMode.forced', (WidgetTester tester) async {
final SnapshotController controller = SnapshotController(allowSnapshotting: true); final SnapshotController controller = SnapshotController(allowSnapshotting: true);
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Center( Center(
child: TestDependencies( child: TestDependencies(
...@@ -241,8 +263,10 @@ void main() { ...@@ -241,8 +263,10 @@ void main() {
expect(tester.takeException(), isNull); expect(tester.takeException(), isNull);
}, skip: kIsWeb); // TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689 }, skip: kIsWeb); // TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
testWidgets('RenderSnapshotWidget does not take a snapshot if a platform view is encountered with SnapshotMode.permissive', (WidgetTester tester) async { testWidgetsWithLeakTracking('RenderSnapshotWidget does not take a snapshot if a platform view is encountered with SnapshotMode.permissive', (WidgetTester tester) async {
final SnapshotController controller = SnapshotController(allowSnapshotting: true); final SnapshotController controller = SnapshotController(allowSnapshotting: true);
addTearDown(controller.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Center( Center(
child: TestDependencies( child: TestDependencies(
...@@ -261,9 +285,15 @@ void main() { ...@@ -261,9 +285,15 @@ void main() {
expect(tester.takeException(), isNull); expect(tester.takeException(), isNull);
expect(tester.layers.last, isA<PlatformViewLayer>()); expect(tester.layers.last, isA<PlatformViewLayer>());
}, skip: kIsWeb); // TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689 },
skip: kIsWeb, // TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
leakTrackingTestConfig: const LeakTrackingTestConfig(
// TODO(ksokolovskyi): remove after fixing
// https://github.com/flutter/flutter/issues/135141
allowAllNotDisposed: true,
));
testWidgets('SnapshotWidget should have same result when enabled', (WidgetTester tester) async { testWidgetsWithLeakTracking('SnapshotWidget should have same result when enabled', (WidgetTester tester) async {
addTearDown(tester.view.reset); addTearDown(tester.view.reset);
tester.view tester.view
...@@ -272,6 +302,8 @@ void main() { ...@@ -272,6 +302,8 @@ void main() {
const ValueKey<String> repaintBoundaryKey = ValueKey<String>('boundary'); const ValueKey<String> repaintBoundaryKey = ValueKey<String>('boundary');
final SnapshotController controller = SnapshotController(); final SnapshotController controller = SnapshotController();
addTearDown(controller.dispose);
await tester.pumpWidget(RepaintBoundary( await tester.pumpWidget(RepaintBoundary(
key: repaintBoundaryKey, key: repaintBoundaryKey,
child: MaterialApp( child: MaterialApp(
...@@ -291,12 +323,19 @@ void main() { ...@@ -291,12 +323,19 @@ void main() {
)); ));
final ui.Image imageWhenDisabled = (tester.renderObject(find.byKey(repaintBoundaryKey)) as RenderRepaintBoundary).toImageSync(); final ui.Image imageWhenDisabled = (tester.renderObject(find.byKey(repaintBoundaryKey)) as RenderRepaintBoundary).toImageSync();
addTearDown(imageWhenDisabled.dispose);
controller.allowSnapshotting = true; controller.allowSnapshotting = true;
await tester.pump(); await tester.pump();
await expectLater(find.byKey(repaintBoundaryKey), matchesReferenceImage(imageWhenDisabled)); await expectLater(find.byKey(repaintBoundaryKey), matchesReferenceImage(imageWhenDisabled));
}, skip: kIsWeb); // TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689 },
skip: kIsWeb, // TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
leakTrackingTestConfig: const LeakTrackingTestConfig(
// TODO(ksokolovskyi): remove after fixing
// https://github.com/flutter/flutter/issues/135137
notDisposedAllowList: <String, int> {'Image': 1},
));
} }
class TestPlatformView extends SingleChildRenderObjectWidget { class TestPlatformView extends SingleChildRenderObjectWidget {
......
...@@ -4,9 +4,10 @@ ...@@ -4,9 +4,10 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() { void main() {
testWidgets('Spacer takes up space.', (WidgetTester tester) async { testWidgetsWithLeakTracking('Spacer takes up space.', (WidgetTester tester) async {
await tester.pumpWidget(const Column( await tester.pumpWidget(const Column(
children: <Widget>[ children: <Widget>[
SizedBox(width: 10.0, height: 10.0), SizedBox(width: 10.0, height: 10.0),
...@@ -19,7 +20,7 @@ void main() { ...@@ -19,7 +20,7 @@ void main() {
expect(spacerRect.topLeft, const Offset(400.0, 10.0)); expect(spacerRect.topLeft, const Offset(400.0, 10.0));
}); });
testWidgets('Spacer takes up space proportional to flex.', (WidgetTester tester) async { testWidgetsWithLeakTracking('Spacer takes up space proportional to flex.', (WidgetTester tester) async {
const Spacer spacer1 = Spacer(); const Spacer spacer1 = Spacer();
const Spacer spacer2 = Spacer(); const Spacer spacer2 = Spacer();
const Spacer spacer3 = Spacer(flex: 2); const Spacer spacer3 = Spacer(flex: 2);
...@@ -53,7 +54,7 @@ void main() { ...@@ -53,7 +54,7 @@ void main() {
expect(spacer4Rect.left, moreOrLessEquals(10.0, epsilon: 0.1)); expect(spacer4Rect.left, moreOrLessEquals(10.0, epsilon: 0.1));
}); });
testWidgets('Spacer takes up space.', (WidgetTester tester) async { testWidgetsWithLeakTracking('Spacer takes up space.', (WidgetTester tester) async {
await tester.pumpWidget(const UnconstrainedBox( await tester.pumpWidget(const UnconstrainedBox(
constrainedAxis: Axis.vertical, constrainedAxis: Axis.vertical,
child: Column( child: Column(
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
late TextStyle composingStyle; late TextStyle composingStyle;
late TextStyle misspelledTextStyle; late TextStyle misspelledTextStyle;
...@@ -17,7 +18,7 @@ void main() { ...@@ -17,7 +18,7 @@ void main() {
misspelledTextStyle = TextField.materialMisspelledTextStyle; misspelledTextStyle = TextField.materialMisspelledTextStyle;
}); });
testWidgets( testWidgetsWithLeakTracking(
'buildTextSpanWithSpellCheckSuggestions ignores composing region when composing region out of range', 'buildTextSpanWithSpellCheckSuggestions ignores composing region when composing region out of range',
(WidgetTester tester) async { (WidgetTester tester) async {
const String text = 'Hello, wrold! Hey'; const String text = 'Hello, wrold! Hey';
...@@ -46,7 +47,7 @@ void main() { ...@@ -46,7 +47,7 @@ void main() {
expect(textSpanTree, equals(expectedTextSpanTree)); expect(textSpanTree, equals(expectedTextSpanTree));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.iOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.iOS }));
testWidgets( testWidgetsWithLeakTracking(
'buildTextSpanWithSpellCheckSuggestions, isolated misspelled word with separate composing region example', 'buildTextSpanWithSpellCheckSuggestions, isolated misspelled word with separate composing region example',
(WidgetTester tester) async { (WidgetTester tester) async {
const String text = 'Hello, wrold! Hey'; const String text = 'Hello, wrold! Hey';
...@@ -77,7 +78,7 @@ void main() { ...@@ -77,7 +78,7 @@ void main() {
expect(textSpanTree, equals(expectedTextSpanTree)); expect(textSpanTree, equals(expectedTextSpanTree));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android }));
testWidgets( testWidgetsWithLeakTracking(
'buildTextSpanWithSpellCheckSuggestions, composing region and misspelled words overlap example', 'buildTextSpanWithSpellCheckSuggestions, composing region and misspelled words overlap example',
(WidgetTester tester) async { (WidgetTester tester) async {
const String text = 'Right worng worng right'; const String text = 'Right worng worng right';
...@@ -111,7 +112,7 @@ void main() { ...@@ -111,7 +112,7 @@ void main() {
expect(textSpanTree, equals(expectedTextSpanTree)); expect(textSpanTree, equals(expectedTextSpanTree));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android }));
testWidgets( testWidgetsWithLeakTracking(
'buildTextSpanWithSpellCheckSuggestions, consecutive misspelled words example', 'buildTextSpanWithSpellCheckSuggestions, consecutive misspelled words example',
(WidgetTester tester) async { (WidgetTester tester) async {
const String text = 'Right worng worng right'; const String text = 'Right worng worng right';
...@@ -144,7 +145,7 @@ void main() { ...@@ -144,7 +145,7 @@ void main() {
expect(textSpanTree, equals(expectedTextSpanTree)); expect(textSpanTree, equals(expectedTextSpanTree));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.iOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.iOS }));
testWidgets( testWidgetsWithLeakTracking(
'buildTextSpanWithSpellCheckSuggestions corrects results when they lag, results text shorter than actual text example', 'buildTextSpanWithSpellCheckSuggestions corrects results when they lag, results text shorter than actual text example',
(WidgetTester tester) async { (WidgetTester tester) async {
const String text = 'Hello, wrold! Hey'; const String text = 'Hello, wrold! Hey';
...@@ -174,7 +175,7 @@ void main() { ...@@ -174,7 +175,7 @@ void main() {
expect(textSpanTree, equals(expectedTextSpanTree)); expect(textSpanTree, equals(expectedTextSpanTree));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.iOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.iOS }));
testWidgets( testWidgetsWithLeakTracking(
'buildTextSpanWithSpellCheckSuggestions corrects results when they lag, results text longer with more misspelled words than actual text example', 'buildTextSpanWithSpellCheckSuggestions corrects results when they lag, results text longer with more misspelled words than actual text example',
(WidgetTester tester) async { (WidgetTester tester) async {
const String text = 'Hello, wrold! Hey'; const String text = 'Hello, wrold! Hey';
...@@ -206,7 +207,7 @@ void main() { ...@@ -206,7 +207,7 @@ void main() {
expect(textSpanTree, equals(expectedTextSpanTree)); expect(textSpanTree, equals(expectedTextSpanTree));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.iOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.iOS }));
testWidgets( testWidgetsWithLeakTracking(
'buildTextSpanWithSpellCheckSuggestions corrects results when they lag, results text mismatched example', 'buildTextSpanWithSpellCheckSuggestions corrects results when they lag, results text mismatched example',
(WidgetTester tester) async { (WidgetTester tester) async {
const String text = 'Hello, wrold! Hey'; const String text = 'Hello, wrold! Hey';
...@@ -233,7 +234,7 @@ void main() { ...@@ -233,7 +234,7 @@ void main() {
expect(textSpanTree, equals(expectedTextSpanTree)); expect(textSpanTree, equals(expectedTextSpanTree));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.iOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.iOS }));
testWidgets( testWidgetsWithLeakTracking(
'buildTextSpanWithSpellCheckSuggestions corrects results when they lag, results shifted forward example', 'buildTextSpanWithSpellCheckSuggestions corrects results when they lag, results shifted forward example',
(WidgetTester tester) async { (WidgetTester tester) async {
const String text = 'Hello, there wrold! Hey'; const String text = 'Hello, there wrold! Hey';
...@@ -263,7 +264,7 @@ void main() { ...@@ -263,7 +264,7 @@ void main() {
expect(textSpanTree, equals(expectedTextSpanTree)); expect(textSpanTree, equals(expectedTextSpanTree));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.iOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.iOS }));
testWidgets( testWidgetsWithLeakTracking(
'buildTextSpanWithSpellCheckSuggestions corrects results when they lag, results shifted backwards example', 'buildTextSpanWithSpellCheckSuggestions corrects results when they lag, results shifted backwards example',
(WidgetTester tester) async { (WidgetTester tester) async {
const String text = 'Hello, wrold! Hey'; const String text = 'Hello, wrold! Hey';
...@@ -293,7 +294,7 @@ void main() { ...@@ -293,7 +294,7 @@ void main() {
expect(textSpanTree, equals(expectedTextSpanTree)); expect(textSpanTree, equals(expectedTextSpanTree));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.iOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.iOS }));
testWidgets( testWidgetsWithLeakTracking(
'buildTextSpanWithSpellCheckSuggestions corrects results when they lag, results shifted backwards and forwards example', 'buildTextSpanWithSpellCheckSuggestions corrects results when they lag, results shifted backwards and forwards example',
(WidgetTester tester) async { (WidgetTester tester) async {
const String text = 'Hello, wrold! And Hye!'; const String text = 'Hello, wrold! And Hye!';
...@@ -326,7 +327,7 @@ void main() { ...@@ -326,7 +327,7 @@ void main() {
expect(textSpanTree, equals(expectedTextSpanTree)); expect(textSpanTree, equals(expectedTextSpanTree));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.iOS })); }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.iOS }));
testWidgets( testWidgetsWithLeakTracking(
'buildTextSpanWithSpellCheckSuggestions discards result when additions are made to misspelled word example', 'buildTextSpanWithSpellCheckSuggestions discards result when additions are made to misspelled word example',
(WidgetTester tester) async { (WidgetTester tester) async {
const String text = 'Hello, wroldd!'; const String text = 'Hello, wroldd!';
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import '../rendering/rendering_tester.dart' show TestCallbackPainter; import '../rendering/rendering_tester.dart' show TestCallbackPainter;
...@@ -18,7 +19,7 @@ class TestPaintingContext implements PaintingContext { ...@@ -18,7 +19,7 @@ class TestPaintingContext implements PaintingContext {
} }
void main() { void main() {
testWidgets('Can construct an empty Stack', (WidgetTester tester) async { testWidgetsWithLeakTracking('Can construct an empty Stack', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const Directionality( const Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -27,7 +28,7 @@ void main() { ...@@ -27,7 +28,7 @@ void main() {
); );
}); });
testWidgets('Can construct an empty Centered Stack', (WidgetTester tester) async { testWidgetsWithLeakTracking('Can construct an empty Centered Stack', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const Directionality( const Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -36,7 +37,7 @@ void main() { ...@@ -36,7 +37,7 @@ void main() {
); );
}); });
testWidgets('Can change position data', (WidgetTester tester) async { testWidgetsWithLeakTracking('Can change position data', (WidgetTester tester) async {
const Key key = Key('container'); const Key key = Key('container');
await tester.pumpWidget( await tester.pumpWidget(
...@@ -93,7 +94,7 @@ void main() { ...@@ -93,7 +94,7 @@ void main() {
expect(parentData.height, isNull); expect(parentData.height, isNull);
}); });
testWidgets('Can remove parent data', (WidgetTester tester) async { testWidgetsWithLeakTracking('Can remove parent data', (WidgetTester tester) async {
const Key key = Key('container'); const Key key = Key('container');
const SizedBox sizedBox = SizedBox(key: key, width: 10.0, height: 10.0); const SizedBox sizedBox = SizedBox(key: key, width: 10.0, height: 10.0);
...@@ -131,7 +132,7 @@ void main() { ...@@ -131,7 +132,7 @@ void main() {
expect(parentData.height, isNull); expect(parentData.height, isNull);
}); });
testWidgets('Can align non-positioned children (LTR)', (WidgetTester tester) async { testWidgetsWithLeakTracking('Can align non-positioned children (LTR)', (WidgetTester tester) async {
const Key child0Key = Key('child0'); const Key child0Key = Key('child0');
const Key child1Key = Key('child1'); const Key child1Key = Key('child1');
...@@ -177,7 +178,7 @@ void main() { ...@@ -177,7 +178,7 @@ void main() {
expect(child1RenderObjectParentData.offset, equals(const Offset(10.0, 10.0))); expect(child1RenderObjectParentData.offset, equals(const Offset(10.0, 10.0)));
}); });
testWidgets('Can align non-positioned children (RTL)', (WidgetTester tester) async { testWidgetsWithLeakTracking('Can align non-positioned children (RTL)', (WidgetTester tester) async {
const Key child0Key = Key('child0'); const Key child0Key = Key('child0');
const Key child1Key = Key('child1'); const Key child1Key = Key('child1');
...@@ -223,7 +224,7 @@ void main() { ...@@ -223,7 +224,7 @@ void main() {
expect(child1RenderObjectParentData.offset, equals(const Offset(0.0, 10.0))); expect(child1RenderObjectParentData.offset, equals(const Offset(0.0, 10.0)));
}); });
testWidgets('Can construct an empty IndexedStack', (WidgetTester tester) async { testWidgetsWithLeakTracking('Can construct an empty IndexedStack', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const Directionality( const Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -232,7 +233,7 @@ void main() { ...@@ -232,7 +233,7 @@ void main() {
); );
}); });
testWidgets('Can construct an empty Centered IndexedStack', (WidgetTester tester) async { testWidgetsWithLeakTracking('Can construct an empty Centered IndexedStack', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const Directionality( const Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -241,7 +242,7 @@ void main() { ...@@ -241,7 +242,7 @@ void main() {
); );
}); });
testWidgets('Can construct an IndexedStack', (WidgetTester tester) async { testWidgetsWithLeakTracking('Can construct an IndexedStack', (WidgetTester tester) async {
const int itemCount = 3; const int itemCount = 3;
late List<int> itemsPainted; late List<int> itemsPainted;
...@@ -289,7 +290,7 @@ void main() { ...@@ -289,7 +290,7 @@ void main() {
expect(itemsPainted, equals(<int>[2])); expect(itemsPainted, equals(<int>[2]));
}); });
testWidgets('Can hit test an IndexedStack', (WidgetTester tester) async { testWidgetsWithLeakTracking('Can hit test an IndexedStack', (WidgetTester tester) async {
const Key key = Key('indexedStack'); const Key key = Key('indexedStack');
const int itemCount = 3; const int itemCount = 3;
late List<int> itemsTapped; late List<int> itemsTapped;
...@@ -320,7 +321,7 @@ void main() { ...@@ -320,7 +321,7 @@ void main() {
expect(itemsTapped, <int>[2]); expect(itemsTapped, <int>[2]);
}); });
testWidgets('IndexedStack sets non-selected indexes to visible=false', (WidgetTester tester) async { testWidgetsWithLeakTracking('IndexedStack sets non-selected indexes to visible=false', (WidgetTester tester) async {
Widget buildStack({required int itemCount, required int? selectedIndex}) { Widget buildStack({required int itemCount, required int? selectedIndex}) {
final List<Widget> children = List<Widget>.generate(itemCount, (int i) { final List<Widget> children = List<Widget>.generate(itemCount, (int i) {
return _ShowVisibility(index: i); return _ShowVisibility(index: i);
...@@ -355,7 +356,7 @@ void main() { ...@@ -355,7 +356,7 @@ void main() {
expect(find.text('index 2 is visible ? true', skipOffstage: false), findsOneWidget); expect(find.text('index 2 is visible ? true', skipOffstage: false), findsOneWidget);
}); });
testWidgets('Can set width and height', (WidgetTester tester) async { testWidgetsWithLeakTracking('Can set width and height', (WidgetTester tester) async {
const Key key = Key('container'); const Key key = Key('container');
const BoxDecoration kBoxDecoration = BoxDecoration( const BoxDecoration kBoxDecoration = BoxDecoration(
...@@ -423,7 +424,7 @@ void main() { ...@@ -423,7 +424,7 @@ void main() {
expect(renderBox.size.height, equals(12.0)); expect(renderBox.size.height, equals(12.0));
}); });
testWidgets('Can set and update clipBehavior', (WidgetTester tester) async { testWidgetsWithLeakTracking('Can set and update clipBehavior', (WidgetTester tester) async {
await tester.pumpWidget(const Stack(textDirection: TextDirection.ltr)); await tester.pumpWidget(const Stack(textDirection: TextDirection.ltr));
final RenderStack renderObject = tester.allRenderObjects.whereType<RenderStack>().first; final RenderStack renderObject = tester.allRenderObjects.whereType<RenderStack>().first;
expect(renderObject.clipBehavior, equals(Clip.hardEdge)); expect(renderObject.clipBehavior, equals(Clip.hardEdge));
...@@ -432,7 +433,7 @@ void main() { ...@@ -432,7 +433,7 @@ void main() {
expect(renderObject.clipBehavior, equals(Clip.hardEdge)); expect(renderObject.clipBehavior, equals(Clip.hardEdge));
}); });
testWidgets('Clip.none is respected by describeApproximateClip', (WidgetTester tester) async { testWidgetsWithLeakTracking('Clip.none is respected by describeApproximateClip', (WidgetTester tester) async {
await tester.pumpWidget(const Stack( await tester.pumpWidget(const Stack(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
children: <Widget>[Positioned(left: 1000, right: 2000, child: SizedBox(width: 2000, height: 2000))], children: <Widget>[Positioned(left: 1000, right: 2000, child: SizedBox(width: 2000, height: 2000))],
...@@ -455,7 +456,7 @@ void main() { ...@@ -455,7 +456,7 @@ void main() {
expect(visited, true); expect(visited, true);
}); });
testWidgets('IndexedStack with null index', (WidgetTester tester) async { testWidgetsWithLeakTracking('IndexedStack with null index', (WidgetTester tester) async {
bool? tapped; bool? tapped;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -485,7 +486,7 @@ void main() { ...@@ -485,7 +486,7 @@ void main() {
expect(tapped, isNull); expect(tapped, isNull);
}); });
testWidgets('IndexedStack reports hidden children as offstage', (WidgetTester tester) async { testWidgetsWithLeakTracking('IndexedStack reports hidden children as offstage', (WidgetTester tester) async {
final List<Widget> children = <Widget>[ final List<Widget> children = <Widget>[
for (int i = 0; i < 5; i++) Text('child $i'), for (int i = 0; i < 5; i++) Text('child $i'),
]; ];
...@@ -519,7 +520,7 @@ void main() { ...@@ -519,7 +520,7 @@ void main() {
} }
}); });
testWidgets('Stack clip test', (WidgetTester tester) async { testWidgetsWithLeakTracking('Stack clip test', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const Directionality( const Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -580,7 +581,7 @@ void main() { ...@@ -580,7 +581,7 @@ void main() {
expect(context.invocations.first.memberName, equals(#paintChild)); expect(context.invocations.first.memberName, equals(#paintChild));
}); });
testWidgets('Stack sizing: default', (WidgetTester tester) async { testWidgetsWithLeakTracking('Stack sizing: default', (WidgetTester tester) async {
final List<String> logs = <String>[]; final List<String> logs = <String>[];
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
...@@ -610,7 +611,7 @@ void main() { ...@@ -610,7 +611,7 @@ void main() {
expect(logs, <String>['BoxConstraints(0.0<=w<=3.0, 0.0<=h<=7.0)']); expect(logs, <String>['BoxConstraints(0.0<=w<=3.0, 0.0<=h<=7.0)']);
}); });
testWidgets('Stack sizing: explicit', (WidgetTester tester) async { testWidgetsWithLeakTracking('Stack sizing: explicit', (WidgetTester tester) async {
final List<String> logs = <String>[]; final List<String> logs = <String>[];
Widget buildStack(StackFit sizing) { Widget buildStack(StackFit sizing) {
return Directionality( return Directionality(
...@@ -652,7 +653,7 @@ void main() { ...@@ -652,7 +653,7 @@ void main() {
]); ]);
}); });
testWidgets('Positioned.directional control test', (WidgetTester tester) async { testWidgetsWithLeakTracking('Positioned.directional control test', (WidgetTester tester) async {
final Key key = UniqueKey(); final Key key = UniqueKey();
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
...@@ -689,7 +690,7 @@ void main() { ...@@ -689,7 +690,7 @@ void main() {
expect(tester.getTopLeft(find.byKey(key)), const Offset(50.0, 0.0)); expect(tester.getTopLeft(find.byKey(key)), const Offset(50.0, 0.0));
}); });
testWidgets('PositionedDirectional control test', (WidgetTester tester) async { testWidgetsWithLeakTracking('PositionedDirectional control test', (WidgetTester tester) async {
final Key key = UniqueKey(); final Key key = UniqueKey();
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
...@@ -724,7 +725,7 @@ void main() { ...@@ -724,7 +725,7 @@ void main() {
expect(tester.getTopLeft(find.byKey(key)), const Offset(50.0, 0.0)); expect(tester.getTopLeft(find.byKey(key)), const Offset(50.0, 0.0));
}); });
testWidgets('Can change the text direction of a Stack', (WidgetTester tester) async { testWidgetsWithLeakTracking('Can change the text direction of a Stack', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const Stack( const Stack(
alignment: Alignment.center, alignment: Alignment.center,
...@@ -742,7 +743,7 @@ void main() { ...@@ -742,7 +743,7 @@ void main() {
); );
}); });
testWidgets('Alignment with partially-positioned children', (WidgetTester tester) async { testWidgetsWithLeakTracking('Alignment with partially-positioned children', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const Directionality( const Directionality(
textDirection: TextDirection.rtl, textDirection: TextDirection.rtl,
...@@ -887,7 +888,7 @@ void main() { ...@@ -887,7 +888,7 @@ void main() {
)); ));
}); });
testWidgets('Can update clipBehavior of IndexedStack', testWidgetsWithLeakTracking('Can update clipBehavior of IndexedStack',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget(const IndexedStack(textDirection: TextDirection.ltr)); await tester.pumpWidget(const IndexedStack(textDirection: TextDirection.ltr));
final RenderIndexedStack renderObject = final RenderIndexedStack renderObject =
...@@ -905,7 +906,7 @@ void main() { ...@@ -905,7 +906,7 @@ void main() {
expect(renderIndexedObject.clipBehavior, equals(Clip.antiAlias)); expect(renderIndexedObject.clipBehavior, equals(Clip.antiAlias));
}); });
testWidgets('IndexedStack sizing: explicit', (WidgetTester tester) async { testWidgetsWithLeakTracking('IndexedStack sizing: explicit', (WidgetTester tester) async {
final List<String> logs = <String>[]; final List<String> logs = <String>[];
Widget buildIndexedStack(StackFit sizing) { Widget buildIndexedStack(StackFit sizing) {
return Directionality( return Directionality(
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
class Foo extends StatefulWidget { class Foo extends StatefulWidget {
const Foo({ super.key }); const Foo({ super.key });
...@@ -12,7 +13,13 @@ class Foo extends StatefulWidget { ...@@ -12,7 +13,13 @@ class Foo extends StatefulWidget {
} }
class FooState extends State<Foo> { class FooState extends State<Foo> {
ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
@override
void dispose() {
scrollController.dispose();
super.dispose();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
...@@ -81,7 +88,7 @@ class FooScrollBehavior extends ScrollBehavior { ...@@ -81,7 +88,7 @@ class FooScrollBehavior extends ScrollBehavior {
} }
void main() { void main() {
testWidgets('Can animate scroll after setState', (WidgetTester tester) async { testWidgetsWithLeakTracking('Can animate scroll after setState', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const Directionality( const Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
......
...@@ -5,11 +5,12 @@ ...@@ -5,11 +5,12 @@
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import 'test_widgets.dart'; import 'test_widgets.dart';
void main() { void main() {
testWidgets('Stateful widget smoke test', (WidgetTester tester) async { testWidgetsWithLeakTracking('Stateful widget smoke test', (WidgetTester tester) async {
void checkTree(BoxDecoration expectedDecoration) { void checkTree(BoxDecoration expectedDecoration) {
final SingleChildRenderObjectElement element = tester.element( final SingleChildRenderObjectElement element = tester.element(
find.byElementPredicate((Element element) => element is SingleChildRenderObjectElement && element.renderObject is! RenderView), find.byElementPredicate((Element element) => element is SingleChildRenderObjectElement && element.renderObject is! RenderView),
...@@ -54,7 +55,7 @@ void main() { ...@@ -54,7 +55,7 @@ void main() {
checkTree(kBoxDecorationB); checkTree(kBoxDecorationB);
}); });
testWidgets("Don't rebuild subwidgets", (WidgetTester tester) async { testWidgetsWithLeakTracking("Don't rebuild subwidgets", (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const FlipWidget( const FlipWidget(
key: Key('rebuild test'), key: Key('rebuild test'),
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
class InnerWidget extends StatefulWidget { class InnerWidget extends StatefulWidget {
const InnerWidget({ super.key }); const InnerWidget({ super.key });
...@@ -44,7 +45,7 @@ class OuterContainerState extends State<OuterContainer> { ...@@ -44,7 +45,7 @@ class OuterContainerState extends State<OuterContainer> {
} }
void main() { void main() {
testWidgets('resync stateful widget', (WidgetTester tester) async { testWidgetsWithLeakTracking('resync stateful widget', (WidgetTester tester) async {
const Key innerKey = Key('inner'); const Key innerKey = Key('inner');
const Key outerKey = Key('outer'); const Key outerKey = Key('outer');
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
class TestStatusTransitionWidget extends StatusTransitionWidget { class TestStatusTransitionWidget extends StatusTransitionWidget {
const TestStatusTransitionWidget({ const TestStatusTransitionWidget({
...@@ -19,12 +20,13 @@ class TestStatusTransitionWidget extends StatusTransitionWidget { ...@@ -19,12 +20,13 @@ class TestStatusTransitionWidget extends StatusTransitionWidget {
} }
void main() { void main() {
testWidgets('Status transition control test', (WidgetTester tester) async { testWidgetsWithLeakTracking('Status transition control test', (WidgetTester tester) async {
bool didBuild = false; bool didBuild = false;
final AnimationController controller = AnimationController( final AnimationController controller = AnimationController(
duration: const Duration(seconds: 1), duration: const Duration(seconds: 1),
vsync: const TestVSync(), vsync: const TestVSync(),
); );
addTearDown(controller.dispose);
await tester.pumpWidget(TestStatusTransitionWidget( await tester.pumpWidget(TestStatusTransitionWidget(
animation: controller, animation: controller,
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
class TestWidget extends StatefulWidget { class TestWidget extends StatefulWidget {
const TestWidget({ const TestWidget({
...@@ -48,7 +49,7 @@ class TestWidgetState extends State<TestWidget> { ...@@ -48,7 +49,7 @@ class TestWidgetState extends State<TestWidget> {
void main() { void main() {
testWidgets('no change', (WidgetTester tester) async { testWidgetsWithLeakTracking('no change', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
ColoredBox( ColoredBox(
color: Colors.blue, color: Colors.blue,
...@@ -88,7 +89,7 @@ void main() { ...@@ -88,7 +89,7 @@ void main() {
await tester.pumpWidget(Container()); await tester.pumpWidget(Container());
}); });
testWidgets('remove one', (WidgetTester tester) async { testWidgetsWithLeakTracking('remove one', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
ColoredBox( ColoredBox(
color: Colors.blue, color: Colors.blue,
...@@ -127,7 +128,7 @@ void main() { ...@@ -127,7 +128,7 @@ void main() {
await tester.pumpWidget(Container()); await tester.pumpWidget(Container());
}); });
testWidgets('swap instances around', (WidgetTester tester) async { testWidgetsWithLeakTracking('swap instances around', (WidgetTester tester) async {
const Widget a = TestWidget(persistentState: 0x61, syncedState: 0x41, child: Text('apple', textDirection: TextDirection.ltr)); const Widget a = TestWidget(persistentState: 0x61, syncedState: 0x41, child: Text('apple', textDirection: TextDirection.ltr));
const Widget b = TestWidget(persistentState: 0x62, syncedState: 0x42, child: Text('banana', textDirection: TextDirection.ltr)); const Widget b = TestWidget(persistentState: 0x62, syncedState: 0x42, child: Text('banana', textDirection: TextDirection.ltr));
await tester.pumpWidget(const Column()); await tester.pumpWidget(const Column());
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
class TestStatefulWidget extends StatefulWidget { class TestStatefulWidget extends StatefulWidget {
const TestStatefulWidget({ super.key }); const TestStatefulWidget({ super.key });
...@@ -37,7 +38,7 @@ class TestChildState extends State<TestChildWidget> { ...@@ -37,7 +38,7 @@ class TestChildState extends State<TestChildWidget> {
} }
void main() { void main() {
testWidgets('Table widget - empty', (WidgetTester tester) async { testWidgetsWithLeakTracking('Table widget - empty', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -46,7 +47,7 @@ void main() { ...@@ -46,7 +47,7 @@ void main() {
); );
}); });
testWidgets('Table widget - control test', (WidgetTester tester) async { testWidgetsWithLeakTracking('Table widget - control test', (WidgetTester tester) async {
Future<void> run(TextDirection textDirection) async { Future<void> run(TextDirection textDirection) async {
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
...@@ -86,7 +87,7 @@ void main() { ...@@ -86,7 +87,7 @@ void main() {
await run(TextDirection.rtl); await run(TextDirection.rtl);
}); });
testWidgets('Table widget can be detached and re-attached', (WidgetTester tester) async { testWidgetsWithLeakTracking('Table widget can be detached and re-attached', (WidgetTester tester) async {
final Widget table = Table( final Widget table = Table(
key: GlobalKey(), key: GlobalKey(),
children: const <TableRow>[ children: const <TableRow>[
...@@ -121,7 +122,7 @@ void main() { ...@@ -121,7 +122,7 @@ void main() {
expect(tester.takeException(), isNull); expect(tester.takeException(), isNull);
}); });
testWidgets('Table widget - column offset (LTR)', (WidgetTester tester) async { testWidgetsWithLeakTracking('Table widget - column offset (LTR)', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -191,7 +192,7 @@ void main() { ...@@ -191,7 +192,7 @@ void main() {
expect(c3.left, equals(c1.left)); expect(c3.left, equals(c1.left));
}); });
testWidgets('Table widget - column offset (RTL)', (WidgetTester tester) async { testWidgetsWithLeakTracking('Table widget - column offset (RTL)', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.rtl, textDirection: TextDirection.rtl,
...@@ -261,7 +262,7 @@ void main() { ...@@ -261,7 +262,7 @@ void main() {
expect(c3.right, equals(c1.right)); expect(c3.right, equals(c1.right));
}); });
testWidgets('Table border - smoke test', (WidgetTester tester) async { testWidgetsWithLeakTracking('Table border - smoke test', (WidgetTester tester) async {
Future<void> run(TextDirection textDirection) async { Future<void> run(TextDirection textDirection) async {
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
...@@ -295,7 +296,7 @@ void main() { ...@@ -295,7 +296,7 @@ void main() {
await run(TextDirection.rtl); await run(TextDirection.rtl);
}); });
testWidgets('Table widget - changing table dimensions', (WidgetTester tester) async { testWidgetsWithLeakTracking('Table widget - changing table dimensions', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -351,7 +352,7 @@ void main() { ...@@ -351,7 +352,7 @@ void main() {
expect(boxG1, isNot(equals(boxG2))); expect(boxG1, isNot(equals(boxG2)));
}); });
testWidgets('Really small deficit double precision error', (WidgetTester tester) async { testWidgetsWithLeakTracking('Really small deficit double precision error', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/27083 // Regression test for https://github.com/flutter/flutter/issues/27083
const SizedBox cell = SizedBox(width: 16, height: 16); const SizedBox cell = SizedBox(width: 16, height: 16);
await tester.pumpWidget( await tester.pumpWidget(
...@@ -376,7 +377,7 @@ void main() { ...@@ -376,7 +377,7 @@ void main() {
// If the above bug is present this test will never terminate. // If the above bug is present this test will never terminate.
}); });
testWidgets('Calculating flex columns with small width deficit', (WidgetTester tester) async { testWidgetsWithLeakTracking('Calculating flex columns with small width deficit', (WidgetTester tester) async {
const SizedBox cell = SizedBox(width: 1, height: 1); const SizedBox cell = SizedBox(width: 1, height: 1);
// If the error is present, pumpWidget() will fail due to an unsatisfied // If the error is present, pumpWidget() will fail due to an unsatisfied
// assertion during the layout phase. // assertion during the layout phase.
...@@ -406,7 +407,7 @@ void main() { ...@@ -406,7 +407,7 @@ void main() {
expect(tester.takeException(), null); expect(tester.takeException(), null);
}); });
testWidgets('Table widget - repump test', (WidgetTester tester) async { testWidgetsWithLeakTracking('Table widget - repump test', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -464,7 +465,7 @@ void main() { ...@@ -464,7 +465,7 @@ void main() {
expect(boxA.size, equals(boxB.size)); expect(boxA.size, equals(boxB.size));
}); });
testWidgets('Table widget - intrinsic sizing test', (WidgetTester tester) async { testWidgetsWithLeakTracking('Table widget - intrinsic sizing test', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -500,7 +501,7 @@ void main() { ...@@ -500,7 +501,7 @@ void main() {
expect(boxA.size.height, equals(boxB.size.height)); expect(boxA.size.height, equals(boxB.size.height));
}); });
testWidgets('Table widget - intrinsic sizing test, resizing', (WidgetTester tester) async { testWidgetsWithLeakTracking('Table widget - intrinsic sizing test, resizing', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -561,7 +562,7 @@ void main() { ...@@ -561,7 +562,7 @@ void main() {
expect(boxA.size.height, equals(boxB.size.height)); expect(boxA.size.height, equals(boxB.size.height));
}); });
testWidgets('Table widget - intrinsic sizing test, changing column widths', (WidgetTester tester) async { testWidgetsWithLeakTracking('Table widget - intrinsic sizing test, changing column widths', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -621,7 +622,7 @@ void main() { ...@@ -621,7 +622,7 @@ void main() {
expect(boxA.size.height, equals(boxB.size.height)); expect(boxA.size.height, equals(boxB.size.height));
}); });
testWidgets('Table widget - moving test', (WidgetTester tester) async { testWidgetsWithLeakTracking('Table widget - moving test', (WidgetTester tester) async {
final List<BuildContext> contexts = <BuildContext>[]; final List<BuildContext> contexts = <BuildContext>[];
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
...@@ -677,7 +678,7 @@ void main() { ...@@ -677,7 +678,7 @@ void main() {
expect(contexts[0], equals(contexts[1])); expect(contexts[0], equals(contexts[1]));
}); });
testWidgets('Table widget - keyed rows', (WidgetTester tester) async { testWidgetsWithLeakTracking('Table widget - keyed rows', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -735,7 +736,7 @@ void main() { ...@@ -735,7 +736,7 @@ void main() {
expect(state22.mounted, isTrue); expect(state22.mounted, isTrue);
}); });
testWidgets('Table widget - global key reparenting', (WidgetTester tester) async { testWidgetsWithLeakTracking('Table widget - global key reparenting', (WidgetTester tester) async {
final GlobalKey key = GlobalKey(); final GlobalKey key = GlobalKey();
final Key tableKey = UniqueKey(); final Key tableKey = UniqueKey();
...@@ -848,7 +849,7 @@ void main() { ...@@ -848,7 +849,7 @@ void main() {
expect(table.row(0).length, 2); expect(table.row(0).length, 2);
}); });
testWidgets('Table widget diagnostics', (WidgetTester tester) async { testWidgetsWithLeakTracking('Table widget diagnostics', (WidgetTester tester) async {
GlobalKey key0; GlobalKey key0;
final Widget table = Directionality( final Widget table = Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -904,7 +905,7 @@ void main() { ...@@ -904,7 +905,7 @@ void main() {
}); });
// Regression test for https://github.com/flutter/flutter/issues/31473. // Regression test for https://github.com/flutter/flutter/issues/31473.
testWidgets( testWidgetsWithLeakTracking(
'Does not crash if a child RenderObject is replaced by another RenderObject of a different type', 'Does not crash if a child RenderObject is replaced by another RenderObject of a different type',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -930,7 +931,7 @@ void main() { ...@@ -930,7 +931,7 @@ void main() {
}, },
); );
testWidgets('Table widget - Default textBaseline is null', (WidgetTester tester) async { testWidgetsWithLeakTracking('Table widget - Default textBaseline is null', (WidgetTester tester) async {
expect( expect(
() => Table(defaultVerticalAlignment: TableCellVerticalAlignment.baseline), () => Table(defaultVerticalAlignment: TableCellVerticalAlignment.baseline),
throwsA( throwsA(
...@@ -940,7 +941,7 @@ void main() { ...@@ -940,7 +941,7 @@ void main() {
); );
}); });
testWidgets( testWidgetsWithLeakTracking(
'Table widget requires all TableRows to have same number of children', 'Table widget requires all TableRows to have same number of children',
(WidgetTester tester) async { (WidgetTester tester) async {
FlutterError? error; FlutterError? error;
...@@ -965,7 +966,7 @@ void main() { ...@@ -965,7 +966,7 @@ void main() {
}, },
); );
testWidgets('Can replace child with a different RenderObject type', (WidgetTester tester) async { testWidgetsWithLeakTracking('Can replace child with a different RenderObject type', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/69395. // Regression test for https://github.com/flutter/flutter/issues/69395.
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
...@@ -1001,7 +1002,7 @@ void main() { ...@@ -1001,7 +1002,7 @@ void main() {
expect(table.column(2).last.runtimeType, isNot(toBeReplaced)); expect(table.column(2).last.runtimeType, isNot(toBeReplaced));
}); });
testWidgets('Do not crash if a child that has not been layed out in a previous build is removed', (WidgetTester tester) async { testWidgetsWithLeakTracking('Do not crash if a child that has not been layed out in a previous build is removed', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/60488. // Regression test for https://github.com/flutter/flutter/issues/60488.
Widget buildTable(Key key) { Widget buildTable(Key key) {
return Directionality( return Directionality(
...@@ -1034,7 +1035,7 @@ void main() { ...@@ -1034,7 +1035,7 @@ void main() {
expect(find.text('Hello'), findsOneWidget); expect(find.text('Hello'), findsOneWidget);
}); });
testWidgets('TableRow with no children throws an error message', (WidgetTester tester) async { testWidgetsWithLeakTracking('TableRow with no children throws an error message', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/119541. // Regression test for https://github.com/flutter/flutter/issues/119541.
String result = 'no exception'; String result = 'no exception';
......
...@@ -7,9 +7,10 @@ import 'dart:ui'; ...@@ -7,9 +7,10 @@ import 'dart:ui';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() { void main() {
testWidgets('TapRegionSurface detects outside taps', (WidgetTester tester) async { testWidgetsWithLeakTracking('TapRegionSurface detects outside taps', (WidgetTester tester) async {
final Set<String> tappedOutside = <String>{}; final Set<String> tappedOutside = <String>{};
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
...@@ -101,7 +102,7 @@ void main() { ...@@ -101,7 +102,7 @@ void main() {
expect(tappedOutside, isEmpty); expect(tappedOutside, isEmpty);
}); });
testWidgets('TapRegionSurface detects inside taps', (WidgetTester tester) async { testWidgetsWithLeakTracking('TapRegionSurface detects inside taps', (WidgetTester tester) async {
final Set<String> tappedInside = <String>{}; final Set<String> tappedInside = <String>{};
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
...@@ -188,7 +189,7 @@ void main() { ...@@ -188,7 +189,7 @@ void main() {
expect(tappedInside, isEmpty); expect(tappedInside, isEmpty);
}); });
testWidgets('TapRegionSurface detects inside taps correctly with behavior', (WidgetTester tester) async { testWidgetsWithLeakTracking('TapRegionSurface detects inside taps correctly with behavior', (WidgetTester tester) async {
final Set<String> tappedInside = <String>{}; final Set<String> tappedInside = <String>{};
const ValueKey<String> noGroupKey = ValueKey<String>('No Group'); const ValueKey<String> noGroupKey = ValueKey<String>('No Group');
const ValueKey<String> group1AKey = ValueKey<String>('Group 1 A'); const ValueKey<String> group1AKey = ValueKey<String>('Group 1 A');
...@@ -275,7 +276,7 @@ void main() { ...@@ -275,7 +276,7 @@ void main() {
tappedInside.clear(); tappedInside.clear();
}); });
testWidgets('Setting the group updates the registration', (WidgetTester tester) async { testWidgetsWithLeakTracking('Setting the group updates the registration', (WidgetTester tester) async {
final Set<String> tappedOutside = <String>{}; final Set<String> tappedOutside = <String>{};
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
......
...@@ -10,9 +10,10 @@ library; ...@@ -10,9 +10,10 @@ library;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() { void main() {
testWidgets('Centered text', (WidgetTester tester) async { testWidgetsWithLeakTracking('Centered text', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Center( Center(
child: RepaintBoundary( child: RepaintBoundary(
...@@ -63,7 +64,7 @@ void main() { ...@@ -63,7 +64,7 @@ void main() {
}); });
testWidgets('Text Foreground', (WidgetTester tester) async { testWidgetsWithLeakTracking('Text Foreground', (WidgetTester tester) async {
const Color black = Color(0xFF000000); const Color black = Color(0xFF000000);
const Color red = Color(0xFFFF0000); const Color red = Color(0xFFFF0000);
const Color blue = Color(0xFF0000FF); const Color blue = Color(0xFF0000FF);
...@@ -141,7 +142,7 @@ void main() { ...@@ -141,7 +142,7 @@ void main() {
// TODO(garyq): This test requires an update when the background // TODO(garyq): This test requires an update when the background
// drawing from the beginning of the line bug is fixed. The current // drawing from the beginning of the line bug is fixed. The current
// tested version is not completely correct. // tested version is not completely correct.
testWidgets('Text Background', (WidgetTester tester) async { testWidgetsWithLeakTracking('Text Background', (WidgetTester tester) async {
const Color red = Colors.red; const Color red = Colors.red;
const Color blue = Colors.blue; const Color blue = Colors.blue;
const Color translucentGreen = Color(0x5000F000); const Color translucentGreen = Color(0x5000F000);
...@@ -188,7 +189,7 @@ void main() { ...@@ -188,7 +189,7 @@ void main() {
); );
}); });
testWidgets('Text Fade', (WidgetTester tester) async { testWidgetsWithLeakTracking('Text Fade', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
theme: ThemeData(useMaterial3: false), theme: ThemeData(useMaterial3: false),
...@@ -225,7 +226,7 @@ void main() { ...@@ -225,7 +226,7 @@ void main() {
); );
}); });
testWidgets('Default Strut text', (WidgetTester tester) async { testWidgetsWithLeakTracking('Default Strut text', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Center( Center(
child: RepaintBoundary( child: RepaintBoundary(
...@@ -250,7 +251,7 @@ void main() { ...@@ -250,7 +251,7 @@ void main() {
); );
}); });
testWidgets('Strut text 1', (WidgetTester tester) async { testWidgetsWithLeakTracking('Strut text 1', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Center( Center(
child: RepaintBoundary( child: RepaintBoundary(
...@@ -277,7 +278,7 @@ void main() { ...@@ -277,7 +278,7 @@ void main() {
); );
}); });
testWidgets('Strut text 2', (WidgetTester tester) async { testWidgetsWithLeakTracking('Strut text 2', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Center( Center(
child: RepaintBoundary( child: RepaintBoundary(
...@@ -305,7 +306,7 @@ void main() { ...@@ -305,7 +306,7 @@ void main() {
); );
}); });
testWidgets('Strut text rich', (WidgetTester tester) async { testWidgetsWithLeakTracking('Strut text rich', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Center( Center(
child: RepaintBoundary( child: RepaintBoundary(
...@@ -356,7 +357,7 @@ void main() { ...@@ -356,7 +357,7 @@ void main() {
); );
}); });
testWidgets('Strut text font fallback', (WidgetTester tester) async { testWidgetsWithLeakTracking('Strut text font fallback', (WidgetTester tester) async {
// Font Fallback // Font Fallback
await tester.pumpWidget( await tester.pumpWidget(
Center( Center(
...@@ -391,7 +392,7 @@ void main() { ...@@ -391,7 +392,7 @@ void main() {
); );
}); });
testWidgets('Strut text rich forceStrutHeight', (WidgetTester tester) async { testWidgetsWithLeakTracking('Strut text rich forceStrutHeight', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Center( Center(
child: RepaintBoundary( child: RepaintBoundary(
...@@ -442,7 +443,7 @@ void main() { ...@@ -442,7 +443,7 @@ void main() {
); );
}); });
testWidgets('Decoration thickness', (WidgetTester tester) async { testWidgetsWithLeakTracking('Decoration thickness', (WidgetTester tester) async {
final TextDecoration allDecorations = TextDecoration.combine( final TextDecoration allDecorations = TextDecoration.combine(
<TextDecoration>[ <TextDecoration>[
TextDecoration.underline, TextDecoration.underline,
...@@ -480,7 +481,7 @@ void main() { ...@@ -480,7 +481,7 @@ void main() {
); );
}); });
testWidgets('Decoration thickness', (WidgetTester tester) async { testWidgetsWithLeakTracking('Decoration thickness', (WidgetTester tester) async {
final TextDecoration allDecorations = TextDecoration.combine( final TextDecoration allDecorations = TextDecoration.combine(
<TextDecoration>[ <TextDecoration>[
TextDecoration.underline, TextDecoration.underline,
...@@ -519,7 +520,7 @@ void main() { ...@@ -519,7 +520,7 @@ void main() {
); );
}); });
testWidgets('Text Inline widget', (WidgetTester tester) async { testWidgetsWithLeakTracking('Text Inline widget', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Theme(data: ThemeData(useMaterial3: false), child: Center( Theme(data: ThemeData(useMaterial3: false), child: Center(
child: RepaintBoundary( child: RepaintBoundary(
...@@ -613,7 +614,7 @@ void main() { ...@@ -613,7 +614,7 @@ void main() {
); );
}); });
testWidgets('Text Inline widget textfield', (WidgetTester tester) async { testWidgetsWithLeakTracking('Text Inline widget textfield', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Center( Center(
child: MaterialApp( child: MaterialApp(
...@@ -660,7 +661,7 @@ void main() { ...@@ -660,7 +661,7 @@ void main() {
}); });
// This tests if multiple Text.rich widgets are able to inline nest within each other. // This tests if multiple Text.rich widgets are able to inline nest within each other.
testWidgets('Text Inline widget nesting', (WidgetTester tester) async { testWidgetsWithLeakTracking('Text Inline widget nesting', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Center( Center(
child: MaterialApp( child: MaterialApp(
...@@ -789,7 +790,7 @@ void main() { ...@@ -789,7 +790,7 @@ void main() {
); );
}); });
testWidgets('Text Inline widget baseline', (WidgetTester tester) async { testWidgetsWithLeakTracking('Text Inline widget baseline', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Theme( Theme(
data: ThemeData(useMaterial3: false), data: ThemeData(useMaterial3: false),
...@@ -899,7 +900,7 @@ void main() { ...@@ -899,7 +900,7 @@ void main() {
); );
}); });
testWidgets('Text Inline widget aboveBaseline', (WidgetTester tester) async { testWidgetsWithLeakTracking('Text Inline widget aboveBaseline', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Theme( Theme(
data: ThemeData(useMaterial3: false), data: ThemeData(useMaterial3: false),
...@@ -1009,7 +1010,7 @@ void main() { ...@@ -1009,7 +1010,7 @@ void main() {
); );
}); });
testWidgets('Text Inline widget belowBaseline', (WidgetTester tester) async { testWidgetsWithLeakTracking('Text Inline widget belowBaseline', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Theme( Theme(
data: ThemeData(useMaterial3: false), data: ThemeData(useMaterial3: false),
...@@ -1119,7 +1120,7 @@ void main() { ...@@ -1119,7 +1120,7 @@ void main() {
); );
}); });
testWidgets('Text Inline widget top', (WidgetTester tester) async { testWidgetsWithLeakTracking('Text Inline widget top', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Theme( Theme(
data: ThemeData(useMaterial3: false), data: ThemeData(useMaterial3: false),
...@@ -1229,7 +1230,7 @@ void main() { ...@@ -1229,7 +1230,7 @@ void main() {
); );
}); });
testWidgets('Text Inline widget middle', (WidgetTester tester) async { testWidgetsWithLeakTracking('Text Inline widget middle', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Theme( Theme(
data: ThemeData(useMaterial3: false), data: ThemeData(useMaterial3: false),
...@@ -1339,7 +1340,7 @@ void main() { ...@@ -1339,7 +1340,7 @@ void main() {
); );
}); });
testWidgets('Text TextHeightBehavior', (WidgetTester tester) async { testWidgetsWithLeakTracking('Text TextHeightBehavior', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Center( Center(
child: RepaintBoundary( child: RepaintBoundary(
......
...@@ -7,6 +7,7 @@ import 'package:flutter/foundation.dart'; ...@@ -7,6 +7,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() { void main() {
group('TextStyle', () { group('TextStyle', () {
...@@ -64,7 +65,7 @@ void main() { ...@@ -64,7 +65,7 @@ void main() {
); );
}); });
testWidgets('MediaQuery.textScaleFactorOf overriding compatibility', (WidgetTester tester) async { testWidgetsWithLeakTracking('MediaQuery.textScaleFactorOf overriding compatibility', (WidgetTester tester) async {
late final double outsideTextScaleFactor; late final double outsideTextScaleFactor;
late final TextScaler outsideTextScaler; late final TextScaler outsideTextScaler;
late final double insideTextScaleFactor; late final double insideTextScaleFactor;
...@@ -103,7 +104,7 @@ void main() { ...@@ -103,7 +104,7 @@ void main() {
expect(insideTextScaler, const TextScaler.linear(4.0)); expect(insideTextScaler, const TextScaler.linear(4.0));
}); });
testWidgets('textScaleFactor overriding backward compatibility', (WidgetTester tester) async { testWidgetsWithLeakTracking('textScaleFactor overriding backward compatibility', (WidgetTester tester) async {
late final double outsideTextScaleFactor; late final double outsideTextScaleFactor;
late final TextScaler outsideTextScaler; late final TextScaler outsideTextScaler;
late final double insideTextScaleFactor; late final double insideTextScaleFactor;
...@@ -183,7 +184,7 @@ void main() { ...@@ -183,7 +184,7 @@ void main() {
}); });
group('Widgets backward compatibility', () { group('Widgets backward compatibility', () {
testWidgets('RichText', (WidgetTester tester) async { testWidgetsWithLeakTracking('RichText', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
RichText( RichText(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -199,7 +200,7 @@ void main() { ...@@ -199,7 +200,7 @@ void main() {
expect(tester.renderObject<RenderParagraph>(find.byType(RichText)).textScaleFactor, 2.0); expect(tester.renderObject<RenderParagraph>(find.byType(RichText)).textScaleFactor, 2.0);
}); });
testWidgets('Text', (WidgetTester tester) async { testWidgetsWithLeakTracking('Text', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const Text( const Text(
'text', 'text',
...@@ -214,9 +215,11 @@ void main() { ...@@ -214,9 +215,11 @@ void main() {
); );
}); });
testWidgets('EditableText', (WidgetTester tester) async { testWidgetsWithLeakTracking('EditableText', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController();
addTearDown(controller.dispose);
final FocusNode focusNode = FocusNode(debugLabel: 'EditableText Node'); final FocusNode focusNode = FocusNode(debugLabel: 'EditableText Node');
addTearDown(focusNode.dispose);
const TextStyle textStyle = TextStyle(); const TextStyle textStyle = TextStyle();
const Color cursorColor = Color.fromARGB(0xFF, 0xFF, 0x00, 0x00); const Color cursorColor = Color.fromARGB(0xFF, 0xFF, 0x00, 0x00);
await tester.pumpWidget( await tester.pumpWidget(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment