Turn on avoid_dynamic_calls lint, make appropriate changes. (#84478)

This commit is contained in:
Greg Spencer 2021-06-23 16:36:03 -07:00 committed by GitHub
parent 0ea4303714
commit 1ac209c222
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
46 changed files with 370 additions and 217 deletions

View file

@ -1,7 +0,0 @@
include: ../analysis_options.yaml
linter:
rules:
# Turn off for tests, since we often use dynamic as a method to obtain a
# reference to a private state object or renderer in tests.
avoid_dynamic_calls: false

View file

@ -2,17 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui' as ui;
import 'package:flutter/cupertino.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
import '../widgets/semantics_tester.dart';
dynamic getRenderSegmentedControl(WidgetTester tester) {
RenderBox getRenderSegmentedControl(WidgetTester tester) {
return tester.allRenderObjects.firstWhere(
(RenderObject currentObject) {
return currentObject.toStringShort().contains('_RenderSegmentedControl');
},
);
) as RenderBox;
}
StatefulBuilder setupSimpleSegmentedControl() {
@ -45,8 +48,41 @@ Widget boilerplate({ required Widget child }) {
);
}
int getChildCount(WidgetTester tester) {
return (getRenderSegmentedControl(tester) as RenderBoxContainerDefaultsMixin<RenderBox, ContainerBoxParentData<RenderBox>>)
.getChildrenAsList().length;
}
ui.RRect getSurroundingRect(WidgetTester tester, {int child = 0}) {
// Using dynamic so the test can access private classes.
// ignore: avoid_dynamic_calls
return ((getRenderSegmentedControl(tester) as RenderBoxContainerDefaultsMixin<RenderBox, ContainerBoxParentData<RenderBox>>)
.getChildrenAsList()[child].parentData! as dynamic).surroundingRect as ui.RRect;
}
Size getChildSize(WidgetTester tester, {int child = 0}) {
// Using dynamic so the test can access private classes.
// ignore: avoid_dynamic_calls
return ((getRenderSegmentedControl(tester) as RenderBoxContainerDefaultsMixin<RenderBox, ContainerBoxParentData<RenderBox>>)
.getChildrenAsList()[child]).size;
}
Color getBorderColor(WidgetTester tester) {
// Using dynamic so the test can access a private class.
// ignore: avoid_dynamic_calls
return (getRenderSegmentedControl(tester) as dynamic).borderColor as Color;
}
int? getSelectedIndex(WidgetTester tester) {
// Using dynamic so the test can access a private class.
// ignore: avoid_dynamic_calls
return (getRenderSegmentedControl(tester) as dynamic).selectedIndex as int?;
}
Color getBackgroundColor(WidgetTester tester, int childIndex) {
return getRenderSegmentedControl(tester).backgroundColors[childIndex] as Color;
// Using dynamic so the test can access a private class.
// ignore: avoid_dynamic_calls
return (getRenderSegmentedControl(tester) as dynamic).backgroundColors[childIndex] as Color;
}
void main() {
@ -349,7 +385,7 @@ void main() {
DefaultTextStyle textStyle = tester.widget(find.widgetWithText(DefaultTextStyle, 'Child 1'));
IconTheme iconTheme = tester.widget(find.widgetWithIcon(IconTheme, const IconData(1)));
expect(getRenderSegmentedControl(tester).borderColor, CupertinoColors.black);
expect(getBorderColor(tester), CupertinoColors.black);
expect(textStyle.style.color, CupertinoColors.lightBackgroundGray);
expect(iconTheme.data.color, CupertinoColors.activeGreen.color);
expect(getBackgroundColor(tester, 0), CupertinoColors.activeGreen.color);
@ -517,7 +553,7 @@ void main() {
testWidgets('Passed in value is child initially selected', (WidgetTester tester) async {
await tester.pumpWidget(setupSimpleSegmentedControl());
expect(getRenderSegmentedControl(tester).selectedIndex, 0);
expect(getSelectedIndex(tester), 0);
expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue);
expect(getBackgroundColor(tester, 1), isSameColorAs(CupertinoColors.white));
@ -548,7 +584,7 @@ void main() {
),
);
expect(getRenderSegmentedControl(tester).selectedIndex, null);
expect(getSelectedIndex(tester), null);
expect(getBackgroundColor(tester, 0), isSameColorAs(CupertinoColors.white));
expect(getBackgroundColor(tester, 1), isSameColorAs(CupertinoColors.white));
@ -647,9 +683,9 @@ void main() {
expect(childWidth, 200.0);
expect(childWidth, getRenderSegmentedControl(tester).getChildrenAsList()[0].parentData.surroundingRect.width);
expect(childWidth, getRenderSegmentedControl(tester).getChildrenAsList()[1].parentData.surroundingRect.width);
expect(childWidth, getRenderSegmentedControl(tester).getChildrenAsList()[2].parentData.surroundingRect.width);
expect(childWidth, getSurroundingRect(tester, child: 0).width);
expect(childWidth, getSurroundingRect(tester, child: 1).width);
expect(childWidth, getSurroundingRect(tester, child: 2).width);
});
testWidgets('Width is finite in unbounded space', (WidgetTester tester) async {
@ -874,7 +910,7 @@ void main() {
expect(sharedValue, 1);
final double childWidth = getRenderSegmentedControl(tester).firstChild.size.width as double;
final double childWidth = getChildSize(tester, child: 0).width;
final Offset centerOfSegmentedControl = tester.getCenter(find.text('Child 1'));
// Tap just inside segment bounds
@ -1359,13 +1395,13 @@ void main() {
),
);
expect(getRenderSegmentedControl(tester).getChildrenAsList().length, 3);
expect(getChildCount(tester), 3);
await tester.tap(find.text('B'));
await tester.pump();
expect(getBackgroundColor(tester, 1), const Color(0x33007aff));
expect(getRenderSegmentedControl(tester).getChildrenAsList().length, 2);
expect(getChildCount(tester), 2);
await tester.pump(const Duration(milliseconds: 40));
expect(getBackgroundColor(tester, 1), const Color(0x64007aff));
@ -1405,12 +1441,12 @@ void main() {
),
);
expect(getRenderSegmentedControl(tester).getChildrenAsList().length, 3);
expect(getChildCount(tester), 3);
await tester.tap(find.text('B'));
await tester.pump();
expect(getRenderSegmentedControl(tester).getChildrenAsList().length, 2);
expect(getChildCount(tester), 2);
await tester.pump(const Duration(milliseconds: 40));
expect(getBackgroundColor(tester, 0), const Color(0xff3d9aff));

View file

@ -10,16 +10,18 @@ import 'package:flutter_test/flutter_test.dart';
import '../widgets/semantics_tester.dart';
dynamic getRenderSegmentedControl(WidgetTester tester) {
RenderBox getRenderSegmentedControl(WidgetTester tester) {
return tester.allRenderObjects.firstWhere(
(RenderObject currentObject) {
return currentObject.toStringShort().contains('_RenderSegmentedControl');
},
);
) as RenderBox;
}
Rect currentUnscaledThumbRect(WidgetTester tester, { bool useGlobalCoordinate = false }) {
final dynamic renderSegmentedControl = getRenderSegmentedControl(tester);
// Using dynamic to access private class in test.
// ignore: avoid_dynamic_calls
final Rect local = renderSegmentedControl.currentThumbRect as Rect;
if (!useGlobalCoordinate)
return local;
@ -28,7 +30,23 @@ Rect currentUnscaledThumbRect(WidgetTester tester, { bool useGlobalCoordinate =
return local.shift(segmentedControl.localToGlobal(Offset.zero));
}
double currentThumbScale(WidgetTester tester) => getRenderSegmentedControl(tester).thumbScale as double;
int? getHighlightedIndex(WidgetTester tester) {
// Using dynamic to access private class in test.
// ignore: avoid_dynamic_calls
return (getRenderSegmentedControl(tester) as dynamic).highlightedIndex as int?;
}
Color getThumbColor(WidgetTester tester) {
// Using dynamic to access private class in test.
// ignore: avoid_dynamic_calls
return (getRenderSegmentedControl(tester) as dynamic).thumbColor as Color;
}
double currentThumbScale(WidgetTester tester) {
// Using dynamic to access private class in test.
// ignore: avoid_dynamic_calls
return (getRenderSegmentedControl(tester) as dynamic).thumbScale as double;
}
Widget setupSimpleSegmentedControl() {
const Map<int, Widget> children = <int, Widget>{
@ -308,7 +326,7 @@ void main() {
matching: find.byType(Container),
)).decoration! as BoxDecoration;
expect(getRenderSegmentedControl(tester).thumbColor.value, CupertinoColors.systemGreen.color.value);
expect(getThumbColor(tester).value, CupertinoColors.systemGreen.color.value);
expect(decoration.color!.value, CupertinoColors.systemRed.color.value);
setState(() { brightness = Brightness.dark; });
@ -320,7 +338,7 @@ void main() {
)).decoration! as BoxDecoration;
expect(getRenderSegmentedControl(tester).thumbColor.value, CupertinoColors.systemGreen.darkColor.value);
expect(getThumbColor(tester).value, CupertinoColors.systemGreen.darkColor.value);
expect(decorationDark.color!.value, CupertinoColors.systemRed.darkColor.value);
});
@ -351,7 +369,7 @@ void main() {
testWidgets('Passed in value is child initially selected', (WidgetTester tester) async {
await tester.pumpWidget(setupSimpleSegmentedControl());
expect(getRenderSegmentedControl(tester).highlightedIndex, 0);
expect(getHighlightedIndex(tester), 0);
});
testWidgets('Null input for value results in no child initially selected', (WidgetTester tester) async {
@ -377,7 +395,7 @@ void main() {
),
);
expect(getRenderSegmentedControl(tester).highlightedIndex, null);
expect(getHighlightedIndex(tester), null);
});
testWidgets('Long press not-selected child interactions', (WidgetTester tester) async {
@ -606,17 +624,17 @@ void main() {
);
// highlightedIndex is 1 instead of 0 because of RTL.
expect(getRenderSegmentedControl(tester).highlightedIndex, 1);
expect(getHighlightedIndex(tester), 1);
await tester.tap(find.text('Child 2'));
await tester.pump();
expect(getRenderSegmentedControl(tester).highlightedIndex, 0);
expect(getHighlightedIndex(tester), 0);
await tester.tap(find.text('Child 2'));
await tester.pump();
expect(getRenderSegmentedControl(tester).highlightedIndex, 0);
expect(getHighlightedIndex(tester), 0);
});
testWidgets('Segmented control semantics', (WidgetTester tester) async {
@ -894,7 +912,7 @@ void main() {
},
));
final RenderBox renderSegmentedControl = getRenderSegmentedControl(tester) as RenderBox;
final RenderBox renderSegmentedControl = getRenderSegmentedControl(tester);
final Offset segmentedControlOrigin = renderSegmentedControl.localToGlobal(Offset.zero);
// Expect the segmented control to be much narrower.
@ -1185,7 +1203,7 @@ void main() {
),
);
final RenderBox renderBox = getRenderSegmentedControl(tester) as RenderBox;
final RenderBox renderBox = getRenderSegmentedControl(tester);
final Size size = renderBox.getDryLayout(const BoxConstraints());
expect(size.width, greaterThan(10));
@ -1214,7 +1232,7 @@ void main() {
),
);
final RenderBox renderBox = getRenderSegmentedControl(tester) as RenderBox;
final RenderBox renderBox = getRenderSegmentedControl(tester);
final Size size = renderBox.size;
for (final int value in children.keys) {

View file

@ -449,6 +449,7 @@ void main() {
await gesture.up();
await tester.pump();
expect(value, isFalse);
// ignore: avoid_dynamic_calls
final CurvedAnimation position = (tester.state(find.byType(CupertinoSwitch)) as dynamic).position as CurvedAnimation;
expect(position.value, lessThan(0.5));
await tester.pump();

View file

@ -3246,7 +3246,7 @@ void main() {
await tester.showKeyboard(find.byType(EditableText));
final MethodCall setClient = log.first;
expect(setClient.method, 'TextInput.setClient');
expect(setClient.arguments.last['keyboardAppearance'], 'Brightness.dark');
expect(((setClient.arguments as List<dynamic>).last as Map<String, dynamic>)['keyboardAppearance'], 'Brightness.dark');
});
testWidgets('text field can override keyboardAppearance from theme', (WidgetTester tester) async {
@ -3271,7 +3271,7 @@ void main() {
await tester.showKeyboard(find.byType(EditableText));
final MethodCall setClient = log.first;
expect(setClient.method, 'TextInput.setClient');
expect(setClient.arguments.last['keyboardAppearance'], 'Brightness.light');
expect(((setClient.arguments as List<dynamic>).last as Map<String, dynamic>)['keyboardAppearance'], 'Brightness.light');
});
testWidgets('cursorColor respects theme', (WidgetTester tester) async {

View file

@ -59,7 +59,9 @@ void main() {
expect(currentTransform(wrapped), equals(m2 * m1));
result.publicPushTransform(m3);
// ignore: avoid_dynamic_calls
expect(currentTransform(result), equals(m3 * m2 * m1));
// ignore: avoid_dynamic_calls
expect(currentTransform(wrapped), equals(m3 * m2 * m1));
result.publicPopTransform();
@ -103,7 +105,9 @@ void main() {
expect(currentTransform(wrapped), equals(m1 * m3));
result.publicPushTransform(m2);
// ignore: avoid_dynamic_calls
expect(currentTransform(result), equals(m2 * m1 * m3));
// ignore: avoid_dynamic_calls
expect(currentTransform(wrapped), equals(m2 * m1 * m3));
result.publicPopTransform();
@ -115,6 +119,7 @@ void main() {
result.publicPushOffset(o3);
result.publicPushTransform(m1);
// ignore: avoid_dynamic_calls
expect(currentTransform(result), equals(m1 * m3 * m2));
result.publicPopTransform();

View file

@ -326,11 +326,13 @@ void main() {
);
final dynamic exception = tester.takeException();
expect(exception, isA<String>());
expect(exception.startsWith('Could not navigate to initial route.'), isTrue);
expect(find.text('route "/"'), findsOneWidget);
expect(find.text('route "/a"'), findsNothing);
expect(find.text('route "/a/b"'), findsNothing);
expect(find.text('route "/b"'), findsNothing);
if (exception is String) {
expect(exception.startsWith('Could not navigate to initial route.'), isTrue);
expect(find.text('route "/"'), findsOneWidget);
expect(find.text('route "/a"'), findsNothing);
expect(find.text('route "/a/b"'), findsNothing);
expect(find.text('route "/b"'), findsNothing);
}
});
testWidgets('Make sure initialRoute is only used the first time', (WidgetTester tester) async {

View file

@ -63,9 +63,13 @@ dynamic getRenderChip(WidgetTester tester) {
return element.renderObject;
}
// ignore: avoid_dynamic_calls
double getSelectProgress(WidgetTester tester) => getRenderChip(tester)?.checkmarkAnimation?.value as double;
// ignore: avoid_dynamic_calls
double getAvatarDrawerProgress(WidgetTester tester) => getRenderChip(tester)?.avatarDrawerAnimation?.value as double;
// ignore: avoid_dynamic_calls
double getDeleteDrawerProgress(WidgetTester tester) => getRenderChip(tester)?.deleteDrawerAnimation?.value as double;
// ignore: avoid_dynamic_calls
double getEnableProgress(WidgetTester tester) => getRenderChip(tester)?.enableAnimation?.value as double;
/// Adds the basic requirements for a Chip.

View file

@ -796,9 +796,13 @@ void main() {
// fill color and test them against the expected values.
void _testInputDecorator(CustomPaint decoratorPaint, InputBorder expectedBorder, Color expectedContainerColor) {
final dynamic/*_InputBorderPainter*/ inputBorderPainter = decoratorPaint.foregroundPainter;
// ignore: avoid_dynamic_calls
final dynamic/*_InputBorderTween*/ inputBorderTween = inputBorderPainter.border;
// ignore: avoid_dynamic_calls
final Animation<double> animation = inputBorderPainter.borderAnimation as Animation<double>;
// ignore: avoid_dynamic_calls
final InputBorder actualBorder = inputBorderTween.evaluate(animation) as InputBorder;
// ignore: avoid_dynamic_calls
final Color containerColor = inputBorderPainter.blendedColor as Color;
expect(actualBorder, equals(expectedBorder));

View file

@ -269,6 +269,7 @@ void main() {
FlutterError.onError = oldHandler;
expect(exceptions.length, 1);
// ignore: avoid_dynamic_calls
expect(exceptions.single.runtimeType, FlutterError);
final FlutterError error = exceptions.first as FlutterError;
expect(error.diagnostics.length, 5);

View file

@ -692,7 +692,7 @@ void main() {
);
}
ExpansionPanelList buildExpansionPanelList(Function setState) {
ExpansionPanelList buildExpansionPanelList(StateSetter setState) {
return ExpansionPanelList(
expansionCallback: (int index, _) => setState(() { _panelExpansionState[index] = !_panelExpansionState[index]; }),
children: <ExpansionPanel>[

View file

@ -283,9 +283,13 @@ void main() {
matching: find.byWidgetPredicate((Widget w) => w is CustomPaint),
));
final dynamic/*_InputBorderPainter*/ inputBorderPainter = customPaint.foregroundPainter;
// ignore: avoid_dynamic_calls
final dynamic/*_InputBorderTween*/ inputBorderTween = inputBorderPainter.border;
// ignore: avoid_dynamic_calls
final Animation<double> animation = inputBorderPainter.borderAnimation as Animation<double>;
// ignore: avoid_dynamic_calls
final InputBorder actualBorder = inputBorderTween.evaluate(animation) as InputBorder;
// ignore: avoid_dynamic_calls
final Color containerColor = inputBorderPainter.blendedColor as Color;
// Border should match

View file

@ -90,8 +90,11 @@ InputBorder? getBorder(WidgetTester tester) {
return null;
final CustomPaint customPaint = tester.widget(findBorderPainter());
final dynamic/*_InputBorderPainter*/ inputBorderPainter = customPaint.foregroundPainter;
// ignore: avoid_dynamic_calls
final dynamic/*_InputBorderTween*/ inputBorderTween = inputBorderPainter.border;
// ignore: avoid_dynamic_calls
final Animation<double> animation = inputBorderPainter.borderAnimation as Animation<double>;
// ignore: avoid_dynamic_calls
final InputBorder border = inputBorderTween.evaluate(animation) as InputBorder;
return border;
}
@ -115,6 +118,7 @@ Color getBorderColor(WidgetTester tester) => getBorderSide(tester)!.color;
Color getContainerColor(WidgetTester tester) {
final CustomPaint customPaint = tester.widget(findBorderPainter());
final dynamic/*_InputBorderPainter*/ inputBorderPainter = customPaint.foregroundPainter;
// ignore: avoid_dynamic_calls
return inputBorderPainter.blendedColor as Color;
}

View file

@ -219,7 +219,9 @@ void main() {
// the column overflows because we're forcing it to 600 pixels high
final dynamic exception = tester.takeException();
expect(exception, isFlutterError);
// ignore: avoid_dynamic_calls
expect(exception.diagnostics.first.level, DiagnosticLevel.summary);
// ignore: avoid_dynamic_calls
expect(exception.diagnostics.first.toString(), startsWith('A RenderFlex overflowed by '));
expect(find.text('Gingerbread (0)'), findsOneWidget);
@ -344,7 +346,9 @@ void main() {
// the column overflows because we're forcing it to 600 pixels high
final dynamic exception = tester.takeException();
expect(exception, isFlutterError);
// ignore: avoid_dynamic_calls
expect(exception.diagnostics.first.level, DiagnosticLevel.summary);
// ignore: avoid_dynamic_calls
expect(exception.diagnostics.first.toString(), contains('A RenderFlex overflowed by'));
expect(find.text('Rows per page:'), findsOneWidget);

View file

@ -2162,6 +2162,7 @@ void main() {
FlutterError.onError = oldHandler;
expect(exceptions.length, 1);
// ignore: avoid_dynamic_calls
expect(exceptions.single.runtimeType, FlutterError);
final FlutterError error = exceptions.first as FlutterError;
expect(error.diagnostics.length, 5);

View file

@ -141,9 +141,11 @@ void main() {
viewportDimension: 100.0,
axisDirection: AxisDirection.down,
);
// ignore: avoid_dynamic_calls
scrollPainter!.update(metrics, AxisDirection.down);
final TestCanvas canvas = TestCanvas();
// ignore: avoid_dynamic_calls
scrollPainter.paint(canvas, const Size(10.0, 100.0));
// Scrollbar is not supposed to draw anything if there isn't enough content.

View file

@ -4706,6 +4706,7 @@ void main() {
tester.binding.defaultBinaryMessenger
.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
if (methodCall.method == 'Clipboard.setData')
// ignore: avoid_dynamic_calls
clipboardContent = methodCall.arguments['text'] as String;
else if (methodCall.method == 'Clipboard.getData')
return <String, dynamic>{'text': clipboardContent};
@ -4779,6 +4780,7 @@ void main() {
tester.binding.defaultBinaryMessenger
.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
if (methodCall.method == 'Clipboard.setData')
// ignore: avoid_dynamic_calls
clipboardContent = methodCall.arguments['text'] as String;
else if (methodCall.method == 'Clipboard.getData')
return <String, dynamic>{'text': clipboardContent};
@ -4902,6 +4904,7 @@ void main() {
tester.binding.defaultBinaryMessenger
.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
if (methodCall.method == 'Clipboard.setData')
// ignore: avoid_dynamic_calls
clipboardContent = methodCall.arguments['text'] as String;
else if (methodCall.method == 'Clipboard.getData')
return <String, dynamic>{'text': clipboardContent};
@ -4976,6 +4979,7 @@ void main() {
tester.binding.defaultBinaryMessenger
.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
if (methodCall.method == 'Clipboard.setData')
// ignore: avoid_dynamic_calls
clipboardContent = methodCall.arguments['text'] as String;
else if (methodCall.method == 'Clipboard.getData')
return <String, dynamic>{'text': clipboardContent};

View file

@ -355,10 +355,14 @@ void _tests() {
final CustomPaint dialPaint = tester.widget(findDialPaint);
final dynamic dialPainter = dialPaint.painter;
// ignore: avoid_dynamic_calls
final List<dynamic> primaryLabels = dialPainter.primaryLabels as List<dynamic>;
// ignore: avoid_dynamic_calls
expect(primaryLabels.map<String>((dynamic tp) => tp.painter.text.text as String), labels12To11);
// ignore: avoid_dynamic_calls
final List<dynamic> secondaryLabels = dialPainter.secondaryLabels as List<dynamic>;
// ignore: avoid_dynamic_calls
expect(secondaryLabels.map<String>((dynamic tp) => tp.painter.text.text as String), labels12To11);
});
@ -367,10 +371,14 @@ void _tests() {
final CustomPaint dialPaint = tester.widget(findDialPaint);
final dynamic dialPainter = dialPaint.painter;
// ignore: avoid_dynamic_calls
final List<dynamic> primaryLabels = dialPainter.primaryLabels as List<dynamic>;
// ignore: avoid_dynamic_calls
expect(primaryLabels.map<String>((dynamic tp) => tp.painter.text.text as String), labels00To22);
// ignore: avoid_dynamic_calls
final List<dynamic> secondaryLabels = dialPainter.secondaryLabels as List<dynamic>;
// ignore: avoid_dynamic_calls
expect(secondaryLabels.map<String>((dynamic tp) => tp.painter.text.text as String), labels00To22);
});
@ -491,6 +499,7 @@ void _tests() {
// Ensure we preserve day period as we roll over.
final dynamic pickerState = tester.state(_timePickerDialog);
// ignore: avoid_dynamic_calls
expect(pickerState.selectedTime.value, const TimeOfDay(hour: 1, minute: 0));
await actAndExpect(
@ -556,6 +565,7 @@ void _tests() {
// Ensure we preserve hour period as we roll over.
final dynamic pickerState = tester.state(_timePickerDialog);
// ignore: avoid_dynamic_calls
expect(pickerState.selectedTime.value, const TimeOfDay(hour: 11, minute: 0));
await actAndExpect(

View file

@ -152,15 +152,19 @@ void main() {
final CustomPaint dialPaint = tester.widget(findDialPaint);
final dynamic dialPainter = dialPaint.painter;
// ignore: avoid_dynamic_calls
final List<dynamic> primaryLabels = dialPainter.primaryLabels as List<dynamic>;
expect(
// ignore: avoid_dynamic_calls
primaryLabels.first.painter.text.style,
Typography.material2014().englishLike.bodyText1!
.merge(Typography.material2014().black.bodyText1)
.copyWith(color: defaultTheme.colorScheme.onSurface),
);
// ignore: avoid_dynamic_calls
final List<dynamic> secondaryLabels = dialPainter.secondaryLabels as List<dynamic>;
expect(
// ignore: avoid_dynamic_calls
secondaryLabels.first.painter.text.style,
Typography.material2014().englishLike.bodyText1!
.merge(Typography.material2014().white.bodyText1)
@ -293,15 +297,19 @@ void main() {
final CustomPaint dialPaint = tester.widget(findDialPaint);
final dynamic dialPainter = dialPaint.painter;
// ignore: avoid_dynamic_calls
final List<dynamic> primaryLabels = dialPainter.primaryLabels as List<dynamic>;
expect(
// ignore: avoid_dynamic_calls
primaryLabels.first.painter.text.style,
Typography.material2014().englishLike.bodyText1!
.merge(Typography.material2014().black.bodyText1)
.copyWith(color: _unselectedColor),
);
// ignore: avoid_dynamic_calls
final List<dynamic> secondaryLabels = dialPainter.secondaryLabels as List<dynamic>;
expect(
// ignore: avoid_dynamic_calls
secondaryLabels.first.painter.text.style,
Typography.material2014().englishLike.bodyText1!
.merge(Typography.material2014().white.bodyText1)

View file

@ -14,20 +14,22 @@ import '../rendering/mock_canvas.dart';
import '../widgets/semantics_tester.dart';
import 'feedback_tester.dart';
// This file uses "as dynamic" in a few places to defeat the static
// analysis. In general you want to avoid using this style in your
// code, as it will cause the analyzer to be unable to help you catch
// errors.
//
// In this case, we do it because we are trying to call internal
// methods of the tooltip code in order to test it. Normally, the
// state of a tooltip is a private class, but by using a GlobalKey we
// can get a handle to that object and by using "as dynamic" we can
// bypass the analyzer's type checks and call methods that we aren't
// supposed to be able to know about.
//
// It's ok to do this in tests, but you really don't want to do it in
// production code.
void _ensureTooltipVisible(GlobalKey key) {
// This function uses "as dynamic"to defeat the static analysis. In general
// you want to avoid using this style in your code, as it will cause the
// analyzer to be unable to help you catch errors.
//
// In this case, we do it because we are trying to call internal methods of
// the tooltip code in order to test it. Normally, the state of a tooltip is a
// private class, but by using a GlobalKey we can get a handle to that object
// and by using "as dynamic" we can bypass the analyzer's type checks and call
// methods that we aren't supposed to be able to know about.
//
// It's ok to do this in tests, but you really don't want to do it in
// production code.
// ignore: avoid_dynamic_calls
(key.currentState as dynamic).ensureTooltipVisible();
}
const String tooltipText = 'TIP';
@ -74,7 +76,7 @@ void main() {
),
),
);
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
/********************* 800x600 screen
@ -134,7 +136,7 @@ void main() {
),
),
);
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
/************************ 800x600 screen
@ -193,7 +195,7 @@ void main() {
),
),
);
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
/********************* 800x600 screen
@ -247,7 +249,7 @@ void main() {
),
),
);
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
/********************* 800x600 screen
@ -303,7 +305,7 @@ void main() {
),
),
);
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
// we try to put it here but it doesn't fit:
@ -370,7 +372,7 @@ void main() {
),
),
);
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
/********************* 800x600 screen
@ -425,7 +427,7 @@ void main() {
),
),
);
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
/********************* 800x600 screen
@ -482,7 +484,7 @@ void main() {
),
),
);
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
/********************* 800x600 screen
@ -530,7 +532,7 @@ void main() {
),
),
);
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
final Offset topLeftTipInGlobal = tester.getTopLeft(
@ -575,7 +577,7 @@ void main() {
),
),
));
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
final TextStyle textStyle = tester.widget<Text>(find.text(tooltipText)).style!;
@ -601,7 +603,7 @@ void main() {
),
),
));
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
final TextStyle textStyle = tester.widget<Text>(find.text(tooltipText)).style!;
@ -628,7 +630,7 @@ void main() {
),
),
));
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
final TextStyle textStyle = tester.widget<Text>(find.text(tooltipText)).style!;
@ -686,7 +688,7 @@ void main() {
),
),
));
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
final TextStyle textStyle = tester.widget<DefaultTextStyle>(
@ -726,7 +728,7 @@ void main() {
),
),
);
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
final RenderBox tip = tester.renderObject(
@ -755,6 +757,7 @@ void main() {
),
),
);
// ignore: avoid_dynamic_calls
(key.currentState as dynamic).ensureTooltipVisible();
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
@ -800,7 +803,7 @@ void main() {
),
),
);
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
final RenderBox tip = tester.renderObject(
@ -1167,8 +1170,8 @@ void main() {
expect(semantics, hasSemantics(expected, ignoreTransform: true, ignoreRect: true));
// Before using "as dynamic" in your code, see note at the top of the file.
(key.currentState as dynamic).ensureTooltipVisible(); // this triggers a rebuild of the semantics because the tree changes
// This triggers a rebuild of the semantics because the tree changes.
_ensureTooltipVisible(key);
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)

View file

@ -11,24 +11,26 @@ import 'package:flutter_test/flutter_test.dart';
import '../rendering/mock_canvas.dart';
import '../widgets/semantics_tester.dart';
// This file uses "as dynamic" in a few places to defeat the static
// analysis. In general you want to avoid using this style in your
// code, as it will cause the analyzer to be unable to help you catch
// errors.
//
// In this case, we do it because we are trying to call internal
// methods of the tooltip code in order to test it. Normally, the
// state of a tooltip is a private class, but by using a GlobalKey we
// can get a handle to that object and by using "as dynamic" we can
// bypass the analyzer's type checks and call methods that we aren't
// supposed to be able to know about.
//
// It's ok to do this in tests, but you really don't want to do it in
// production code.
const String tooltipText = 'TIP';
const double _customPaddingValue = 10.0;
void _ensureTooltipVisible(GlobalKey key) {
// This function uses "as dynamic"to defeat the static analysis. In general
// you want to avoid using this style in your code, as it will cause the
// analyzer to be unable to help you catch errors.
//
// In this case, we do it because we are trying to call internal methods of
// the tooltip code in order to test it. Normally, the state of a tooltip is a
// private class, but by using a GlobalKey we can get a handle to that object
// and by using "as dynamic" we can bypass the analyzer's type checks and call
// methods that we aren't supposed to be able to know about.
//
// It's ok to do this in tests, but you really don't want to do it in
// production code.
// ignore: avoid_dynamic_calls
(key.currentState as dynamic).ensureTooltipVisible();
}
void main() {
test('TooltipThemeData copyWith, ==, hashCode basics', () {
expect(const TooltipThemeData(), const TooltipThemeData().copyWith());
@ -135,7 +137,7 @@ void main() {
),
),
);
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
/********************* 800x600 screen
@ -193,7 +195,7 @@ void main() {
),
),
);
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
/********************* 800x600 screen
@ -253,7 +255,7 @@ void main() {
),
),
);
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
// we try to put it here but it doesn't fit:
@ -322,7 +324,7 @@ void main() {
),
),
);
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
// we try to put it here but it doesn't fit:
@ -393,7 +395,7 @@ void main() {
),
),
);
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pumpAndSettle(); // faded in, show timer started (and at 0.0)
/********************* 800x600 screen
@ -450,7 +452,7 @@ void main() {
),
),
);
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pumpAndSettle(); // faded in, show timer started (and at 0.0)
/********************* 800x600 screen
@ -499,7 +501,7 @@ void main() {
),
),
);
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
final RenderBox tip = tester.renderObject(find.text(tooltipText)).parent!.parent!.parent!.parent!.parent! as RenderBox;
@ -555,7 +557,7 @@ void main() {
),
),
);
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
final RenderBox tip = tester.renderObject(find.text(tooltipText)).parent!.parent!.parent!.parent!.parent! as RenderBox;
@ -603,7 +605,7 @@ void main() {
),
),
));
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
final TextStyle textStyle = tester.widget<Text>(find.text(tooltipText)).style!;
@ -632,7 +634,7 @@ void main() {
),
),
));
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
final TextStyle textStyle = tester.widget<Text>(find.text(tooltipText)).style!;
@ -675,7 +677,7 @@ void main() {
),
),
);
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
final RenderBox tip = tester.renderObject(find.text(tooltipText)).parent!.parent!.parent!.parent! as RenderBox;
@ -717,7 +719,7 @@ void main() {
),
),
);
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pump(const Duration(seconds: 2)); // faded in, show timer started (and at 0.0)
final RenderBox tip = tester.renderObject(find.text(tooltipText)).parent!.parent!.parent!.parent! as RenderBox;
@ -759,7 +761,7 @@ void main() {
),
),
);
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pumpAndSettle();
final RenderBox tip = tester.renderObject(find.ancestor(
@ -804,7 +806,7 @@ void main() {
),
),
);
(key.currentState as dynamic).ensureTooltipVisible(); // Before using "as dynamic" in your code, see note at the top of the file.
_ensureTooltipVisible(key);
await tester.pumpAndSettle();
final RenderBox tip = tester.renderObject(find.ancestor(

View file

@ -117,6 +117,7 @@ void main() {
// Use didPopRoute() to simulate the system back button. Check that
// didPopRoute() indicates that the notification was handled.
final dynamic widgetsAppState = tester.state(find.byType(WidgetsApp));
// ignore: avoid_dynamic_calls
expect(await widgetsAppState.didPopRoute(), isTrue);
expect(find.text('Sample Page'), findsOneWidget);

View file

@ -316,8 +316,11 @@ void main() {
expect(call.positionalArguments[1], const Rect.fromLTRB(10.0, 20.0, 40.0, 60.0));
expect(call.positionalArguments[2], const Rect.fromLTRB(0.0, 0.0, 100.0, 100.0));
expect(call.positionalArguments[3], isA<Paint>());
// ignore: avoid_dynamic_calls
expect(call.positionalArguments[3].isAntiAlias, false);
// ignore: avoid_dynamic_calls
expect(call.positionalArguments[3].colorFilter, colorFilter);
// ignore: avoid_dynamic_calls
expect(call.positionalArguments[3].filterQuality, FilterQuality.low);
});
@ -654,6 +657,7 @@ void main() {
expect(call.positionalArguments, hasLength(4));
// Image should be positioned in the center of the container
// ignore: avoid_dynamic_calls
expect(call.positionalArguments[2].center, outputRect.center);
}
});
@ -674,6 +678,7 @@ void main() {
final Invocation call = canvas.invocations.firstWhere((Invocation call) => call.memberName == #drawImageRect);
// The image should scale down to Size(25.0, 25.0) from Size(100.0, 100.0)
// considering DecorationImage scale to be 4.0 and Image scale to be 1.0.
// ignore: avoid_dynamic_calls
expect(call.positionalArguments[2].size, const Size(25.0, 25.0));
expect(call.positionalArguments[2], const Rect.fromLTRB(0.0, 0.0, 25.0, 25.0));
});

View file

@ -75,6 +75,7 @@ void main() {
),
);
final dynamic state = tester.state(find.byType(CupertinoDatePicker));
// ignore: avoid_dynamic_calls
final Map<int, double> cache = state.estimatedColumnWidths as Map<int, double>;
expect(cache.isNotEmpty, isTrue);
const Map<String, dynamic> data = <String, dynamic>{
@ -101,6 +102,7 @@ void main() {
),
);
final dynamic state = tester.state(find.byType(CupertinoDatePicker));
// ignore: avoid_dynamic_calls
final Map<int, double> cache = state.estimatedColumnWidths as Map<int, double>;
// Simulates font missing.
cache.clear();
@ -128,8 +130,11 @@ void main() {
);
final dynamic state = tester.state(find.byType(CupertinoTimerPicker));
// Simulates wrong metrics due to font missing.
// ignore: avoid_dynamic_calls
state.numberLabelWidth = 0.0;
// ignore: avoid_dynamic_calls
state.numberLabelHeight = 0.0;
// ignore: avoid_dynamic_calls
state.numberLabelBaseline = 0.0;
const Map<String, dynamic> data = <String, dynamic>{
'type': 'fontsChange',
@ -140,8 +145,11 @@ void main() {
(ByteData? data) { },
);
// Metrics should be refreshed
// ignore: avoid_dynamic_calls
expect(state.numberLabelWidth - 46.0 < precisionErrorTolerance, isTrue);
// ignore: avoid_dynamic_calls
expect(state.numberLabelHeight - 23.0 < precisionErrorTolerance, isTrue);
// ignore: avoid_dynamic_calls
expect(state.numberLabelBaseline - 18.400070190429688 < precisionErrorTolerance, isTrue);
final Element element = tester.element(find.byType(CupertinoTimerPicker));
expect(element.dirty, isTrue);

View file

@ -35,7 +35,9 @@ void main() {
final dynamic exception = tester.takeException();
expect(exception, isFlutterError);
// ignore: avoid_dynamic_calls
expect(exception.diagnostics.first.level, DiagnosticLevel.summary);
// ignore: avoid_dynamic_calls
expect(exception.diagnostics.first.toString(), startsWith('A RenderConstraintsTransformBox overflowed by '));
expect(find.byType(UnconstrainedBox), paints..rect());

View file

@ -664,6 +664,7 @@ void main() {
// try to paint(), which also checks _hasOverflow, and it should be able to
// do so without an ancillary error.
expect(exceptions, hasLength(1));
// ignore: avoid_dynamic_calls
expect(exceptions.first.message, isNot(contains('Null check operator')));
});
}

View file

@ -208,11 +208,10 @@ class FakeAndroidPlatformViewsController {
Future<dynamic> _dispose(MethodCall call) {
assert(call.arguments is Map);
final Map<Object?, Object?> arguments = call.arguments as Map<Object?, Object?>;
// ignore: avoid_dynamic_calls
final int id = call.arguments['id'] as int;
// ignore: avoid_dynamic_calls
final bool hybrid = call.arguments['hybrid'] as bool;
final int id = arguments['id']! as int;
final bool hybrid = arguments['hybrid']! as bool;
if (hybrid && !_views[id]!.hybrid!) {
throw ArgumentError('An $AndroidViewController using hybrid composition must pass `hybrid: true`');

View file

@ -22,7 +22,7 @@ void main() {
});
test('Haptic feedback variation tests', () async {
Future<void> callAndVerifyHapticFunction(Function hapticFunction, String platformMethodArgument) async {
Future<void> callAndVerifyHapticFunction(Future<void> Function() hapticFunction, String platformMethodArgument) async {
final List<MethodCall> log = <MethodCall>[];
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {

View file

@ -208,7 +208,7 @@ void main() {
);
// Change the modifiers so that they show the shift key as already down
// when this event is received, but it's not in keysPressed yet.
data['modifiers'] |= RawKeyEventDataMacOs.modifierLeftShift | RawKeyEventDataMacOs.modifierShift;
data['modifiers'] = (data['modifiers'] as int) | RawKeyEventDataMacOs.modifierLeftShift | RawKeyEventDataMacOs.modifierShift;
// dispatch the modified data.
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
SystemChannels.keyEvent.name,
@ -233,7 +233,7 @@ void main() {
);
// Change the modifiers so that they show the shift key as already down
// when this event is received, but it's not in keysPressed yet.
data['modifiers'] |= RawKeyEventDataMacOs.modifierLeftShift | RawKeyEventDataMacOs.modifierShift;
data['modifiers'] = (data['modifiers'] as int) | RawKeyEventDataMacOs.modifierLeftShift | RawKeyEventDataMacOs.modifierShift;
// dispatch the modified data.
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
SystemChannels.keyEvent.name,
@ -258,7 +258,7 @@ void main() {
);
// Change the modifiers so that they show the shift key as already down
// when this event is received, but it's not in keysPressed yet.
data['modifiers'] |= RawKeyEventDataWindows.modifierLeftShift | RawKeyEventDataWindows.modifierShift;
data['modifiers'] = (data['modifiers'] as int) | RawKeyEventDataWindows.modifierLeftShift | RawKeyEventDataWindows.modifierShift;
// dispatch the modified data.
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
SystemChannels.keyEvent.name,
@ -283,7 +283,7 @@ void main() {
);
// Change the modifiers so that they show the shift key as already down
// when this event is received, but it's not in keysPressed yet.
data['metaState'] |= RawKeyEventDataAndroid.modifierLeftShift | RawKeyEventDataAndroid.modifierShift;
data['metaState'] = (data['metaState'] as int) | RawKeyEventDataAndroid.modifierLeftShift | RawKeyEventDataAndroid.modifierShift;
// dispatch the modified data.
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
SystemChannels.keyEvent.name,
@ -308,7 +308,7 @@ void main() {
);
// Change the modifiers so that they show the shift key as already down
// when this event is received, but it's not in keysPressed yet.
data['modifiers'] |= RawKeyEventDataFuchsia.modifierLeftShift;
data['modifiers'] = (data['modifiers'] as int) | RawKeyEventDataFuchsia.modifierLeftShift;
// dispatch the modified data.
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
SystemChannels.keyEvent.name,
@ -333,7 +333,7 @@ void main() {
);
// Change the modifiers so that they show the shift key as already down
// when this event is received, but it's not in keysPressed yet.
data['modifiers'] |= GLFWKeyHelper.modifierShift;
data['modifiers'] = (data['modifiers'] as int) | GLFWKeyHelper.modifierShift;
// dispatch the modified data.
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
SystemChannels.keyEvent.name,
@ -363,7 +363,8 @@ void main() {
LogicalKeyboardKey.keyA,
platform: 'web',
isDown: true,
)..['metaState'] |= RawKeyEventDataWeb.modifierShift;
);
data['metaState'] = (data['metaState'] as int) | RawKeyEventDataWeb.modifierShift;
// Dispatch the modified data.
await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
SystemChannels.keyEvent.name,
@ -406,7 +407,8 @@ void main() {
LogicalKeyboardKey.shiftRight,
platform: 'web',
isDown: true,
)..['metaState'] |= RawKeyEventDataWeb.modifierShift;
);
data['metaState'] = (data['metaState'] as int) | RawKeyEventDataWeb.modifierShift;
// Dispatch the modified data.
await ServicesBinding.instance!.defaultBinaryMessenger.handlePlatformMessage(
SystemChannels.keyEvent.name,
@ -451,7 +453,7 @@ void main() {
isDown: true,
);
// Set only the generic "down" modifier, without setting a side.
data['metaState'] |=
data['metaState'] = (data['metaState'] as int) |
RawKeyEventDataAndroid.modifierShift |
RawKeyEventDataAndroid.modifierAlt |
RawKeyEventDataAndroid.modifierControl |
@ -489,7 +491,7 @@ void main() {
isDown: true,
);
// Set only the generic "shift down" modifier, without setting a side.
data['modifiers'] |=
data['modifiers'] = (data['modifiers'] as int) |
RawKeyEventDataMacOs.modifierShift |
RawKeyEventDataMacOs.modifierOption |
RawKeyEventDataMacOs.modifierCommand |
@ -527,7 +529,7 @@ void main() {
isDown: true,
);
// Set only the generic "shift down" modifier, without setting a side.
data['modifiers'] |=
data['modifiers'] = (data['modifiers'] as int) |
RawKeyEventDataIos.modifierShift |
RawKeyEventDataIos.modifierOption |
RawKeyEventDataIos.modifierCommand |
@ -566,7 +568,7 @@ void main() {
);
// Set only the generic "shift down" modifier, without setting a side.
// Windows doesn't have a concept of "either" for the Windows (meta) key.
data['modifiers'] |=
data['modifiers'] = (data['modifiers'] as int) |
RawKeyEventDataWindows.modifierShift |
RawKeyEventDataWindows.modifierAlt |
RawKeyEventDataWindows.modifierControl;
@ -602,7 +604,7 @@ void main() {
);
// Set only the generic "shift down" modifier, without setting a side.
// Windows doesn't have a concept of "either" for the Windows (meta) key.
data['modifiers'] |=
data['modifiers'] = (data['modifiers'] as int) |
GLFWKeyHelper.modifierShift |
GLFWKeyHelper.modifierAlt |
GLFWKeyHelper.modifierControl |
@ -640,7 +642,7 @@ void main() {
isDown: true,
);
// Set only the generic "shift down" modifier, without setting a side.
data['metaState'] |=
data['metaState'] = (data['metaState'] as int) |
RawKeyEventDataWeb.modifierShift |
RawKeyEventDataWeb.modifierAlt |
RawKeyEventDataWeb.modifierControl |

View file

@ -29,7 +29,7 @@ void main() {
expect(manager.updateScheduled, isTrue);
expect(bucket.read<int>('value1'), 22);
manager.doSerialization();
expect(rawData[valuesMapKey]['value1'], 22);
expect((rawData[valuesMapKey] as Map<String, dynamic>)['value1'], 22);
expect(manager.updateScheduled, isFalse);
// Can add a new value.
@ -37,7 +37,7 @@ void main() {
expect(manager.updateScheduled, isTrue);
expect(bucket.read<bool>('value3'), true);
manager.doSerialization();
expect(rawData[valuesMapKey]['value3'], true);
expect((rawData[valuesMapKey] as Map<String, dynamic>)['value3'], true);
expect(manager.updateScheduled, isFalse);
// Can remove existing value.
@ -45,7 +45,7 @@ void main() {
expect(manager.updateScheduled, isTrue);
expect(bucket.read<int>('value1'), isNull); // Does not exist anymore.
manager.doSerialization();
expect(rawData[valuesMapKey].containsKey('value1'), isFalse);
expect((rawData[valuesMapKey] as Map<String, dynamic>).containsKey('value1'), isFalse);
expect(manager.updateScheduled, isFalse);
// Removing non-existing value is no-op.
@ -57,8 +57,8 @@ void main() {
expect(manager.updateScheduled, isTrue);
expect(bucket.read<int>('value4'), null);
manager.doSerialization();
expect(rawData[valuesMapKey].containsKey('value4'), isTrue);
expect(rawData[valuesMapKey]['value4'], null);
expect((rawData[valuesMapKey] as Map<String, dynamic>).containsKey('value4'), isTrue);
expect((rawData[valuesMapKey] as Map<String, dynamic>)['value4'], null);
expect(manager.updateScheduled, isFalse);
});
@ -86,7 +86,7 @@ void main() {
expect(manager.updateScheduled, isTrue);
expect(child.read<int>('foo'), 44);
manager.doSerialization();
expect(rootRawData[childrenMapKey]['child1'][valuesMapKey]['foo'], 44);
expect((((rootRawData[childrenMapKey] as Map<String, dynamic>)['child1'] as Map<String, dynamic>)[valuesMapKey] as Map<String, dynamic>)['foo'], 44);
expect(manager.updateScheduled, isFalse);
// Can add a new value.
@ -94,7 +94,7 @@ void main() {
expect(manager.updateScheduled, isTrue);
expect(child.read<bool>('value3'), true);
manager.doSerialization();
expect(rootRawData[childrenMapKey]['child1'][valuesMapKey]['value3'], true);
expect((((rootRawData[childrenMapKey] as Map<String, dynamic>)['child1'] as Map<String, dynamic>)[valuesMapKey] as Map<String, dynamic>)['value3'], true);
expect(manager.updateScheduled, isFalse);
// Can remove existing value.
@ -102,7 +102,7 @@ void main() {
expect(manager.updateScheduled, isTrue);
expect(child.read<int>('foo'), isNull); // Does not exist anymore.
manager.doSerialization();
expect(rootRawData[childrenMapKey]['child1'].containsKey('foo'), isFalse);
expect(((rootRawData[childrenMapKey] as Map<String, dynamic>)['child1'] as Map<String, dynamic>).containsKey('foo'), isFalse);
expect(manager.updateScheduled, isFalse);
// Removing non-existing value is no-op.
@ -114,8 +114,8 @@ void main() {
expect(manager.updateScheduled, isTrue);
expect(child.read<int>('value4'), null);
manager.doSerialization();
expect(rootRawData[childrenMapKey]['child1'][valuesMapKey].containsKey('value4'), isTrue);
expect(rootRawData[childrenMapKey]['child1'][valuesMapKey]['value4'], null);
expect((((rootRawData[childrenMapKey] as Map<String, dynamic>)['child1'] as Map<String, dynamic>)[valuesMapKey] as Map<String, dynamic>).containsKey('value4'), isTrue);
expect((((rootRawData[childrenMapKey] as Map<String, dynamic>)['child1'] as Map<String, dynamic>)[valuesMapKey] as Map<String, dynamic>)['value4'], null);
expect(manager.updateScheduled, isFalse);
});
@ -135,7 +135,7 @@ void main() {
child.write('bar', 44);
expect(manager.updateScheduled, isTrue);
manager.doSerialization();
expect(rawData[childrenMapKey]['child1'][valuesMapKey]['bar'], 44);
expect((((rawData[childrenMapKey] as Map<String, dynamic>)['child1'] as Map<String, dynamic>)[valuesMapKey] as Map<String, dynamic>)['bar'], 44);
expect(manager.updateScheduled, isFalse);
});
@ -144,7 +144,7 @@ void main() {
final Map<String, dynamic> rawData = _createRawDataSet();
final RestorationBucket bucket = RestorationBucket.root(manager: manager, rawData: rawData);
expect(rawData[childrenMapKey].containsKey('child2'), isFalse);
expect((rawData[childrenMapKey] as Map<String, dynamic>).containsKey('child2'), isFalse);
final Object debugOwner = Object();
final RestorationBucket child = bucket.claimChild('child2', debugOwner: debugOwner);
@ -158,8 +158,8 @@ void main() {
manager.doSerialization();
expect(manager.updateScheduled, isFalse);
expect(rawData[childrenMapKey].containsKey('child2'), isTrue);
expect(rawData[childrenMapKey]['child2'][valuesMapKey]['foo'], 55);
expect((rawData[childrenMapKey] as Map<String, dynamic>).containsKey('child2'), isTrue);
expect((((rawData[childrenMapKey] as Map<String, dynamic>)['child2'] as Map<String, dynamic>)[valuesMapKey] as Map<Object?, Object?>)['foo'], 55);
});
test('claim child that is already claimed throws if not given up', () {
@ -220,8 +220,8 @@ void main() {
child1.dispose();
manager.doSerialization();
expect(manager.updateScheduled, isFalse);
expect(rawData[childrenMapKey]['child1'][valuesMapKey].containsKey('foo'), isFalse);
expect(rawData[childrenMapKey]['child1'][valuesMapKey]['bar'], 55);
expect((((rawData[childrenMapKey] as Map<String, dynamic>)['child1'] as Map<String, dynamic>)[valuesMapKey] as Map<Object?, Object?>).containsKey('foo'), isFalse);
expect((((rawData[childrenMapKey] as Map<String, dynamic>)['child1'] as Map<String, dynamic>)[valuesMapKey] as Map<Object?, Object?>)['bar'], 55);
});
test('claiming a claimed child twice and only giving it up once throws', () {
@ -288,15 +288,15 @@ void main() {
manager.doSerialization();
expect(manager.updateScheduled, isFalse);
expect(rawData[childrenMapKey].containsKey('child1'), isTrue);
expect(rawData[childrenMapKey].containsKey('child2'), isTrue);
expect((rawData[childrenMapKey] as Map<String, dynamic>).containsKey('child1'), isTrue);
expect((rawData[childrenMapKey] as Map<String, dynamic>).containsKey('child2'), isTrue);
child1.dispose();
expect(manager.updateScheduled, isTrue);
manager.doSerialization();
expect(manager.updateScheduled, isFalse);
expect(rawData[childrenMapKey].containsKey('child1'), isFalse);
expect((rawData[childrenMapKey] as Map<String, dynamic>).containsKey('child1'), isFalse);
child2.dispose();
expect(manager.updateScheduled, isTrue);
@ -318,7 +318,7 @@ void main() {
child.rename('child1');
expect(manager.updateScheduled, isFalse);
expect(child.restorationId, 'child1');
expect(rawData[childrenMapKey].containsKey('child1'), isTrue);
expect((rawData[childrenMapKey] as Map<String, dynamic>).containsKey('child1'), isTrue);
});
test('rename to unused id', () {
@ -327,7 +327,7 @@ void main() {
final RestorationBucket root = RestorationBucket.root(manager: manager, rawData: rawData);
final RestorationBucket child = root.claimChild('child1', debugOwner: 'owner1');
final Object rawChildData = rawData[childrenMapKey]['child1'] as Object;
final Object rawChildData = (rawData[childrenMapKey] as Map<String, dynamic>)['child1'] as Object;
expect(rawChildData, isNotNull);
expect(manager.updateScheduled, isFalse);
@ -339,8 +339,8 @@ void main() {
manager.doSerialization();
expect(manager.updateScheduled, isFalse);
expect(rawData[childrenMapKey].containsKey('child1'), isFalse);
expect(rawData[childrenMapKey]['new-name'], rawChildData);
expect((rawData[childrenMapKey] as Map<Object?, Object?>).containsKey('child1'), isFalse);
expect((rawData[childrenMapKey] as Map<Object?, Object?>)['new-name'], rawChildData);
});
test('rename to used id throws if id is not given up', () {
@ -370,9 +370,9 @@ void main() {
final RestorationBucket child2 = root.claimChild('child2', debugOwner: 'owner1');
manager.doSerialization();
final Object rawChild1Data = rawData[childrenMapKey]['child1'] as Object;
final Object rawChild1Data = (rawData[childrenMapKey] as Map<String, dynamic>)['child1'] as Object;
expect(rawChild1Data, isNotNull);
final Object rawChild2Data = rawData[childrenMapKey]['child2'] as Object;
final Object rawChild2Data = (rawData[childrenMapKey] as Map<String, dynamic>)['child2'] as Object;
expect(rawChild2Data, isNotNull);
expect(child1.restorationId, 'child1');
@ -387,8 +387,8 @@ void main() {
manager.doSerialization();
expect(manager.updateScheduled, isFalse);
expect(rawData[childrenMapKey]['child1'], rawChild2Data);
expect(rawData[childrenMapKey].containsKey('child2'), isFalse);
expect((rawData[childrenMapKey] as Map<String, dynamic>)['child1'], rawChild2Data);
expect((rawData[childrenMapKey] as Map<String, dynamic>).containsKey('child2'), isFalse);
});
test('renaming a to be added child', () {
@ -396,7 +396,7 @@ void main() {
final Map<String, dynamic> rawData = _createRawDataSet();
final RestorationBucket root = RestorationBucket.root(manager: manager, rawData: rawData);
final Object rawChild1Data = rawData[childrenMapKey]['child1'] as Object;
final Object rawChild1Data = (rawData[childrenMapKey] as Map<String, dynamic>)['child1'] as Object;
expect(rawChild1Data, isNotNull);
final RestorationBucket child1 = root.claimChild('child1', debugOwner: 'owner1');
@ -411,8 +411,8 @@ void main() {
expect(child1.restorationId, 'child1');
expect(child2.restorationId, 'foo');
expect(rawData[childrenMapKey]['child1'], rawChild1Data);
expect(rawData[childrenMapKey]['foo'], isEmpty); // new bucket
expect((rawData[childrenMapKey] as Map<String, dynamic>)['child1'], rawChild1Data);
expect((rawData[childrenMapKey] as Map<String, dynamic>)['foo'], isEmpty); // new bucket
});
test('adopt is no-op if same parent', () {
@ -424,7 +424,7 @@ void main() {
root.adoptChild(child1);
expect(manager.updateScheduled, isFalse);
expect(rawData[childrenMapKey].containsKey('child1'), isTrue);
expect((rawData[childrenMapKey] as Map<String, dynamic>).containsKey('child1'), isTrue);
});
test('adopt fresh child', () {
@ -442,8 +442,8 @@ void main() {
manager.doSerialization();
expect(manager.updateScheduled, isFalse);
expect(rawData[childrenMapKey].containsKey('fresh-child'), isTrue);
expect(rawData[childrenMapKey]['fresh-child'][valuesMapKey]['value'], 22);
expect((rawData[childrenMapKey] as Map<String, dynamic>).containsKey('fresh-child'), isTrue);
expect((((rawData[childrenMapKey] as Map<String, dynamic>)['fresh-child'] as Map<String, dynamic>)[valuesMapKey] as Map<Object?, Object?>)['value'], 22);
child.write('bar', 'blabla');
expect(manager.updateScheduled, isTrue);
@ -462,7 +462,7 @@ void main() {
manager.doSerialization();
expect(manager.updateScheduled, isFalse);
final Object childOfChildData = rawData[childrenMapKey]['child1'][childrenMapKey]['childOfChild'] as Object;
final Object childOfChildData = (((rawData[childrenMapKey] as Map<String, dynamic>)['child1'] as Map<String, dynamic>)[childrenMapKey] as Map<Object?, Object?>)['childOfChild']!;
expect(childOfChildData, isNotEmpty);
root.adoptChild(childOfChild);
@ -470,8 +470,8 @@ void main() {
manager.doSerialization();
expect(manager.updateScheduled, isFalse);
expect(rawData[childrenMapKey]['child1'].containsKey(childrenMapKey), isFalse); // child1 has no children anymore.
expect(rawData[childrenMapKey]['childOfChild'], childOfChildData);
expect(((rawData[childrenMapKey] as Map<String, dynamic>)['child1'] as Map<String, dynamic>).containsKey(childrenMapKey), isFalse); // child1 has no children anymore.
expect((rawData[childrenMapKey] as Map<String, dynamic>)['childOfChild'], childOfChildData);
});
test('adopting child throws if id is already in use and not given up', () {
@ -497,7 +497,7 @@ void main() {
final RestorationBucket childOfChild = child.claimChild('child1', debugOwner: 'owner2');
childOfChild.write<String>('foo', 'bar');
final Object childOfChildData = rawData[childrenMapKey]['child1'][childrenMapKey]['child1'] as Object;
final Object childOfChildData = (((rawData[childrenMapKey] as Map<String, dynamic>)['child1'] as Map<String, dynamic>)[childrenMapKey] as Map<Object?, Object?>)['child1']!;
expect(childOfChildData, isNotEmpty);
expect(manager.updateScheduled, isTrue);
@ -510,7 +510,7 @@ void main() {
manager.doSerialization();
expect(manager.updateScheduled, isFalse);
expect(rawData[childrenMapKey]['child1'], childOfChildData);
expect((rawData[childrenMapKey] as Map<String, dynamic>)['child1'], childOfChildData);
});
test('adopting a to-be-added child under an already in use id', () {
@ -537,8 +537,13 @@ void main() {
manager.doSerialization();
expect(manager.updateScheduled, isFalse);
expect(rawData[childrenMapKey]['child2'][valuesMapKey]['foo'], 'bar');
expect(rawData[childrenMapKey]['child1'][childrenMapKey]['child2'][valuesMapKey]['hello'], 'world');
expect((((rawData[childrenMapKey] as Map<String, dynamic>)['child2'] as Map<String, dynamic>)[valuesMapKey] as Map<Object?, Object?>)['foo'], 'bar');
expect((((((rawData[childrenMapKey] as Map<String, dynamic>)
['child1'] as Map<String, dynamic>)
[childrenMapKey] as Map<Object?, Object?>)
['child2']! as Map<String, dynamic>)
[valuesMapKey] as Map<Object?, Object?>)
['hello'], 'world');
});
test('throws when used after dispose', () {

View file

@ -233,7 +233,7 @@ void main() {
tester.firstWidget(find.byType(EditableText));
expect(editableText.maxLines, equals(1));
expect(tester.testTextInput.editingState!['text'], equals('test'));
expect(tester.testTextInput.setClientArgs!['inputType']['name'], equals('TextInputType.text'));
expect((tester.testTextInput.setClientArgs!['inputType'] as Map<String, dynamic>)['name'], equals('TextInputType.text'));
expect(tester.testTextInput.setClientArgs!['inputAction'], equals('TextInputAction.done'));
});
@ -372,7 +372,7 @@ void main() {
await tester.idle();
expect(tester.testTextInput.editingState!['text'], equals('test'));
expect(
tester.testTextInput.setClientArgs!['inputType']['name'],
(tester.testTextInput.setClientArgs!['inputType'] as Map<String, dynamic>)['name'],
// On web, we don't infer the keyboard type as "name". We only infer
// on iOS and macOS.
kIsWeb ? equals('TextInputType.address') : equals('TextInputType.name'),
@ -410,7 +410,7 @@ void main() {
controller.text = 'test';
await tester.idle();
expect(tester.testTextInput.editingState!['text'], equals('test'));
expect(tester.testTextInput.setClientArgs!['inputType']['name'], equals('TextInputType.address'));
expect((tester.testTextInput.setClientArgs!['inputType'] as Map<String, dynamic>)['name'], equals('TextInputType.address'));
},
);
@ -444,7 +444,7 @@ void main() {
controller.text = 'test';
await tester.idle();
expect(tester.testTextInput.editingState!['text'], equals('test'));
expect(tester.testTextInput.setClientArgs!['inputType']['name'], equals('TextInputType.text'));
expect((tester.testTextInput.setClientArgs!['inputType'] as Map<String, dynamic>)['name'], equals('TextInputType.text'));
},
variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }),
);
@ -479,7 +479,7 @@ void main() {
controller.text = 'test';
await tester.idle();
expect(tester.testTextInput.editingState!['text'], equals('test'));
expect(tester.testTextInput.setClientArgs!['inputType']['name'], equals('TextInputType.text'));
expect((tester.testTextInput.setClientArgs!['inputType'] as Map<String, dynamic>)['name'], equals('TextInputType.text'));
},
);
});
@ -511,7 +511,7 @@ void main() {
controller.text = 'test';
await tester.idle();
expect(tester.testTextInput.editingState!['text'], equals('test'));
expect(tester.testTextInput.setClientArgs!['inputType']['name'], equals('TextInputType.multiline'));
expect((tester.testTextInput.setClientArgs!['inputType'] as Map<String, dynamic>)['name'], equals('TextInputType.multiline'));
expect(tester.testTextInput.setClientArgs!['inputAction'], equals('TextInputAction.newline'));
});
@ -542,7 +542,7 @@ void main() {
controller.text = 'test';
await tester.idle();
expect(tester.testTextInput.editingState!['text'], equals('test'));
expect(tester.testTextInput.setClientArgs!['inputType']['name'], equals('TextInputType.visiblePassword'));
expect((tester.testTextInput.setClientArgs!['inputType'] as Map<String, dynamic>)['name'], equals('TextInputType.visiblePassword'));
expect(tester.testTextInput.setClientArgs!['inputAction'], equals('TextInputAction.done'));
});
@ -841,7 +841,7 @@ void main() {
controller.text = 'test';
await tester.idle();
expect(tester.testTextInput.editingState!['text'], equals('test'));
expect(tester.testTextInput.setClientArgs!['inputType']['name'], equals('TextInputType.multiline'));
expect((tester.testTextInput.setClientArgs!['inputType'] as Map<String, dynamic>)['name'], equals('TextInputType.multiline'));
expect(tester.testTextInput.setClientArgs!['inputAction'], equals('TextInputAction.newline'));
});
@ -873,7 +873,7 @@ void main() {
controller.text = 'test';
await tester.idle();
expect(tester.testTextInput.editingState!['text'], equals('test'));
expect(tester.testTextInput.setClientArgs!['inputType']['name'], equals('TextInputType.text'));
expect((tester.testTextInput.setClientArgs!['inputType'] as Map<String, dynamic>)['name'], equals('TextInputType.text'));
expect(tester.testTextInput.setClientArgs!['inputAction'], equals('TextInputAction.done'));
});
@ -905,7 +905,7 @@ void main() {
controller.text = 'test';
await tester.idle();
expect(tester.testTextInput.editingState!['text'], equals('test'));
expect(tester.testTextInput.setClientArgs!['inputType']['name'], equals('TextInputType.phone'));
expect((tester.testTextInput.setClientArgs!['inputType'] as Map<String, dynamic>)['name'], equals('TextInputType.phone'));
expect(tester.testTextInput.setClientArgs!['inputAction'], equals('TextInputAction.done'));
});
@ -936,7 +936,7 @@ void main() {
controller.text = 'test';
await tester.idle();
expect(tester.testTextInput.editingState!['text'], equals('test'));
expect(tester.testTextInput.setClientArgs!['inputType']['name'], equals('TextInputType.multiline'));
expect((tester.testTextInput.setClientArgs!['inputType'] as Map<String, dynamic>)['name'], equals('TextInputType.multiline'));
expect(tester.testTextInput.setClientArgs!['inputAction'], equals('TextInputAction.newline'));
});
@ -967,7 +967,7 @@ void main() {
controller.text = 'test';
await tester.idle();
expect(tester.testTextInput.editingState!['text'], equals('test'));
expect(tester.testTextInput.setClientArgs!['inputType']['name'], equals('TextInputType.text'));
expect((tester.testTextInput.setClientArgs!['inputType'] as Map<String, dynamic>)['name'], equals('TextInputType.text'));
expect(tester.testTextInput.setClientArgs!['inputAction'], equals('TextInputAction.done'));
});
@ -3260,7 +3260,7 @@ void main() {
await tester.showKeyboard(find.byType(EditableText));
final MethodCall setClient = log.first;
expect(setClient.method, 'TextInput.setClient');
expect(setClient.arguments.last['keyboardAppearance'], 'Brightness.light');
expect(((setClient.arguments as Iterable<dynamic>).last as Map<String, dynamic>)['keyboardAppearance'], 'Brightness.light');
});
testWidgets('location of widget is sent on show keyboard', (WidgetTester tester) async {
@ -3775,7 +3775,7 @@ void main() {
await tester.showKeyboard(find.byType(EditableText));
final MethodCall setClient = log.first;
expect(setClient.method, 'TextInput.setClient');
expect(setClient.arguments.last['keyboardAppearance'], 'Brightness.dark');
expect(((setClient.arguments as Iterable<dynamic>).last as Map<String, dynamic>)['keyboardAppearance'], 'Brightness.dark');
});
testWidgets('Composing text is underlined and underline is cleared when losing focus', (WidgetTester tester) async {

View file

@ -1523,6 +1523,7 @@ void main() {
await tester.pumpWidget(Container());
final dynamic exception = tester.takeException();
expect(
// ignore: avoid_dynamic_calls
exception.message,
equalsIgnoringHashCodes(
'Tried to build dirty widget in the wrong build scope.\n'

View file

@ -21,11 +21,13 @@ void main() {
child: const Text('loaded'),
));
final dynamic state = tester.state(find.byType(Localizations));
// ignore: avoid_dynamic_calls
expect(state!.locale, isNull);
expect(find.text('loaded'), findsNothing);
late Locale locale;
binding.onAllowFrame = () {
// ignore: avoid_dynamic_calls
locale = state.locale as Locale;
};
delegate.completer.complete('foo');

View file

@ -1582,6 +1582,7 @@ void main() {
final dynamic exception = tester.takeException();
expect(exception, isA<String>());
// ignore: avoid_dynamic_calls
expect(exception.startsWith('Could not navigate to initial route.'), isTrue);
// Only the root route should've been pushed.

View file

@ -1036,6 +1036,7 @@ void main() {
// By default, clipBehavior should be Clip.hardEdge
final dynamic renderObject = tester.renderObject(find.byType(Overlay));
// ignore: avoid_dynamic_calls
expect(renderObject.clipBehavior, equals(Clip.hardEdge));
for (final Clip clip in Clip.values) {
@ -1052,6 +1053,7 @@ void main() {
),
),
);
// ignore: avoid_dynamic_calls
expect(renderObject.clipBehavior, clip);
}
});

View file

@ -91,7 +91,9 @@ void main() {
final dynamic exception = tester.takeException();
expect(exception, isFlutterError);
// ignore: avoid_dynamic_calls
expect(exception.diagnostics.first.level, DiagnosticLevel.summary);
// ignore: avoid_dynamic_calls
expect(exception.diagnostics.first.toString(), startsWith('A RenderFlex overflowed by '));
await expectLater(
find.byKey(key),

View file

@ -27,9 +27,9 @@ void main() {
final _TestRestorableWidgetState state = tester.state(find.byType(_TestRestorableWidget));
expect(state.bucket?.restorationId, id);
expect(rawData[childrenMapKey].containsKey(id), isTrue);
expect((rawData[childrenMapKey] as Map<Object?, Object?>).containsKey(id), isTrue);
expect(state.property.value, 10);
expect(rawData[childrenMapKey][id][valuesMapKey]['foo'], 10);
expect((((rawData[childrenMapKey] as Map<Object?, Object?>)[id]! as Map<String, dynamic>)[valuesMapKey] as Map<Object?, Object?>)['foo'], 10);
expect(state.property.log, <String>['createDefaultValue', 'initWithValue', 'toPrimitives']);
expect(state.toggleBucketLog, isEmpty);
expect(state.restoreStateLog.single, isNull);
@ -139,7 +139,7 @@ void main() {
final Map<String, dynamic> rawData = _createRawDataSet();
final RestorationBucket root = RestorationBucket.root(manager: manager, rawData: rawData);
expect(rawData[childrenMapKey].containsKey('child1'), isTrue);
expect((rawData[childrenMapKey] as Map<String, dynamic>).containsKey('child1'), isTrue);
await tester.pumpWidget(
UnmanagedRestorationScope(
bucket: root,
@ -149,7 +149,7 @@ void main() {
),
);
manager.doSerialization();
expect(rawData[childrenMapKey].containsKey('child1'), isTrue);
expect((rawData[childrenMapKey] as Map<String, dynamic>).containsKey('child1'), isTrue);
await tester.pumpWidget(
UnmanagedRestorationScope(
@ -159,7 +159,7 @@ void main() {
);
manager.doSerialization();
expect(rawData[childrenMapKey].containsKey('child1'), isFalse);
expect((rawData[childrenMapKey] as Map<String, dynamic>).containsKey('child1'), isFalse);
});
testWidgets('toggling id between null and non-null', (WidgetTester tester) async {
@ -178,7 +178,7 @@ void main() {
final _TestRestorableWidgetState state = tester.state(find.byType(_TestRestorableWidget));
expect(state.bucket, isNull);
expect(state.property.value, 10); // Initialized to default.
expect(rawData[childrenMapKey]['child1'][valuesMapKey]['foo'], 22);
expect((((rawData[childrenMapKey] as Map<String, dynamic>)['child1'] as Map<String, dynamic>)[valuesMapKey] as Map<String, dynamic>)['foo'], 22);
expect(state.property.log, <String>['createDefaultValue', 'initWithValue']);
state.property.log.clear();
expect(state.restoreStateLog.single, isNull);
@ -199,7 +199,7 @@ void main() {
expect(state.bucket, isNotNull);
expect(state.bucket!.restorationId, 'child1');
expect(state.property.value, 10);
expect(rawData[childrenMapKey]['child1'][valuesMapKey]['foo'], 10);
expect((((rawData[childrenMapKey] as Map<String, dynamic>)['child1'] as Map<String, dynamic>)[valuesMapKey] as Map<String, dynamic>)['foo'], 10);
expect(state.property.log, <String>['toPrimitives']);
state.property.log.clear();
expect(state.restoreStateLog, isEmpty);
@ -220,7 +220,7 @@ void main() {
);
manager.doSerialization();
expect(state.bucket, isNull);
expect(rawData[childrenMapKey].containsKey('child1'), isFalse);
expect((rawData[childrenMapKey] as Map<String, dynamic>).containsKey('child1'), isFalse);
expect(state.property.log, isEmpty);
expect(state.restoreStateLog, isEmpty);
expect(state.toggleBucketLog.single, same(bucket));
@ -241,7 +241,7 @@ void main() {
final _TestRestorableWidgetState state = tester.state(find.byType(_TestRestorableWidget));
expect(state.bucket, isNull);
expect(state.property.value, 10); // Initialized to default.
expect(rawData[childrenMapKey]['child1'][valuesMapKey]['foo'], 22);
expect((((rawData[childrenMapKey] as Map<String, dynamic>)['child1'] as Map<String, dynamic>)[valuesMapKey] as Map<String, dynamic>)['foo'], 22);
expect(state.property.log, <String>['createDefaultValue', 'initWithValue']);
state.property.log.clear();
expect(state.restoreStateLog.single, isNull);
@ -263,7 +263,7 @@ void main() {
expect(state.bucket, isNotNull);
expect(state.bucket!.restorationId, 'child1');
expect(state.property.value, 10);
expect(rawData[childrenMapKey]['child1'][valuesMapKey]['foo'], 10);
expect((((rawData[childrenMapKey] as Map<String, dynamic>)['child1'] as Map<String, dynamic>)[valuesMapKey] as Map<String, dynamic>)['foo'], 10);
expect(state.property.log, <String>['toPrimitives']);
state.property.log.clear();
expect(state.restoreStateLog, isEmpty);
@ -282,7 +282,7 @@ void main() {
);
manager.doSerialization();
expect(state.bucket, isNull);
expect(rawData[childrenMapKey].containsKey('child1'), isFalse);
expect((rawData[childrenMapKey] as Map<String, dynamic>).containsKey('child1'), isFalse);
expect(state.property.log, isEmpty);
expect(state.restoreStateLog, isEmpty);
expect(state.toggleBucketLog.single, same(bucket));
@ -314,7 +314,7 @@ void main() {
manager.doSerialization();
final _TestRestorableWidgetState state = tester.state(find.byType(_TestRestorableWidget));
expect(state.bucket!.restorationId, 'moving-child');
expect(rawData[childrenMapKey]['fixed'][childrenMapKey].containsKey('moving-child'), isTrue);
expect((((rawData[childrenMapKey] as Map<Object?, Object?>)['fixed']! as Map<String, dynamic>)[childrenMapKey] as Map<Object?, Object?>).containsKey('moving-child'), isTrue);
final RestorationBucket bucket = state.bucket!;
state.property.log.clear();
state.restoreStateLog.clear();
@ -349,8 +349,8 @@ void main() {
expect(state.toggleBucketLog, isEmpty);
expect(state.restoreStateLog, isEmpty);
expect(rawData[childrenMapKey]['fixed'], isEmpty);
expect(rawData[childrenMapKey].containsKey('moving-child'), isTrue);
expect((rawData[childrenMapKey] as Map<Object?, Object?>)['fixed'], isEmpty);
expect((rawData[childrenMapKey] as Map<Object?, Object?>).containsKey('moving-child'), isTrue);
});
testWidgets('restartAndRestore', (WidgetTester tester) async {

View file

@ -72,7 +72,7 @@ void main() {
final BucketSpyState state = tester.state(find.byType(BucketSpy));
expect(state.bucket!.restorationId, id);
expect(rawData[childrenMapKey].containsKey(id), isTrue);
expect((rawData[childrenMapKey] as Map<Object?, Object?>).containsKey(id), isTrue);
});
testWidgets('bucket for descendants contains data claimed from parent', (WidgetTester tester) async {
@ -138,7 +138,7 @@ void main() {
final Map<String, dynamic> rawData = _createRawDataSet();
final RestorationBucket root = RestorationBucket.root(manager: manager, rawData: rawData);
expect(rawData[childrenMapKey].containsKey('child1'), isTrue);
expect((rawData[childrenMapKey] as Map<String, dynamic>).containsKey('child1'), isTrue);
await tester.pumpWidget(
UnmanagedRestorationScope(
bucket: root,
@ -149,7 +149,7 @@ void main() {
),
);
manager.doSerialization();
expect(rawData[childrenMapKey].containsKey('child1'), isTrue);
expect((rawData[childrenMapKey] as Map<String, dynamic>).containsKey('child1'), isTrue);
await tester.pumpWidget(
UnmanagedRestorationScope(
@ -159,7 +159,7 @@ void main() {
);
manager.doSerialization();
expect(rawData[childrenMapKey].containsKey('child1'), isFalse);
expect((rawData[childrenMapKey] as Map<String, dynamic>).containsKey('child1'), isFalse);
});
testWidgets('no bucket for descendants when id is null', (WidgetTester tester) async {
@ -286,7 +286,7 @@ void main() {
manager.doSerialization();
final BucketSpyState state = tester.state(find.byType(BucketSpy));
expect(state.bucket!.restorationId, 'moving-child');
expect(rawData[childrenMapKey]['fixed'][childrenMapKey].containsKey('moving-child'), isTrue);
expect((((rawData[childrenMapKey] as Map<Object?, Object?>)['fixed']! as Map<String, dynamic>)[childrenMapKey] as Map<Object?, Object?>).containsKey('moving-child'), isTrue);
final RestorationBucket bucket = state.bucket!;
state.bucket!.write('value', 11);
@ -317,8 +317,8 @@ void main() {
expect(state.bucket, same(bucket));
expect(state.bucket!.read<int>('value'), 11);
expect(rawData[childrenMapKey]['fixed'], isEmpty);
expect(rawData[childrenMapKey].containsKey('moving-child'), isTrue);
expect((rawData[childrenMapKey] as Map<Object?, Object?>)['fixed'], isEmpty);
expect((rawData[childrenMapKey] as Map<Object?, Object?>).containsKey('moving-child'), isTrue);
});
});
}

View file

@ -42,7 +42,7 @@ void main() {
expect(binding.restorationManager.rootBucketAccessed, 0);
final BucketSpyState state = tester.state(find.byType(BucketSpy));
expect(state.bucket!.restorationId, 'root-child');
expect(rawData[childrenMapKey].containsKey('root-child'), isTrue);
expect((rawData[childrenMapKey] as Map<Object?, Object?>).containsKey('root-child'), isTrue);
expect(find.text('Hello'), findsOneWidget);
});
@ -80,7 +80,7 @@ void main() {
final BucketSpyState state = tester.state(find.byType(BucketSpy));
expect(state.bucket!.restorationId, 'root-child');
expect(rawData[childrenMapKey].containsKey('root-child'), isTrue);
expect((rawData[childrenMapKey] as Map<Object?, Object?>).containsKey('root-child'), isTrue);
});
testWidgets('no delay when root is available synchronously', (WidgetTester tester) async {
@ -106,7 +106,7 @@ void main() {
final BucketSpyState state = tester.state(find.byType(BucketSpy));
expect(state.bucket!.restorationId, 'root-child');
expect(rawData[childrenMapKey].containsKey('root-child'), isTrue);
expect((rawData[childrenMapKey] as Map<Object?, Object?>).containsKey('root-child'), isTrue);
});
testWidgets('does not insert root when restoration id is null', (WidgetTester tester) async {
@ -201,7 +201,7 @@ void main() {
expect(find.text('Hello'), findsOneWidget);
final BucketSpyState state = tester.state(find.byType(BucketSpy));
expect(state.bucket!.restorationId, 'root-child');
expect(inScopeRawData[childrenMapKey].containsKey('root-child'), isTrue);
expect((inScopeRawData[childrenMapKey] as Map<Object?, Object?>).containsKey('root-child'), isTrue);
// Move out of scope.
final Completer<RestorationBucket> bucketCompleter = Completer<RestorationBucket>();
@ -230,7 +230,7 @@ void main() {
expect(binding.restorationManager.rootBucketAccessed, 1);
expect(find.text('Hello'), findsOneWidget);
expect(state.bucket!.restorationId, 'root-child');
expect(outOfScopeRawData[childrenMapKey].containsKey('root-child'), isTrue);
expect((outOfScopeRawData[childrenMapKey] as Map<Object?, Object?>).containsKey('root-child'), isTrue);
expect(inScopeRawData, isEmpty);
// Move into scope.
@ -254,7 +254,7 @@ void main() {
expect(find.text('Hello'), findsOneWidget);
expect(state.bucket!.restorationId, 'root-child');
expect(outOfScopeRawData, isEmpty);
expect(inScopeRawData[childrenMapKey].containsKey('root-child'), isTrue);
expect((inScopeRawData[childrenMapKey] as Map<Object?, Object?>).containsKey('root-child'), isTrue);
});
testWidgets('injects new root when old one is decommissioned', (WidgetTester tester) async {
@ -278,7 +278,7 @@ void main() {
expect(find.text('Hello'), findsOneWidget);
final BucketSpyState state = tester.state(find.byType(BucketSpy));
state.bucket!.write('foo', 42);
expect(firstRawData[childrenMapKey]['root-child'][valuesMapKey]['foo'], 42);
expect((((firstRawData[childrenMapKey] as Map<Object?, Object?>)['root-child']! as Map<String, dynamic>)[valuesMapKey] as Map<Object?, Object?>)['foo'], 42);
final RestorationBucket firstBucket = state.bucket!;
// Replace with new root.

View file

@ -1670,7 +1670,7 @@ void main() {
String clipboardContent = '';
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
if (methodCall.method == 'Clipboard.setData')
clipboardContent = methodCall.arguments['text'] as String;
clipboardContent = (methodCall.arguments as Map<String, dynamic>)['text'] as String;
else if (methodCall.method == 'Clipboard.getData')
return <String, dynamic>{'text': clipboardContent};
return null;

View file

@ -40,7 +40,9 @@ void main() {
final dynamic exception = tester.takeException();
expect(exception, isFlutterError);
// ignore: avoid_dynamic_calls
expect(exception.diagnostics.first.level, DiagnosticLevel.summary);
// ignore: avoid_dynamic_calls
expect(exception.diagnostics.first.toString(), contains('overflowed'));
expect(semantics, hasSemantics(
@ -102,7 +104,9 @@ void main() {
final dynamic exception = tester.takeException();
expect(exception, isFlutterError);
// ignore: avoid_dynamic_calls
expect(exception.diagnostics.first.level, DiagnosticLevel.summary);
// ignore: avoid_dynamic_calls
expect(exception.diagnostics.first.toString(), contains('overflowed'));
expect(semantics, hasSemantics(

View file

@ -461,6 +461,7 @@ void main() {
final RenderObject renderTextfield = tester.renderObject(find.descendant(of: find.byKey(textField), matching: find.byType(Semantics)).first);
expect(
// ignore: avoid_dynamic_calls
semanticsDebuggerPainter.getMessage(renderTextfield.debugSemantics),
'textfield',
);
@ -483,6 +484,7 @@ void main() {
),
);
// ignore: avoid_dynamic_calls
expect(_getSemanticsDebuggerPainter(debuggerKey: debugger, tester: tester).labelStyle, labelStyle);
});
}
@ -493,6 +495,7 @@ String _getMessageShownInSemanticsDebugger({
required WidgetTester tester,
}) {
final dynamic semanticsDebuggerPainter = _getSemanticsDebuggerPainter(debuggerKey: debuggerKey, tester: tester);
// ignore: avoid_dynamic_calls
return semanticsDebuggerPainter.getMessage(tester.renderObject(find.byKey(widgetKey)).debugSemantics) as String;
}

View file

@ -52,11 +52,11 @@ void main() {
// 1st, check that the render object has received the default clip behavior.
final dynamic renderObject = tester.allRenderObjects.where((RenderObject o) => o.runtimeType.toString() == '_RenderSingleChildViewport').first;
expect(renderObject.clipBehavior, equals(Clip.hardEdge));
expect(renderObject.clipBehavior, equals(Clip.hardEdge)); // ignore: avoid_dynamic_calls
// 2nd, height == widow.height test: check that the painting context does not call pushClipRect .
TestClipPaintingContext context = TestClipPaintingContext();
renderObject.paint(context, Offset.zero);
renderObject.paint(context, Offset.zero); // ignore: avoid_dynamic_calls
expect(context.clipBehavior, equals(Clip.none));
// 3rd, height overflow test: check that the painting context call pushClipRect.
@ -69,7 +69,7 @@ void main() {
),
),
);
renderObject.paint(context, Offset.zero);
renderObject.paint(context, Offset.zero); // ignore: avoid_dynamic_calls
expect(context.clipBehavior, equals(Clip.hardEdge));
// 4th, width == widow.width test: check that the painting context do not call pushClipRect.
@ -84,7 +84,7 @@ void main() {
),
),
);
renderObject.paint(context, Offset.zero);
renderObject.paint(context, Offset.zero); // ignore: avoid_dynamic_calls
expect(context.clipBehavior, equals(Clip.none));
// 5th, width overflow test: check that the painting context call pushClipRect.
@ -97,7 +97,7 @@ void main() {
),
),
);
renderObject.paint(context, Offset.zero);
renderObject.paint(context, Offset.zero); // ignore: avoid_dynamic_calls
expect(context.clipBehavior, equals(Clip.hardEdge));
});
@ -106,19 +106,19 @@ void main() {
// 1st, check that the render object has received the default clip behavior.
final dynamic renderObject = tester.allRenderObjects.where((RenderObject o) => o.runtimeType.toString() == '_RenderSingleChildViewport').first;
expect(renderObject.clipBehavior, equals(Clip.hardEdge));
expect(renderObject.clipBehavior, equals(Clip.hardEdge)); // ignore: avoid_dynamic_calls
// 2nd, check that the painting context has received the default clip behavior.
final TestClipPaintingContext context = TestClipPaintingContext();
renderObject.paint(context, Offset.zero);
renderObject.paint(context, Offset.zero); // ignore: avoid_dynamic_calls
expect(context.clipBehavior, equals(Clip.hardEdge));
// 3rd, pump a new widget to check that the render object can update its clip behavior.
await tester.pumpWidget(SingleChildScrollView(clipBehavior: Clip.antiAlias, child: Container(height: 2000.0)));
expect(renderObject.clipBehavior, equals(Clip.antiAlias));
expect(renderObject.clipBehavior, equals(Clip.antiAlias)); // ignore: avoid_dynamic_calls
// 4th, check that a non-default clip behavior can be sent to the painting context.
renderObject.paint(context, Offset.zero);
renderObject.paint(context, Offset.zero); // ignore: avoid_dynamic_calls
expect(context.clipBehavior, equals(Clip.antiAlias));
});

View file

@ -47,6 +47,7 @@ class StructureErrorTestWidgetInspectorService extends Object with WidgetInspect
expect(extensions, contains(name));
// Encode and decode to JSON to match behavior using a real service
// extension where only JSON is allowed.
// ignore: avoid_dynamic_calls
return json.decode(json.encode(await extensions[name]!(arguments)))['enabled'] as String;
}

View file

@ -318,11 +318,12 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
),
);
expect(getInspectorState().selection.current, isNull);
expect(getInspectorState().selection.current, isNull); // ignore: avoid_dynamic_calls
await tester.tap(find.text('TOP'), warnIfMissed: false);
await tester.pump();
// Tap intercepted by the inspector
expect(log, equals(<String>[]));
// ignore: avoid_dynamic_calls
final InspectorSelection selection = getInspectorState().selection as InspectorSelection;
expect(paragraphText(selection.current! as RenderParagraph), equals('TOP'));
final RenderObject topButton = find.byKey(topButtonKey).evaluate().first.renderObject!;
@ -336,6 +337,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(log, equals(<String>['bottom']));
log.clear();
// Ensure the inspector selection has not changed to bottom.
// ignore: avoid_dynamic_calls
expect(paragraphText(getInspectorState().selection.current as RenderParagraph), equals('TOP'));
await tester.tap(find.byKey(selectButtonKey));
@ -346,6 +348,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
await tester.tap(find.text('BOTTOM'), warnIfMissed: false);
expect(log, equals(<String>[]));
log.clear();
// ignore: avoid_dynamic_calls
expect(paragraphText(getInspectorState().selection.current as RenderParagraph), equals('BOTTOM'));
});
@ -419,7 +422,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
await tester.tap(find.byType(ListView), warnIfMissed: false);
await tester.pump();
expect(getInspectorState().selection.current, isNotNull);
expect(getInspectorState().selection.current, isNotNull); // ignore: avoid_dynamic_calls
// Now out of inspect mode due to the click.
await tester.fling(find.byType(ListView), const Offset(0.0, -200.0), 200.0);
@ -509,10 +512,12 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
final dynamic inspectorState = inspectorKey.currentState;
// The object with width 95.0 wins over the object with width 94.0 because
// the subtree with width 94.0 is offstage.
// ignore: avoid_dynamic_calls
expect(inspectorState.selection.current.semanticBounds.width, equals(95.0));
// Exactly 2 out of the 3 text elements should be in the candidate list of
// objects to select as only 2 are onstage.
// ignore: avoid_dynamic_calls
expect(inspectorState.selection.candidates.where((RenderObject object) => object is RenderParagraph).length, equals(2));
});
@ -620,6 +625,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
),
);
// ignore: avoid_dynamic_calls
final InspectorSelection selection = getInspectorState().selection as InspectorSelection;
// The selection is static, so it may be initialized from previous tests.
selection.clear();
@ -2853,12 +2859,14 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
service.setPubRootDirectories(<String>[pubRootTest]);
final String summary = service.getRootWidgetSummaryTree('foo1');
// ignore: avoid_dynamic_calls
final List<Object?> childrenOfRoot = json.decode(summary)['children'] as List<Object?>;
final List<Object?> childrenOfMaterialApp = (childrenOfRoot.first! as Map<String, Object?>)['children']! as List<Object?>;
final Map<String, Object?> scaffold = childrenOfMaterialApp.first! as Map<String, Object?>;
expect(scaffold['description'], 'Scaffold');
final String objectId = scaffold['objectId']! as String;
final String details = service.getDetailsSubtree(objectId, 'foo2');
// ignore: avoid_dynamic_calls
final List<Object?> detailedChildren = json.decode(details)['children'] as List<Object?>;
final List<Map<String, Object?>> appBars = <Map<String, Object?>>[];

View file

@ -41,14 +41,14 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
expect(extensions, contains(name));
// Encode and decode to JSON to match behavior using a real service
// extension where only JSON is allowed.
return json.decode(json.encode(await extensions[name]!(arguments)))['result'];
return (json.decode(json.encode(await extensions[name]!(arguments))) as Map<String, dynamic>)['result'];
}
Future<String> testBoolExtension(String name, Map<String, String> arguments) async {
expect(extensions, contains(name));
// Encode and decode to JSON to match behavior using a real service
// extension where only JSON is allowed.
return json.decode(json.encode(await extensions[name]!(arguments)))['enabled'] as String;
return (json.decode(json.encode(await extensions[name]!(arguments))) as Map<String, dynamic>)['enabled'] as String;
}
int rebuildCount = 0;