Unverified Commit cfe7afdc authored by Kostia Sokolovskyi's avatar Kostia Sokolovskyi Committed by GitHub

Fix memory leaks in WidgetInspector and WidgetInspectorService. (#135828)

parent 71acf242
...@@ -372,6 +372,12 @@ class _ScreenshotData { ...@@ -372,6 +372,12 @@ class _ScreenshotData {
set screenshotOffset(Offset offset) { set screenshotOffset(Offset offset) {
containerLayer.offset = offset; containerLayer.offset = offset;
} }
/// Releases allocated resources.
@mustCallSuper
void dispose() {
containerLayer.dispose();
}
} }
/// A place to paint to build screenshots of [RenderObject]s. /// A place to paint to build screenshots of [RenderObject]s.
...@@ -550,7 +556,7 @@ class _ScreenshotPaintingContext extends PaintingContext { ...@@ -550,7 +556,7 @@ class _ScreenshotPaintingContext extends PaintingContext {
Rect renderBounds, { Rect renderBounds, {
double pixelRatio = 1.0, double pixelRatio = 1.0,
bool debugPaint = false, bool debugPaint = false,
}) { }) async {
RenderObject repaintBoundary = renderObject; RenderObject repaintBoundary = renderObject;
while (!repaintBoundary.isRepaintBoundary) { while (!repaintBoundary.isRepaintBoundary) {
repaintBoundary = repaintBoundary.parent!; repaintBoundary = repaintBoundary.parent!;
...@@ -604,7 +610,15 @@ class _ScreenshotPaintingContext extends PaintingContext { ...@@ -604,7 +610,15 @@ class _ScreenshotPaintingContext extends PaintingContext {
// been called successfully for all layers in the regular scene. // been called successfully for all layers in the regular scene.
repaintBoundary.debugLayer!.buildScene(ui.SceneBuilder()); repaintBoundary.debugLayer!.buildScene(ui.SceneBuilder());
return data.containerLayer.toImage(renderBounds, pixelRatio: pixelRatio); final ui.Image image;
try {
image = await data.containerLayer.toImage(renderBounds, pixelRatio: pixelRatio);
} finally {
data.dispose();
}
return image;
} }
} }
...@@ -1285,6 +1299,7 @@ mixin WidgetInspectorService { ...@@ -1285,6 +1299,7 @@ mixin WidgetInspectorService {
return <String, Object?>{'result': null}; return <String, Object?>{'result': null};
} }
final ByteData? byteData = await image.toByteData(format:ui.ImageByteFormat.png); final ByteData? byteData = await image.toByteData(format:ui.ImageByteFormat.png);
image.dispose();
return <String, Object>{ return <String, Object>{
'result': base64.encoder.convert(Uint8List.view(byteData!.buffer)), 'result': base64.encoder.convert(Uint8List.view(byteData!.buffer)),
...@@ -3141,7 +3156,7 @@ class _InspectorOverlayLayer extends Layer { ...@@ -3141,7 +3156,7 @@ class _InspectorOverlayLayer extends Layer {
_InspectorOverlayRenderState? _lastState; _InspectorOverlayRenderState? _lastState;
/// Picture generated from _lastState. /// Picture generated from _lastState.
late ui.Picture _picture; ui.Picture? _picture;
TextPainter? _textPainter; TextPainter? _textPainter;
double? _textPainterMaxWidth; double? _textPainterMaxWidth;
...@@ -3150,6 +3165,7 @@ class _InspectorOverlayLayer extends Layer { ...@@ -3150,6 +3165,7 @@ class _InspectorOverlayLayer extends Layer {
void dispose() { void dispose() {
_textPainter?.dispose(); _textPainter?.dispose();
_textPainter = null; _textPainter = null;
_picture?.dispose();
super.dispose(); super.dispose();
} }
...@@ -3184,9 +3200,10 @@ class _InspectorOverlayLayer extends Layer { ...@@ -3184,9 +3200,10 @@ class _InspectorOverlayLayer extends Layer {
if (state != _lastState) { if (state != _lastState) {
_lastState = state; _lastState = state;
_picture?.dispose();
_picture = _buildPicture(state); _picture = _buildPicture(state);
} }
builder.addPicture(Offset.zero, _picture); builder.addPicture(Offset.zero, _picture!);
} }
ui.Picture _buildPicture(_InspectorOverlayRenderState state) { ui.Picture _buildPicture(_InspectorOverlayRenderState state) {
......
...@@ -20,6 +20,7 @@ import 'package:flutter/material.dart'; ...@@ -20,6 +20,7 @@ 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/leak_tracker.dart'; import 'package:leak_tracker/leak_tracker.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import 'widget_inspector_test_utils.dart'; import 'widget_inspector_test_utils.dart';
...@@ -317,7 +318,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -317,7 +318,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(ref.target, null); expect(ref.target, null);
}); });
testWidgets('WidgetInspector smoke test', (WidgetTester tester) async { testWidgetsWithLeakTracking('WidgetInspector smoke test', (WidgetTester tester) async {
// This is a smoke test to verify that adding the inspector doesn't crash. // This is a smoke test to verify that adding the inspector doesn't crash.
await tester.pumpWidget( await tester.pumpWidget(
const Directionality( const Directionality(
...@@ -351,7 +352,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -351,7 +352,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(true, isTrue); // Expect that we reach here without crashing. expect(true, isTrue); // Expect that we reach here without crashing.
}); });
testWidgets('WidgetInspector interaction test', (WidgetTester tester) async { testWidgetsWithLeakTracking('WidgetInspector interaction test', (WidgetTester tester) async {
final List<String> log = <String>[]; final List<String> log = <String>[];
final GlobalKey selectButtonKey = GlobalKey(); final GlobalKey selectButtonKey = GlobalKey();
final GlobalKey inspectorKey = GlobalKey(); final GlobalKey inspectorKey = GlobalKey();
...@@ -446,7 +447,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -446,7 +447,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
); );
}); });
testWidgets('WidgetInspector non-invertible transform regression test', (WidgetTester tester) async { testWidgetsWithLeakTracking('WidgetInspector non-invertible transform regression test', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -471,7 +472,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -471,7 +472,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(true, isTrue); // Expect that we reach here without crashing. expect(true, isTrue); // Expect that we reach here without crashing.
}); });
testWidgets('WidgetInspector scroll test', (WidgetTester tester) async { testWidgetsWithLeakTracking('WidgetInspector scroll test', (WidgetTester tester) async {
final Key childKey = UniqueKey(); final Key childKey = UniqueKey();
final GlobalKey selectButtonKey = GlobalKey(); final GlobalKey selectButtonKey = GlobalKey();
final GlobalKey inspectorKey = GlobalKey(); final GlobalKey inspectorKey = GlobalKey();
...@@ -528,7 +529,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -528,7 +529,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(tester.getTopLeft(find.byKey(childKey)).dy, equals(0.0)); expect(tester.getTopLeft(find.byKey(childKey)).dy, equals(0.0));
}); });
testWidgets('WidgetInspector long press', (WidgetTester tester) async { testWidgetsWithLeakTracking('WidgetInspector long press', (WidgetTester tester) async {
bool didLongPress = false; bool didLongPress = false;
await tester.pumpWidget( await tester.pumpWidget(
...@@ -552,7 +553,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -552,7 +553,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(didLongPress, isFalse); expect(didLongPress, isFalse);
}); });
testWidgets('WidgetInspector offstage', (WidgetTester tester) async { testWidgetsWithLeakTracking('WidgetInspector offstage', (WidgetTester tester) async {
final GlobalKey inspectorKey = GlobalKey(); final GlobalKey inspectorKey = GlobalKey();
final GlobalKey clickTarget = GlobalKey(); final GlobalKey clickTarget = GlobalKey();
...@@ -570,6 +571,14 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -570,6 +571,14 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
], ],
); );
} }
late final OverlayEntry entry1;
addTearDown(() => entry1..remove()..dispose());
late final OverlayEntry entry2;
addTearDown(() => entry2..remove()..dispose());
late final OverlayEntry entry3;
addTearDown(() => entry3..remove()..dispose());
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -578,16 +587,16 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -578,16 +587,16 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
selectButtonBuilder: null, selectButtonBuilder: null,
child: Overlay( child: Overlay(
initialEntries: <OverlayEntry>[ initialEntries: <OverlayEntry>[
OverlayEntry( entry1 = OverlayEntry(
maintainState: true, maintainState: true,
builder: (BuildContext _) => createSubtree(width: 94.0), builder: (BuildContext _) => createSubtree(width: 94.0),
), ),
OverlayEntry( entry2 = OverlayEntry(
opaque: true, opaque: true,
maintainState: true, maintainState: true,
builder: (BuildContext _) => createSubtree(width: 95.0), builder: (BuildContext _) => createSubtree(width: 95.0),
), ),
OverlayEntry( entry3 = OverlayEntry(
maintainState: true, maintainState: true,
builder: (BuildContext _) => createSubtree(width: 96.0, key: clickTarget), builder: (BuildContext _) => createSubtree(width: 96.0, key: clickTarget),
), ),
...@@ -617,7 +626,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -617,7 +626,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
); );
}); });
testWidgets('WidgetInspector with Transform above', (WidgetTester tester) async { testWidgetsWithLeakTracking('WidgetInspector with Transform above', (WidgetTester tester) async {
final GlobalKey childKey = GlobalKey(); final GlobalKey childKey = GlobalKey();
final GlobalKey repaintBoundaryKey = GlobalKey(); final GlobalKey repaintBoundaryKey = GlobalKey();
...@@ -664,7 +673,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -664,7 +673,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
); );
}); });
testWidgets('Multiple widget inspectors', (WidgetTester tester) async { testWidgetsWithLeakTracking('Multiple widget inspectors', (WidgetTester tester) async {
// This test verifies that interacting with different inspectors // This test verifies that interacting with different inspectors
// works correctly. This use case may be an app that displays multiple // works correctly. This use case may be an app that displays multiple
// apps inside (i.e. a storyboard). // apps inside (i.e. a storyboard).
...@@ -826,7 +835,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -826,7 +835,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
service.disposeGroup(group3); service.disposeGroup(group3);
}); });
testWidgets('WidgetInspectorService maybeSetSelection', (WidgetTester tester) async { testWidgetsWithLeakTracking('WidgetInspectorService maybeSetSelection', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const Directionality( const Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -873,7 +882,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -873,7 +882,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(service.selection.currentElement, equals(elementA)); expect(service.selection.currentElement, equals(elementA));
}); });
testWidgets('WidgetInspectorService defunct selection regression test', (WidgetTester tester) async { testWidgetsWithLeakTracking('WidgetInspectorService defunct selection regression test', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const Directionality( const Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -926,7 +935,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -926,7 +935,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(service.selection.current, equals(null)); expect(service.selection.current, equals(null));
}); });
testWidgets('WidgetInspectorService getParentChain', (WidgetTester tester) async { testWidgetsWithLeakTracking('WidgetInspectorService getParentChain', (WidgetTester tester) async {
const String group = 'test-group'; const String group = 'test-group';
await tester.pumpWidget( await tester.pumpWidget(
...@@ -994,7 +1003,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -994,7 +1003,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
} }
}); });
testWidgets('WidgetInspectorService getChildren', (WidgetTester tester) async { testWidgetsWithLeakTracking('WidgetInspectorService getChildren', (WidgetTester tester) async {
const String group = 'test-group'; const String group = 'test-group';
await tester.pumpWidget( await tester.pumpWidget(
...@@ -1022,7 +1031,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -1022,7 +1031,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
} }
}); });
testWidgets('WidgetInspectorService creationLocation', (WidgetTester tester) async { testWidgetsWithLeakTracking('WidgetInspectorService creationLocation', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -1084,7 +1093,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -1084,7 +1093,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(columnC, equals(19)); expect(columnC, equals(19));
}, skip: !WidgetInspectorService.instance.isWidgetCreationTracked()); // [intended] Test requires --track-widget-creation flag. }, skip: !WidgetInspectorService.instance.isWidgetCreationTracked()); // [intended] Test requires --track-widget-creation flag.
testWidgets('WidgetInspectorService setSelection notifiers for an Element', testWidgetsWithLeakTracking('WidgetInspectorService setSelection notifiers for an Element',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const Directionality( const Directionality(
...@@ -1129,7 +1138,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -1129,7 +1138,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
skip: !WidgetInspectorService.instance.isWidgetCreationTracked(), // [intended] Test requires --track-widget-creation flag. skip: !WidgetInspectorService.instance.isWidgetCreationTracked(), // [intended] Test requires --track-widget-creation flag.
); );
testWidgets( testWidgetsWithLeakTracking(
'WidgetInspectorService setSelection notifiers for a RenderObject', 'WidgetInspectorService setSelection notifiers for a RenderObject',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -1175,7 +1184,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -1175,7 +1184,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
skip: !WidgetInspectorService.instance.isWidgetCreationTracked(), // [intended] Test requires --track-widget-creation flag. skip: !WidgetInspectorService.instance.isWidgetCreationTracked(), // [intended] Test requires --track-widget-creation flag.
); );
testWidgets( testWidgetsWithLeakTracking(
'WidgetInspector selectButton inspection for tap', 'WidgetInspector selectButton inspection for tap',
(WidgetTester tester) async { (WidgetTester tester) async {
final GlobalKey selectButtonKey = GlobalKey(); final GlobalKey selectButtonKey = GlobalKey();
...@@ -1225,7 +1234,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -1225,7 +1234,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
skip: !WidgetInspectorService.instance.isWidgetCreationTracked() // [intended] Test requires --track-widget-creation flag. skip: !WidgetInspectorService.instance.isWidgetCreationTracked() // [intended] Test requires --track-widget-creation flag.
); );
testWidgets('test transformDebugCreator will re-order if after stack trace', (WidgetTester tester) async { testWidgetsWithLeakTracking('test transformDebugCreator will re-order if after stack trace', (WidgetTester tester) async {
final bool widgetTracked = WidgetInspectorService.instance.isWidgetCreationTracked(); final bool widgetTracked = WidgetInspectorService.instance.isWidgetCreationTracked();
await tester.pumpWidget( await tester.pumpWidget(
const Directionality( const Directionality(
...@@ -1289,7 +1298,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -1289,7 +1298,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(nodes[4].runtimeType, DiagnosticsStackTrace); expect(nodes[4].runtimeType, DiagnosticsStackTrace);
}); });
testWidgets('test transformDebugCreator will not re-order if before stack trace', (WidgetTester tester) async { testWidgetsWithLeakTracking('test transformDebugCreator will not re-order if before stack trace', (WidgetTester tester) async {
final bool widgetTracked = WidgetInspectorService.instance.isWidgetCreationTracked(); final bool widgetTracked = WidgetInspectorService.instance.isWidgetCreationTracked();
await tester.pumpWidget( await tester.pumpWidget(
const Directionality( const Directionality(
...@@ -1352,7 +1361,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -1352,7 +1361,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(nodes[4].runtimeType, DiagnosticsStackTrace); expect(nodes[4].runtimeType, DiagnosticsStackTrace);
}, skip: WidgetInspectorService.instance.isWidgetCreationTracked()); // [intended] Test requires --no-track-widget-creation flag. }, skip: WidgetInspectorService.instance.isWidgetCreationTracked()); // [intended] Test requires --no-track-widget-creation flag.
testWidgets('test transformDebugCreator will add DevToolsDeepLinkProperty for overflow errors', (WidgetTester tester) async { testWidgetsWithLeakTracking('test transformDebugCreator will add DevToolsDeepLinkProperty for overflow errors', (WidgetTester tester) async {
activeDevToolsServerAddress = 'http://127.0.0.1:9100'; activeDevToolsServerAddress = 'http://127.0.0.1:9100';
connectedVmServiceUri = 'http://127.0.0.1:55269/798ay5al_FM=/'; connectedVmServiceUri = 'http://127.0.0.1:55269/798ay5al_FM=/';
...@@ -1387,7 +1396,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -1387,7 +1396,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(nodes[5].runtimeType, StringProperty); expect(nodes[5].runtimeType, StringProperty);
}, skip: !WidgetInspectorService.instance.isWidgetCreationTracked()); // [intended] Test requires --track-widget-creation flag. }, skip: !WidgetInspectorService.instance.isWidgetCreationTracked()); // [intended] Test requires --track-widget-creation flag.
testWidgets('test transformDebugCreator will not add DevToolsDeepLinkProperty for non-overflow errors', (WidgetTester tester) async { testWidgetsWithLeakTracking('test transformDebugCreator will not add DevToolsDeepLinkProperty for non-overflow errors', (WidgetTester tester) async {
activeDevToolsServerAddress = 'http://127.0.0.1:9100'; activeDevToolsServerAddress = 'http://127.0.0.1:9100';
connectedVmServiceUri = 'http://127.0.0.1:55269/798ay5al_FM=/'; connectedVmServiceUri = 'http://127.0.0.1:55269/798ay5al_FM=/';
setupDefaultPubRootDirectory(service); setupDefaultPubRootDirectory(service);
...@@ -1419,7 +1428,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -1419,7 +1428,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(nodes[3].runtimeType, StringProperty); expect(nodes[3].runtimeType, StringProperty);
}, skip: !WidgetInspectorService.instance.isWidgetCreationTracked()); // [intended] Test requires --track-widget-creation flag. }, skip: !WidgetInspectorService.instance.isWidgetCreationTracked()); // [intended] Test requires --track-widget-creation flag.
testWidgets('test transformDebugCreator will not add DevToolsDeepLinkProperty if devtoolsServerAddress is unavailable', (WidgetTester tester) async { testWidgetsWithLeakTracking('test transformDebugCreator will not add DevToolsDeepLinkProperty if devtoolsServerAddress is unavailable', (WidgetTester tester) async {
activeDevToolsServerAddress = null; activeDevToolsServerAddress = null;
connectedVmServiceUri = 'http://127.0.0.1:55269/798ay5al_FM=/'; connectedVmServiceUri = 'http://127.0.0.1:55269/798ay5al_FM=/';
setupDefaultPubRootDirectory(service); setupDefaultPubRootDirectory(service);
...@@ -1561,7 +1570,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -1561,7 +1570,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
}); });
group('addPubRootDirectories', () { group('addPubRootDirectories', () {
testWidgets( testWidgetsWithLeakTracking(
'does not have createdByLocalProject when there are no pubRootDirectories', 'does not have createdByLocalProject when there are no pubRootDirectories',
(WidgetTester tester) async { (WidgetTester tester) async {
const Widget widget = Directionality( const Widget widget = Directionality(
...@@ -1591,7 +1600,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -1591,7 +1600,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'has createdByLocalProject when the element is part of the pubRootDirectory', 'has createdByLocalProject when the element is part of the pubRootDirectory',
(WidgetTester tester) async { (WidgetTester tester) async {
const Widget widget = Directionality( const Widget widget = Directionality(
...@@ -1617,7 +1626,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -1617,7 +1626,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'does not have createdByLocalProject when widget package directory is a suffix of a pubRootDirectory', 'does not have createdByLocalProject when widget package directory is a suffix of a pubRootDirectory',
(WidgetTester tester) async { (WidgetTester tester) async {
const Widget widget = Directionality( const Widget widget = Directionality(
...@@ -1642,7 +1651,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -1642,7 +1651,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'has createdByLocalProject when the pubRootDirectory is prefixed with file://', 'has createdByLocalProject when the pubRootDirectory is prefixed with file://',
(WidgetTester tester) async { (WidgetTester tester) async {
const Widget widget = Directionality( const Widget widget = Directionality(
...@@ -1667,7 +1676,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -1667,7 +1676,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'does not have createdByLocalProject when thePubRootDirectory has a different suffix', 'does not have createdByLocalProject when thePubRootDirectory has a different suffix',
(WidgetTester tester) async { (WidgetTester tester) async {
const Widget widget = Directionality( const Widget widget = Directionality(
...@@ -1692,7 +1701,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -1692,7 +1701,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'has createdByLocalProject even if another pubRootDirectory does not match', 'has createdByLocalProject even if another pubRootDirectory does not match',
(WidgetTester tester) async { (WidgetTester tester) async {
const Widget widget = Directionality( const Widget widget = Directionality(
...@@ -1720,7 +1729,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -1720,7 +1729,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'widget is part of core framework and is the child of a widget in the package pubRootDirectories', 'widget is part of core framework and is the child of a widget in the package pubRootDirectories',
(WidgetTester tester) async { (WidgetTester tester) async {
const Widget widget = Directionality( const Widget widget = Directionality(
...@@ -1797,7 +1806,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -1797,7 +1806,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
service.resetPubRootDirectories(); service.resetPubRootDirectories();
}); });
testWidgets( testWidgetsWithLeakTracking(
'reacts to add and removing pubRootDirectories', 'reacts to add and removing pubRootDirectories',
(WidgetTester tester) async { (WidgetTester tester) async {
const Widget widget = Directionality( const Widget widget = Directionality(
...@@ -1835,7 +1844,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -1835,7 +1844,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'does not match when the package directory does not match', 'does not match when the package directory does not match',
(WidgetTester tester) async { (WidgetTester tester) async {
const Widget widget = Directionality( const Widget widget = Directionality(
...@@ -1863,7 +1872,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -1863,7 +1872,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'has createdByLocalProject when the pubRootDirectory is prefixed with file://', 'has createdByLocalProject when the pubRootDirectory is prefixed with file://',
(WidgetTester tester) async { (WidgetTester tester) async {
const Widget widget = Directionality( const Widget widget = Directionality(
...@@ -1888,7 +1897,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -1888,7 +1897,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'can handle consecutive calls to add', 'can handle consecutive calls to add',
(WidgetTester tester) async { (WidgetTester tester) async {
const Widget widget = Directionality( const Widget widget = Directionality(
...@@ -1917,7 +1926,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -1917,7 +1926,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
); );
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'can handle removing an unrelated pubRootDirectory', 'can handle removing an unrelated pubRootDirectory',
(WidgetTester tester) async { (WidgetTester tester) async {
const Widget widget = Directionality( const Widget widget = Directionality(
...@@ -1953,7 +1962,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -1953,7 +1962,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'can handle parent widget being part of a separate package', 'can handle parent widget being part of a separate package',
(WidgetTester tester) async { (WidgetTester tester) async {
const Widget widget = Directionality( const Widget widget = Directionality(
...@@ -2030,7 +2039,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -2030,7 +2039,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
); );
group('InspectorSelection', () { group('InspectorSelection', () {
testWidgets('receives notifications when selection changes', testWidgetsWithLeakTracking('receives notifications when selection changes',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const Directionality( const Directionality(
...@@ -2044,6 +2053,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -2044,6 +2053,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
), ),
); );
final InspectorSelection selection = InspectorSelection(); final InspectorSelection selection = InspectorSelection();
addTearDown(selection.dispose);
int count = 0; int count = 0;
selection.addListener(() { selection.addListener(() {
count++; count++;
...@@ -2124,7 +2134,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -2124,7 +2134,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(() => service.toObject(aId), throwsFlutterError); expect(() => service.toObject(aId), throwsFlutterError);
}); });
testWidgets('ext.flutter.inspector.setSelection', (WidgetTester tester) async { testWidgetsWithLeakTracking('ext.flutter.inspector.setSelection', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const Directionality( const Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -2174,7 +2184,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -2174,7 +2184,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(service.selection.currentElement, equals(elementA)); expect(service.selection.currentElement, equals(elementA));
}); });
testWidgets('ext.flutter.inspector.getParentChain', (WidgetTester tester) async { testWidgetsWithLeakTracking('ext.flutter.inspector.getParentChain', (WidgetTester tester) async {
const String group = 'test-group'; const String group = 'test-group';
await tester.pumpWidget( await tester.pumpWidget(
...@@ -2246,7 +2256,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -2246,7 +2256,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
} }
}); });
testWidgets('ext.flutter.inspector.getChildren', (WidgetTester tester) async { testWidgetsWithLeakTracking('ext.flutter.inspector.getChildren', (WidgetTester tester) async {
const String group = 'test-group'; const String group = 'test-group';
await tester.pumpWidget( await tester.pumpWidget(
...@@ -2276,7 +2286,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -2276,7 +2286,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
} }
}); });
testWidgets('ext.flutter.inspector.getChildrenDetailsSubtree', (WidgetTester tester) async { testWidgetsWithLeakTracking('ext.flutter.inspector.getChildrenDetailsSubtree', (WidgetTester tester) async {
const String group = 'test-group'; const String group = 'test-group';
await tester.pumpWidget( await tester.pumpWidget(
...@@ -2315,7 +2325,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -2315,7 +2325,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
} }
}); });
testWidgets('WidgetInspectorService getDetailsSubtree', (WidgetTester tester) async { testWidgetsWithLeakTracking('WidgetInspectorService getDetailsSubtree', (WidgetTester tester) async {
const String group = 'test-group'; const String group = 'test-group';
await tester.pumpWidget( await tester.pumpWidget(
...@@ -2371,7 +2381,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -2371,7 +2381,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
} }
}); });
testWidgets('cyclic diagnostics regression test', (WidgetTester tester) async { testWidgetsWithLeakTracking('cyclic diagnostics regression test', (WidgetTester tester) async {
const String group = 'test-group'; const String group = 'test-group';
final CyclicDiagnostic a = CyclicDiagnostic('a'); final CyclicDiagnostic a = CyclicDiagnostic('a');
final CyclicDiagnostic b = CyclicDiagnostic('b'); final CyclicDiagnostic b = CyclicDiagnostic('b');
...@@ -2407,7 +2417,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -2407,7 +2417,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(nestedRelatedProperty, isNot(contains('children'))); expect(nestedRelatedProperty, isNot(contains('children')));
}); });
testWidgets('ext.flutter.inspector.getRootWidgetSummaryTree', (WidgetTester tester) async { testWidgetsWithLeakTracking('ext.flutter.inspector.getRootWidgetSummaryTree', (WidgetTester tester) async {
const String group = 'test-group'; const String group = 'test-group';
await tester.pumpWidget( await tester.pumpWidget(
const Directionality( const Directionality(
...@@ -2517,7 +2527,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -2517,7 +2527,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(childJson['chidlren'], isNull); expect(childJson['chidlren'], isNull);
}, skip: !WidgetInspectorService.instance.isWidgetCreationTracked()); // [intended] Test requires --track-widget-creation flag. }, skip: !WidgetInspectorService.instance.isWidgetCreationTracked()); // [intended] Test requires --track-widget-creation flag.
testWidgets('ext.flutter.inspector.getRootWidgetSummaryTreeWithPreviews', (WidgetTester tester) async { testWidgetsWithLeakTracking('ext.flutter.inspector.getRootWidgetSummaryTreeWithPreviews', (WidgetTester tester) async {
const String group = 'test-group'; const String group = 'test-group';
await tester.pumpWidget( await tester.pumpWidget(
...@@ -2608,7 +2618,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -2608,7 +2618,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(childJson['textPreview'], equals('c')); expect(childJson['textPreview'], equals('c'));
}, skip: !WidgetInspectorService.instance.isWidgetCreationTracked()); // [intended] Test requires --track-widget-creation flag. }, skip: !WidgetInspectorService.instance.isWidgetCreationTracked()); // [intended] Test requires --track-widget-creation flag.
testWidgets('ext.flutter.inspector.getSelectedSummaryWidget', (WidgetTester tester) async { testWidgetsWithLeakTracking('ext.flutter.inspector.getSelectedSummaryWidget', (WidgetTester tester) async {
const String group = 'test-group'; const String group = 'test-group';
await tester.pumpWidget( await tester.pumpWidget(
...@@ -2679,7 +2689,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -2679,7 +2689,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(service.toObject(regularSelection['valueId']! as String), richTextDiagnostic.value); expect(service.toObject(regularSelection['valueId']! as String), richTextDiagnostic.value);
}, skip: !WidgetInspectorService.instance.isWidgetCreationTracked()); // [intended] Test requires --track-widget-creation flag. }, skip: !WidgetInspectorService.instance.isWidgetCreationTracked()); // [intended] Test requires --track-widget-creation flag.
testWidgets('ext.flutter.inspector creationLocation', (WidgetTester tester) async { testWidgetsWithLeakTracking('ext.flutter.inspector creationLocation', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
const Directionality( const Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -2741,7 +2751,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -2741,7 +2751,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
service.resetPubRootDirectories(); service.resetPubRootDirectories();
}); });
testWidgets( testWidgetsWithLeakTracking(
'has createdByLocalProject when the widget is in the pubRootDirectory', 'has createdByLocalProject when the widget is in the pubRootDirectory',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -2774,7 +2784,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -2774,7 +2784,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'does not have createdByLocalProject if the prefix of the pubRootDirectory is different', 'does not have createdByLocalProject if the prefix of the pubRootDirectory is different',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -2807,7 +2817,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -2807,7 +2817,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'has createdByLocalProject if the pubRootDirectory is prefixed with file://', 'has createdByLocalProject if the pubRootDirectory is prefixed with file://',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -2840,7 +2850,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -2840,7 +2850,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'does not have createdByLocalProject if the pubRootDirectory has a different suffix', 'does not have createdByLocalProject if the pubRootDirectory has a different suffix',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -2873,7 +2883,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -2873,7 +2883,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'has createdByLocalProject if at least one of the pubRootDirectories matches', 'has createdByLocalProject if at least one of the pubRootDirectories matches',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -2910,7 +2920,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -2910,7 +2920,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'widget is part of core framework and is the child of a widget in the package pubRootDirectories', 'widget is part of core framework and is the child of a widget in the package pubRootDirectories',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -3021,7 +3031,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -3021,7 +3031,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
service.resetPubRootDirectories(); service.resetPubRootDirectories();
}); });
testWidgets( testWidgetsWithLeakTracking(
'has createdByLocalProject when the widget is in the pubRootDirectory', 'has createdByLocalProject when the widget is in the pubRootDirectory',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -3053,7 +3063,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -3053,7 +3063,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'does not have createdByLocalProject if the prefix of the pubRootDirectory is different', 'does not have createdByLocalProject if the prefix of the pubRootDirectory is different',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -3088,7 +3098,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -3088,7 +3098,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'has createdByLocalProject if the pubRootDirectory is prefixed with file://', 'has createdByLocalProject if the pubRootDirectory is prefixed with file://',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -3120,7 +3130,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -3120,7 +3130,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'does not have createdByLocalProject if the pubRootDirectory has a different suffix', 'does not have createdByLocalProject if the pubRootDirectory has a different suffix',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -3155,7 +3165,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -3155,7 +3165,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'has createdByLocalProject if at least one of the pubRootDirectories matches', 'has createdByLocalProject if at least one of the pubRootDirectories matches',
(WidgetTester tester) async { (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
...@@ -3213,7 +3223,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -3213,7 +3223,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
service.resetPubRootDirectories(); service.resetPubRootDirectories();
}); });
testWidgets( testWidgetsWithLeakTracking(
'reacts to add and removing pubRootDirectories', 'reacts to add and removing pubRootDirectories',
(WidgetTester tester) async { (WidgetTester tester) async {
const Widget widget = Directionality( const Widget widget = Directionality(
...@@ -3263,7 +3273,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -3263,7 +3273,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'does not match when the package directory does not match', 'does not match when the package directory does not match',
(WidgetTester tester) async { (WidgetTester tester) async {
const Widget widget = Directionality( const Widget widget = Directionality(
...@@ -3297,7 +3307,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -3297,7 +3307,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'has createdByLocalProject when the pubRootDirectory is prefixed with file://', 'has createdByLocalProject when the pubRootDirectory is prefixed with file://',
(WidgetTester tester) async { (WidgetTester tester) async {
const Widget widget = Directionality( const Widget widget = Directionality(
...@@ -3328,7 +3338,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -3328,7 +3338,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'can handle consecutive calls to add', 'can handle consecutive calls to add',
(WidgetTester tester) async { (WidgetTester tester) async {
const Widget widget = Directionality( const Widget widget = Directionality(
...@@ -3362,7 +3372,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -3362,7 +3372,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
); );
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'can handle removing an unrelated pubRootDirectory', 'can handle removing an unrelated pubRootDirectory',
(WidgetTester tester) async { (WidgetTester tester) async {
const Widget widget = Directionality( const Widget widget = Directionality(
...@@ -3408,7 +3418,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -3408,7 +3418,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'can handle parent widget being part of a separate package', 'can handle parent widget being part of a separate package',
(WidgetTester tester) async { (WidgetTester tester) async {
const Widget widget = Directionality( const Widget widget = Directionality(
...@@ -3519,7 +3529,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -3519,7 +3529,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
service.resetPubRootDirectories(); service.resetPubRootDirectories();
}); });
testWidgets( testWidgetsWithLeakTracking(
'reacts to add and removing pubRootDirectories', 'reacts to add and removing pubRootDirectories',
(WidgetTester tester) async { (WidgetTester tester) async {
const Widget widget = Directionality( const Widget widget = Directionality(
...@@ -3571,7 +3581,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -3571,7 +3581,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'does not match when the package directory does not match', 'does not match when the package directory does not match',
(WidgetTester tester) async { (WidgetTester tester) async {
const Widget widget = Directionality( const Widget widget = Directionality(
...@@ -3605,7 +3615,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -3605,7 +3615,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'has createdByLocalProject when the pubRootDirectory is prefixed with file://', 'has createdByLocalProject when the pubRootDirectory is prefixed with file://',
(WidgetTester tester) async { (WidgetTester tester) async {
const Widget widget = Directionality( const Widget widget = Directionality(
...@@ -3639,7 +3649,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -3639,7 +3649,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'can handle consecutive calls to add', 'can handle consecutive calls to add',
(WidgetTester tester) async { (WidgetTester tester) async {
const Widget widget = Directionality( const Widget widget = Directionality(
...@@ -3679,7 +3689,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -3679,7 +3689,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
); );
}, },
); );
testWidgets( testWidgetsWithLeakTracking(
'can handle removing an unrelated pubRootDirectory', 'can handle removing an unrelated pubRootDirectory',
(WidgetTester tester) async { (WidgetTester tester) async {
const Widget widget = Directionality( const Widget widget = Directionality(
...@@ -3738,7 +3748,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -3738,7 +3748,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
skip: !WidgetInspectorService.instance.isWidgetCreationTracked(), // [intended] Test requires --track-widget-creation flag. skip: !WidgetInspectorService.instance.isWidgetCreationTracked(), // [intended] Test requires --track-widget-creation flag.
); );
testWidgets('ext.flutter.inspector.trackRebuildDirtyWidgets with tear-offs', (WidgetTester tester) async { testWidgetsWithLeakTracking('ext.flutter.inspector.trackRebuildDirtyWidgets with tear-offs', (WidgetTester tester) async {
final Widget widget = Directionality( final Widget widget = Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: WidgetInspector( child: WidgetInspector(
...@@ -3760,7 +3770,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -3760,7 +3770,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
skip: !WidgetInspectorService.instance.isWidgetCreationTracked(), // [intended] Test requires --track-widget-creation flag. skip: !WidgetInspectorService.instance.isWidgetCreationTracked(), // [intended] Test requires --track-widget-creation flag.
); );
testWidgets('ext.flutter.inspector.trackRebuildDirtyWidgets', (WidgetTester tester) async { testWidgetsWithLeakTracking('ext.flutter.inspector.trackRebuildDirtyWidgets', (WidgetTester tester) async {
service.rebuildCount = 0; service.rebuildCount = 0;
await tester.pumpWidget(const ClockDemo()); await tester.pumpWidget(const ClockDemo());
...@@ -3865,7 +3875,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -3865,7 +3875,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
_CreationLocation location = knownLocations[id]!; _CreationLocation location = knownLocations[id]!;
expect(location.file, equals(file)); expect(location.file, equals(file));
// ClockText widget. // ClockText widget.
expect(location.line, equals(56)); expect(location.line, equals(57));
expect(location.column, equals(9)); expect(location.column, equals(9));
expect(location.name, equals('ClockText')); expect(location.name, equals('ClockText'));
expect(count, equals(1)); expect(count, equals(1));
...@@ -3875,7 +3885,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -3875,7 +3885,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
location = knownLocations[id]!; location = knownLocations[id]!;
expect(location.file, equals(file)); expect(location.file, equals(file));
// Text widget in _ClockTextState build method. // Text widget in _ClockTextState build method.
expect(location.line, equals(94)); expect(location.line, equals(95));
expect(location.column, equals(12)); expect(location.column, equals(12));
expect(location.name, equals('Text')); expect(location.name, equals('Text'));
expect(count, equals(1)); expect(count, equals(1));
...@@ -3902,7 +3912,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -3902,7 +3912,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
location = knownLocations[id]!; location = knownLocations[id]!;
expect(location.file, equals(file)); expect(location.file, equals(file));
// ClockText widget. // ClockText widget.
expect(location.line, equals(56)); expect(location.line, equals(57));
expect(location.column, equals(9)); expect(location.column, equals(9));
expect(location.name, equals('ClockText')); expect(location.name, equals('ClockText'));
expect(count, equals(3)); // 3 clock widget instances rebuilt. expect(count, equals(3)); // 3 clock widget instances rebuilt.
...@@ -3912,7 +3922,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -3912,7 +3922,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
location = knownLocations[id]!; location = knownLocations[id]!;
expect(location.file, equals(file)); expect(location.file, equals(file));
// Text widget in _ClockTextState build method. // Text widget in _ClockTextState build method.
expect(location.line, equals(94)); expect(location.line, equals(95));
expect(location.column, equals(12)); expect(location.column, equals(12));
expect(location.name, equals('Text')); expect(location.name, equals('Text'));
expect(count, equals(3)); // 3 clock widget instances rebuilt. expect(count, equals(3)); // 3 clock widget instances rebuilt.
...@@ -3979,7 +3989,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -3979,7 +3989,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(rebuildEvents, isEmpty); expect(rebuildEvents, isEmpty);
}, skip: !WidgetInspectorService.instance.isWidgetCreationTracked()); // [intended] Test requires --track-widget-creation flag. }, skip: !WidgetInspectorService.instance.isWidgetCreationTracked()); // [intended] Test requires --track-widget-creation flag.
testWidgets('ext.flutter.inspector.trackRepaintWidgets', (WidgetTester tester) async { testWidgetsWithLeakTracking('ext.flutter.inspector.trackRepaintWidgets', (WidgetTester tester) async {
service.rebuildCount = 0; service.rebuildCount = 0;
await tester.pumpWidget(const ClockDemo()); await tester.pumpWidget(const ClockDemo());
...@@ -4102,7 +4112,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -4102,7 +4112,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(repaintEvents, isEmpty); expect(repaintEvents, isEmpty);
}, skip: !WidgetInspectorService.instance.isWidgetCreationTracked()); // [intended] Test requires --track-widget-creation flag. }, skip: !WidgetInspectorService.instance.isWidgetCreationTracked()); // [intended] Test requires --track-widget-creation flag.
testWidgets('ext.flutter.inspector.show', (WidgetTester tester) async { testWidgetsWithLeakTracking('ext.flutter.inspector.show', (WidgetTester tester) async {
final Iterable<Map<Object, Object?>> extensionChangedEvents = service.getServiceExtensionStateChangedEvents('ext.flutter.inspector.show'); final Iterable<Map<Object, Object?>> extensionChangedEvents = service.getServiceExtensionStateChangedEvents('ext.flutter.inspector.show');
Map<Object, Object?> extensionChangedEvent; Map<Object, Object?> extensionChangedEvent;
...@@ -4164,7 +4174,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -4164,7 +4174,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(WidgetsApp.debugShowWidgetInspectorOverride, isFalse); expect(WidgetsApp.debugShowWidgetInspectorOverride, isFalse);
}); });
testWidgets('ext.flutter.inspector.screenshot', (WidgetTester tester) async { testWidgetsWithLeakTracking('ext.flutter.inspector.screenshot', (WidgetTester tester) async {
final GlobalKey outerContainerKey = GlobalKey(); final GlobalKey outerContainerKey = GlobalKey();
final GlobalKey paddingKey = GlobalKey(); final GlobalKey paddingKey = GlobalKey();
final GlobalKey redContainerKey = GlobalKey(); final GlobalKey redContainerKey = GlobalKey();
...@@ -4230,26 +4240,38 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -4230,26 +4240,38 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
final OffsetLayer layer = renderObject.debugLayer! as OffsetLayer; final OffsetLayer layer = renderObject.debugLayer! as OffsetLayer;
final int expectedChildLayerCount = getChildLayerCount(layer); final int expectedChildLayerCount = getChildLayerCount(layer);
expect(expectedChildLayerCount, equals(2)); expect(expectedChildLayerCount, equals(2));
final ui.Image image1 = await layer.toImage(
renderObject.semanticBounds.inflate(50.0),
);
addTearDown(image1.dispose);
await expectLater( await expectLater(
layer.toImage(renderObject.semanticBounds.inflate(50.0)), image1,
matchesGoldenFile('inspector.repaint_boundary_margin.png'), matchesGoldenFile('inspector.repaint_boundary_margin.png'),
); );
// Regression test for how rendering with a pixel scale other than 1.0 // Regression test for how rendering with a pixel scale other than 1.0
// was handled. // was handled.
final ui.Image image2 = await layer.toImage(
renderObject.semanticBounds.inflate(50.0),
pixelRatio: 0.5,
);
addTearDown(image2.dispose);
await expectLater( await expectLater(
layer.toImage( image2,
renderObject.semanticBounds.inflate(50.0),
pixelRatio: 0.5,
),
matchesGoldenFile('inspector.repaint_boundary_margin_small.png'), matchesGoldenFile('inspector.repaint_boundary_margin_small.png'),
); );
final ui.Image image3 = await layer.toImage(
renderObject.semanticBounds.inflate(50.0),
pixelRatio: 2.0,
);
addTearDown(image3.dispose);
await expectLater( await expectLater(
layer.toImage( image3,
renderObject.semanticBounds.inflate(50.0),
pixelRatio: 2.0,
),
matchesGoldenFile('inspector.repaint_boundary_margin_large.png'), matchesGoldenFile('inspector.repaint_boundary_margin_large.png'),
); );
...@@ -4259,12 +4281,15 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -4259,12 +4281,15 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(layerParent, isNotNull); expect(layerParent, isNotNull);
expect(firstChild, isNotNull); expect(firstChild, isNotNull);
final ui.Image? screenshot1 = await service.screenshot(
repaintBoundary,
width: 300.0,
height: 300.0,
);
addTearDown(() => screenshot1?.dispose());
await expectLater( await expectLater(
service.screenshot( screenshot1,
repaintBoundary,
width: 300.0,
height: 300.0,
),
matchesGoldenFile('inspector.repaint_boundary.png'), matchesGoldenFile('inspector.repaint_boundary.png'),
); );
...@@ -4275,13 +4300,16 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -4275,13 +4300,16 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
// of the layer. // of the layer.
expect(getChildLayerCount(layer), equals(expectedChildLayerCount)); expect(getChildLayerCount(layer), equals(expectedChildLayerCount));
final ui.Image? screenshot2 = await service.screenshot(
repaintBoundary,
width: 500.0,
height: 500.0,
margin: 50.0,
);
addTearDown(() => screenshot2?.dispose());
await expectLater( await expectLater(
service.screenshot( screenshot2,
repaintBoundary,
width: 500.0,
height: 500.0,
margin: 50.0,
),
matchesGoldenFile('inspector.repaint_boundary_margin.png'), matchesGoldenFile('inspector.repaint_boundary_margin.png'),
); );
...@@ -4295,13 +4323,16 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -4295,13 +4323,16 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
// Make sure taking a screenshot didn't change the parent of the layer. // Make sure taking a screenshot didn't change the parent of the layer.
expect(layer.parent, equals(layerParent)); expect(layer.parent, equals(layerParent));
final ui.Image? screenshot3 = await service.screenshot(
repaintBoundary,
width: 300.0,
height: 300.0,
debugPaint: true,
);
addTearDown(() => screenshot3?.dispose());
await expectLater( await expectLater(
service.screenshot( screenshot3,
repaintBoundary,
width: 300.0,
height: 300.0,
debugPaint: true,
),
matchesGoldenFile('inspector.repaint_boundary_debugPaint.png'), matchesGoldenFile('inspector.repaint_boundary_debugPaint.png'),
); );
// Verify that taking a screenshot with debug paint on did not change // Verify that taking a screenshot with debug paint on did not change
...@@ -4319,22 +4350,28 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -4319,22 +4350,28 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(layer.attached, isTrue); expect(layer.attached, isTrue);
// Full size image // Full size image
final ui.Image? screenshot4 = await service.screenshot(
find.byKey(outerContainerKey).evaluate().single,
width: 100.0,
height: 100.0,
);
addTearDown(() => screenshot4?.dispose());
await expectLater( await expectLater(
service.screenshot( screenshot4,
find.byKey(outerContainerKey).evaluate().single,
width: 100.0,
height: 100.0,
),
matchesGoldenFile('inspector.container.png'), matchesGoldenFile('inspector.container.png'),
); );
final ui.Image? screenshot5 = await service.screenshot(
find.byKey(outerContainerKey).evaluate().single,
width: 100.0,
height: 100.0,
debugPaint: true,
);
addTearDown(() => screenshot5?.dispose());
await expectLater( await expectLater(
service.screenshot( screenshot5,
find.byKey(outerContainerKey).evaluate().single,
width: 100.0,
height: 100.0,
debugPaint: true,
),
matchesGoldenFile('inspector.container_debugPaint.png'), matchesGoldenFile('inspector.container_debugPaint.png'),
); );
...@@ -4348,59 +4385,73 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -4348,59 +4385,73 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
..markNeedsPaint(); ..markNeedsPaint();
expect(container.debugNeedsLayout, isTrue); expect(container.debugNeedsLayout, isTrue);
final ui.Image? screenshot6 = await service.screenshot(
find.byKey(outerContainerKey).evaluate().single,
width: 100.0,
height: 100.0,
debugPaint: true,
);
addTearDown(() => screenshot6?.dispose());
await expectLater( await expectLater(
service.screenshot( screenshot6,
find.byKey(outerContainerKey).evaluate().single,
width: 100.0,
height: 100.0,
debugPaint: true,
),
matchesGoldenFile('inspector.container_debugPaint.png'), matchesGoldenFile('inspector.container_debugPaint.png'),
); );
expect(container.debugNeedsLayout, isFalse); expect(container.debugNeedsLayout, isFalse);
} }
// Small image // Small image
final ui.Image? screenshot7 = await service.screenshot(
find.byKey(outerContainerKey).evaluate().single,
width: 50.0,
height: 100.0,
);
addTearDown(() => screenshot7?.dispose());
await expectLater( await expectLater(
service.screenshot( screenshot7,
find.byKey(outerContainerKey).evaluate().single,
width: 50.0,
height: 100.0,
),
matchesGoldenFile('inspector.container_small.png'), matchesGoldenFile('inspector.container_small.png'),
); );
final ui.Image? screenshot8 = await service.screenshot(
find.byKey(outerContainerKey).evaluate().single,
width: 400.0,
height: 400.0,
maxPixelRatio: 3.0,
);
addTearDown(() => screenshot8?.dispose());
await expectLater( await expectLater(
service.screenshot( screenshot8,
find.byKey(outerContainerKey).evaluate().single,
width: 400.0,
height: 400.0,
maxPixelRatio: 3.0,
),
matchesGoldenFile('inspector.container_large.png'), matchesGoldenFile('inspector.container_large.png'),
); );
// This screenshot will show the clip rect debug paint but no other // This screenshot will show the clip rect debug paint but no other
// debug paint. // debug paint.
final ui.Image? screenshot9 = await service.screenshot(
find.byType(ClipRRect).evaluate().single,
width: 100.0,
height: 100.0,
debugPaint: true,
);
addTearDown(() => screenshot9?.dispose());
await expectLater( await expectLater(
service.screenshot( screenshot9,
find.byType(ClipRRect).evaluate().single,
width: 100.0,
height: 100.0,
debugPaint: true,
),
matchesGoldenFile('inspector.clipRect_debugPaint.png'), matchesGoldenFile('inspector.clipRect_debugPaint.png'),
); );
final Element clipRect = find.byType(ClipRRect).evaluate().single; final Element clipRect = find.byType(ClipRRect).evaluate().single;
final Future<ui.Image?> clipRectScreenshot = service.screenshot( final ui.Image? clipRectScreenshot = await service.screenshot(
clipRect, clipRect,
width: 100.0, width: 100.0,
height: 100.0, height: 100.0,
margin: 20.0, margin: 20.0,
debugPaint: true, debugPaint: true,
); );
addTearDown(() => clipRectScreenshot?.dispose());
// Add a margin so that the clip icon shows up in the screenshot. // Add a margin so that the clip icon shows up in the screenshot.
// This golden image is platform dependent due to the clip icon. // This golden image is platform dependent due to the clip icon.
await expectLater( await expectLater(
...@@ -4428,43 +4479,53 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -4428,43 +4479,53 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
final ui.FrameInfo frame = await codec.getNextFrame(); final ui.FrameInfo frame = await codec.getNextFrame();
return frame.image; return frame.image;
}))!; }))!;
addTearDown(screenshotImage.dispose);
await expectLater( await expectLater(
screenshotImage, screenshotImage,
matchesReferenceImage((await clipRectScreenshot)!), matchesReferenceImage(clipRectScreenshot!),
); );
// Test with a very visible debug paint // Test with a very visible debug paint
final ui.Image? screenshot10 = await service.screenshot(
find.byKey(paddingKey).evaluate().single,
width: 300.0,
height: 300.0,
debugPaint: true,
);
addTearDown(() => screenshot10?.dispose());
await expectLater( await expectLater(
service.screenshot( screenshot10,
find.byKey(paddingKey).evaluate().single,
width: 300.0,
height: 300.0,
debugPaint: true,
),
matchesGoldenFile('inspector.padding_debugPaint.png'), matchesGoldenFile('inspector.padding_debugPaint.png'),
); );
// The bounds for this box crop its rendered content. // The bounds for this box crop its rendered content.
final ui.Image? screenshot11 = await service.screenshot(
find.byKey(sizedBoxKey).evaluate().single,
width: 300.0,
height: 300.0,
debugPaint: true,
);
addTearDown(() => screenshot11?.dispose());
await expectLater( await expectLater(
service.screenshot( screenshot11,
find.byKey(sizedBoxKey).evaluate().single,
width: 300.0,
height: 300.0,
debugPaint: true,
),
matchesGoldenFile('inspector.sizedBox_debugPaint.png'), matchesGoldenFile('inspector.sizedBox_debugPaint.png'),
); );
// Verify that setting a margin includes the previously cropped content. // Verify that setting a margin includes the previously cropped content.
final ui.Image? screenshot12 = await service.screenshot(
find.byKey(sizedBoxKey).evaluate().single,
width: 300.0,
height: 300.0,
margin: 50.0,
debugPaint: true,
);
addTearDown(() => screenshot12?.dispose());
await expectLater( await expectLater(
service.screenshot( screenshot12,
find.byKey(sizedBoxKey).evaluate().single,
width: 300.0,
height: 300.0,
margin: 50.0,
debugPaint: true,
),
matchesGoldenFile('inspector.sizedBox_debugPaint_margin.png'), matchesGoldenFile('inspector.sizedBox_debugPaint_margin.png'),
); );
}); });
...@@ -4496,7 +4557,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -4496,7 +4557,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
await tester.pumpWidget(widget); await tester.pumpWidget(widget);
} }
testWidgets('ext.flutter.inspector.getLayoutExplorerNode for RenderBox with BoxParentData',(WidgetTester tester) async { testWidgetsWithLeakTracking('ext.flutter.inspector.getLayoutExplorerNode for RenderBox with BoxParentData',(WidgetTester tester) async {
await pumpWidgetForLayoutExplorer(tester); await pumpWidgetForLayoutExplorer(tester);
final Element rowElement = tester.element(find.byType(Row)); final Element rowElement = tester.element(find.byType(Row));
...@@ -4541,7 +4602,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -4541,7 +4602,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(parentData['offsetY'], equals('293.0')); expect(parentData['offsetY'], equals('293.0'));
}); });
testWidgets('ext.flutter.inspector.getLayoutExplorerNode for RenderBox with FlexParentData',(WidgetTester tester) async { testWidgetsWithLeakTracking('ext.flutter.inspector.getLayoutExplorerNode for RenderBox with FlexParentData',(WidgetTester tester) async {
await pumpWidgetForLayoutExplorer(tester); await pumpWidgetForLayoutExplorer(tester);
final Element flexibleElement = tester.element(find.byType(Flexible).first); final Element flexibleElement = tester.element(find.byType(Flexible).first);
...@@ -4583,7 +4644,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -4583,7 +4644,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(result['parentData'], isNull); expect(result['parentData'], isNull);
}); });
testWidgets('ext.flutter.inspector.getLayoutExplorerNode for RenderView',(WidgetTester tester) async { testWidgetsWithLeakTracking('ext.flutter.inspector.getLayoutExplorerNode for RenderView',(WidgetTester tester) async {
await pumpWidgetForLayoutExplorer(tester); await pumpWidgetForLayoutExplorer(tester);
final Element element = tester.element(find.byType(Directionality).first); final Element element = tester.element(find.byType(Directionality).first);
...@@ -4619,7 +4680,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -4619,7 +4680,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(result['parentData'], isNull); expect(result['parentData'], isNull);
}); });
testWidgets('ext.flutter.inspector.setFlexFit', (WidgetTester tester) async { testWidgetsWithLeakTracking('ext.flutter.inspector.setFlexFit', (WidgetTester tester) async {
await pumpWidgetForLayoutExplorer(tester); await pumpWidgetForLayoutExplorer(tester);
final Element childElement = tester.element(find.byType(Flexible).first); final Element childElement = tester.element(find.byType(Flexible).first);
...@@ -4649,7 +4710,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -4649,7 +4710,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(result['flexFit'], equals('tight')); expect(result['flexFit'], equals('tight'));
}); });
testWidgets('ext.flutter.inspector.setFlexFactor', (WidgetTester tester) async { testWidgetsWithLeakTracking('ext.flutter.inspector.setFlexFactor', (WidgetTester tester) async {
await pumpWidgetForLayoutExplorer(tester); await pumpWidgetForLayoutExplorer(tester);
final Element childElement = tester.element(find.byType(Flexible).first); final Element childElement = tester.element(find.byType(Flexible).first);
...@@ -4679,7 +4740,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -4679,7 +4740,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(result['flexFactor'], equals(3)); expect(result['flexFactor'], equals(3));
}); });
testWidgets('ext.flutter.inspector.setFlexProperties', (WidgetTester tester) async { testWidgetsWithLeakTracking('ext.flutter.inspector.setFlexProperties', (WidgetTester tester) async {
await pumpWidgetForLayoutExplorer(tester); await pumpWidgetForLayoutExplorer(tester);
final Element rowElement = tester.element(find.byType(Row).first); final Element rowElement = tester.element(find.byType(Row).first);
...@@ -4742,7 +4803,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -4742,7 +4803,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(crossAxisAlignment, equals('start')); expect(crossAxisAlignment, equals('start'));
}); });
testWidgets('ext.flutter.inspector.getLayoutExplorerNode does not throw StackOverflowError',(WidgetTester tester) async { testWidgetsWithLeakTracking('ext.flutter.inspector.getLayoutExplorerNode does not throw StackOverflowError',(WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/115228 // Regression test for https://github.com/flutter/flutter/issues/115228
const Key leafKey = ValueKey<String>('ColoredBox'); const Key leafKey = ValueKey<String>('ColoredBox');
await tester.pumpWidget( await tester.pumpWidget(
...@@ -4772,7 +4833,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -4772,7 +4833,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(error, isNull); expect(error, isNull);
}); });
testWidgets( testWidgetsWithLeakTracking(
'ext.flutter.inspector.getLayoutExplorerNode, on a ToolTip, does not throw StackOverflowError', 'ext.flutter.inspector.getLayoutExplorerNode, on a ToolTip, does not throw StackOverflowError',
(WidgetTester tester) async { (WidgetTester tester) async {
// Regression test for https://github.com/flutter/devtools/issues/5946 // Regression test for https://github.com/flutter/devtools/issues/5946
...@@ -4904,7 +4965,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -4904,7 +4965,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
} }
}); });
testWidgets('Screenshot of composited transforms - only offsets', (WidgetTester tester) async { testWidgetsWithLeakTracking('Screenshot of composited transforms - only offsets', (WidgetTester tester) async {
// Composited transforms are challenging to take screenshots of as the // Composited transforms are challenging to take screenshots of as the
// LeaderLayer and FollowerLayer classes used by CompositedTransformTarget // LeaderLayer and FollowerLayer classes used by CompositedTransformTarget
// and CompositedTransformFollower depend on traversing ancestors of the // and CompositedTransformFollower depend on traversing ancestors of the
...@@ -4974,31 +5035,44 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -4974,31 +5035,44 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
matchesGoldenFile('inspector.composited_transform.only_offsets.png'), matchesGoldenFile('inspector.composited_transform.only_offsets.png'),
); );
final ui.Image? screenshot1 = await WidgetInspectorService.instance.screenshot(
find.byKey(stackWithTransformFollower).evaluate().first,
width: 5000.0,
height: 500.0,
);
addTearDown(() => screenshot1?.dispose());
await expectLater( await expectLater(
WidgetInspectorService.instance.screenshot( screenshot1,
find.byKey(stackWithTransformFollower).evaluate().first,
width: 5000.0,
height: 500.0,
),
matchesGoldenFile('inspector.composited_transform.only_offsets_follower.png'), matchesGoldenFile('inspector.composited_transform.only_offsets_follower.png'),
); );
final ui.Image? screenshot2 = await WidgetInspectorService.instance.screenshot(
find.byType(Stack).evaluate().first,
width: 300.0,
height: 300.0,
);
addTearDown(() => screenshot2?.dispose());
await expectLater( await expectLater(
WidgetInspectorService.instance.screenshot(find.byType(Stack).evaluate().first, width: 300.0, height: 300.0), screenshot2,
matchesGoldenFile('inspector.composited_transform.only_offsets_small.png'), matchesGoldenFile('inspector.composited_transform.only_offsets_small.png'),
); );
final ui.Image? screenshot3 = await WidgetInspectorService.instance.screenshot(
find.byKey(transformTargetParent).evaluate().first,
width: 500.0,
height: 500.0,
);
addTearDown(() => screenshot3?.dispose());
await expectLater( await expectLater(
WidgetInspectorService.instance.screenshot( screenshot3,
find.byKey(transformTargetParent).evaluate().first,
width: 500.0,
height: 500.0,
),
matchesGoldenFile('inspector.composited_transform.only_offsets_target.png'), matchesGoldenFile('inspector.composited_transform.only_offsets_target.png'),
); );
}); });
testWidgets('Screenshot composited transforms - with rotations', (WidgetTester tester) async { testWidgetsWithLeakTracking('Screenshot composited transforms - with rotations', (WidgetTester tester) async {
final LayerLink link = LayerLink(); final LayerLink link = LayerLink();
final GlobalKey key1 = GlobalKey(); final GlobalKey key1 = GlobalKey();
final GlobalKey key2 = GlobalKey(); final GlobalKey key2 = GlobalKey();
...@@ -5069,30 +5143,39 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -5069,30 +5143,39 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
matchesGoldenFile('inspector.composited_transform.with_rotations.png'), matchesGoldenFile('inspector.composited_transform.with_rotations.png'),
); );
final ui.Image? screenshot1 = await WidgetInspectorService.instance.screenshot(
find.byKey(mainStackKey).evaluate().first,
width: 500.0,
height: 500.0,
);
addTearDown(() => screenshot1?.dispose());
await expectLater( await expectLater(
WidgetInspectorService.instance.screenshot( screenshot1,
find.byKey(mainStackKey).evaluate().first,
width: 500.0,
height: 500.0,
),
matchesGoldenFile('inspector.composited_transform.with_rotations_small.png'), matchesGoldenFile('inspector.composited_transform.with_rotations_small.png'),
); );
final ui.Image? screenshot2 = await WidgetInspectorService.instance.screenshot(
find.byKey(stackWithTransformTarget).evaluate().first,
width: 500.0,
height: 500.0,
);
addTearDown(() => screenshot2?.dispose());
await expectLater( await expectLater(
WidgetInspectorService.instance.screenshot( screenshot2,
find.byKey(stackWithTransformTarget).evaluate().first,
width: 500.0,
height: 500.0,
),
matchesGoldenFile('inspector.composited_transform.with_rotations_target.png'), matchesGoldenFile('inspector.composited_transform.with_rotations_target.png'),
); );
final ui.Image? screenshot3 = await WidgetInspectorService.instance.screenshot(
find.byKey(stackWithTransformFollower).evaluate().first,
width: 500.0,
height: 500.0,
);
addTearDown(() => screenshot3?.dispose());
await expectLater( await expectLater(
WidgetInspectorService.instance.screenshot( screenshot3,
find.byKey(stackWithTransformFollower).evaluate().first,
width: 500.0,
height: 500.0,
),
matchesGoldenFile('inspector.composited_transform.with_rotations_follower.png'), matchesGoldenFile('inspector.composited_transform.with_rotations_follower.png'),
); );
...@@ -5104,7 +5187,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -5104,7 +5187,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(box2.localToGlobal(Offset.zero), equals(position2)); expect(box2.localToGlobal(Offset.zero), equals(position2));
}); });
testWidgets('getChildrenDetailsSubtree', (WidgetTester tester) async { testWidgetsWithLeakTracking('getChildrenDetailsSubtree', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
title: 'Hello, World', title: 'Hello, World',
...@@ -5164,7 +5247,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -5164,7 +5247,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(appBars.single, isNot(contains('children'))); expect(appBars.single, isNot(contains('children')));
}, skip: !WidgetInspectorService.instance.isWidgetCreationTracked()); // [intended] Test requires --track-widget-creation flag. }, skip: !WidgetInspectorService.instance.isWidgetCreationTracked()); // [intended] Test requires --track-widget-creation flag.
testWidgets('InspectorSerializationDelegate addAdditionalPropertiesCallback', (WidgetTester tester) async { testWidgetsWithLeakTracking('InspectorSerializationDelegate addAdditionalPropertiesCallback', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
title: 'Hello World!', title: 'Hello World!',
...@@ -5233,7 +5316,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -5233,7 +5316,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(node.toJsonMap(emptyDelegate), node.toJsonMap(defaultDelegate)); expect(node.toJsonMap(emptyDelegate), node.toJsonMap(defaultDelegate));
}); });
testWidgets('debugIsLocalCreationLocation test', (WidgetTester tester) async { testWidgetsWithLeakTracking('debugIsLocalCreationLocation test', (WidgetTester tester) async {
setupDefaultPubRootDirectory(service); setupDefaultPubRootDirectory(service);
final GlobalKey key = GlobalKey(); final GlobalKey key = GlobalKey();
...@@ -5262,7 +5345,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -5262,7 +5345,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(debugIsLocalCreationLocation(paddingElement.widget), isFalse); expect(debugIsLocalCreationLocation(paddingElement.widget), isFalse);
}, skip: !WidgetInspectorService.instance.isWidgetCreationTracked()); // [intended] Test requires --track-widget-creation flag. }, skip: !WidgetInspectorService.instance.isWidgetCreationTracked()); // [intended] Test requires --track-widget-creation flag.
testWidgets('debugIsWidgetLocalCreation test', (WidgetTester tester) async { testWidgetsWithLeakTracking('debugIsWidgetLocalCreation test', (WidgetTester tester) async {
setupDefaultPubRootDirectory(service); setupDefaultPubRootDirectory(service);
final GlobalKey key = GlobalKey(); final GlobalKey key = GlobalKey();
...@@ -5285,7 +5368,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ...@@ -5285,7 +5368,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(debugIsWidgetLocalCreation(paddingElement.widget), isFalse); expect(debugIsWidgetLocalCreation(paddingElement.widget), isFalse);
}, skip: !WidgetInspectorService.instance.isWidgetCreationTracked()); // [intended] Test requires --track-widget-creation flag. }, skip: !WidgetInspectorService.instance.isWidgetCreationTracked()); // [intended] Test requires --track-widget-creation flag.
testWidgets('debugIsWidgetLocalCreation false test', (WidgetTester tester) async { testWidgetsWithLeakTracking('debugIsWidgetLocalCreation false test', (WidgetTester tester) async {
final GlobalKey key = GlobalKey(); final GlobalKey key = GlobalKey();
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