Unverified Commit 74cfc3db authored by Pierre-Louis's avatar Pierre-Louis Committed by GitHub

Use `curly_braces_in_flow_control_structures` for non-`flutter` packages (#104629)

* Use `curly_braces_in_flow_control_structures` for `packages/flutter_driver`

* Use `curly_braces_in_flow_control_structures` for `packages/flutter_goldens`

* Use `curly_braces_in_flow_control_structures` for `packages/flutter_goldens_client`

* Use `curly_braces_in_flow_control_structures` for `packages/flutter_localizations`

* Use `curly_braces_in_flow_control_structures` for `packages/flutter_test`

* Use `curly_braces_in_flow_control_structures` for `packages/flutter_web_plugins`

* fix comments

* Use `curly_braces_in_flow_control_structures` for `packages/integration_test`

* fix indentation
parent a0248ebd
...@@ -21,8 +21,9 @@ class DriverError extends Error { ...@@ -21,8 +21,9 @@ class DriverError extends Error {
@override @override
String toString() { String toString() {
if (originalError == null) if (originalError == null) {
return 'DriverError: $message\n'; return 'DriverError: $message\n';
}
return ''' return '''
DriverError: $message DriverError: $message
Original error: $originalError Original error: $originalError
......
...@@ -205,8 +205,9 @@ class ByValueKey extends SerializableFinder { ...@@ -205,8 +205,9 @@ class ByValueKey extends SerializableFinder {
ByValueKey(this.keyValue) ByValueKey(this.keyValue)
: keyValueString = '$keyValue', : keyValueString = '$keyValue',
keyValueType = '${keyValue.runtimeType}' { keyValueType = '${keyValue.runtimeType}' {
if (!_supportedKeyValueTypes.contains(keyValue.runtimeType)) if (!_supportedKeyValueTypes.contains(keyValue.runtimeType)) {
throw _createInvalidKeyValueTypeError('$keyValue.runtimeType'); throw _createInvalidKeyValueTypeError('$keyValue.runtimeType');
}
} }
/// The true value of the key. /// The true value of the key.
......
...@@ -260,8 +260,9 @@ mixin CommandHandlerFactory { ...@@ -260,8 +260,9 @@ mixin CommandHandlerFactory {
'This feature was deprecated after v1.9.3.' 'This feature was deprecated after v1.9.3.'
) )
Future<Result> _waitUntilNoTransientCallbacks(Command command) async { Future<Result> _waitUntilNoTransientCallbacks(Command command) async {
if (SchedulerBinding.instance.transientCallbackCount != 0) if (SchedulerBinding.instance.transientCallbackCount != 0) {
await _waitUntilFrame(() => SchedulerBinding.instance.transientCallbackCount == 0); await _waitUntilFrame(() => SchedulerBinding.instance.transientCallbackCount == 0);
}
return Result.empty; return Result.empty;
} }
...@@ -310,8 +311,9 @@ mixin CommandHandlerFactory { ...@@ -310,8 +311,9 @@ mixin CommandHandlerFactory {
node = renderObject.debugSemantics; node = renderObject.debugSemantics;
renderObject = renderObject.parent as RenderObject?; renderObject = renderObject.parent as RenderObject?;
} }
if (node == null) if (node == null) {
throw StateError('No semantics data found'); throw StateError('No semantics data found');
}
return GetSemanticsIdResult(node.id); return GetSemanticsIdResult(node.id);
} }
...@@ -464,26 +466,30 @@ mixin CommandHandlerFactory { ...@@ -464,26 +466,30 @@ mixin CommandHandlerFactory {
/// Runs `finder` repeatedly until it finds one or more [Element]s. /// Runs `finder` repeatedly until it finds one or more [Element]s.
Future<Finder> waitForElement(Finder finder) async { Future<Finder> waitForElement(Finder finder) async {
if (_frameSync) if (_frameSync) {
await _waitUntilFrame(() => SchedulerBinding.instance.transientCallbackCount == 0); await _waitUntilFrame(() => SchedulerBinding.instance.transientCallbackCount == 0);
}
await _waitUntilFrame(() => finder.evaluate().isNotEmpty); await _waitUntilFrame(() => finder.evaluate().isNotEmpty);
if (_frameSync) if (_frameSync) {
await _waitUntilFrame(() => SchedulerBinding.instance.transientCallbackCount == 0); await _waitUntilFrame(() => SchedulerBinding.instance.transientCallbackCount == 0);
}
return finder; return finder;
} }
/// Runs `finder` repeatedly until it finds zero [Element]s. /// Runs `finder` repeatedly until it finds zero [Element]s.
Future<Finder> waitForAbsentElement(Finder finder) async { Future<Finder> waitForAbsentElement(Finder finder) async {
if (_frameSync) if (_frameSync) {
await _waitUntilFrame(() => SchedulerBinding.instance.transientCallbackCount == 0); await _waitUntilFrame(() => SchedulerBinding.instance.transientCallbackCount == 0);
}
await _waitUntilFrame(() => finder.evaluate().isEmpty); await _waitUntilFrame(() => finder.evaluate().isEmpty);
if (_frameSync) if (_frameSync) {
await _waitUntilFrame(() => SchedulerBinding.instance.transientCallbackCount == 0); await _waitUntilFrame(() => SchedulerBinding.instance.transientCallbackCount == 0);
}
return finder; return finder;
} }
......
...@@ -17,8 +17,9 @@ abstract class Command { ...@@ -17,8 +17,9 @@ abstract class Command {
static Duration? _parseTimeout(Map<String, String> json) { static Duration? _parseTimeout(Map<String, String> json) {
final String? timeout = json['timeout']; final String? timeout = json['timeout'];
if (timeout == null) if (timeout == null) {
return null; return null;
}
return Duration(milliseconds: int.parse(timeout)); return Duration(milliseconds: int.parse(timeout));
} }
...@@ -52,8 +53,9 @@ abstract class Command { ...@@ -52,8 +53,9 @@ abstract class Command {
final Map<String, String> result = <String, String>{ final Map<String, String> result = <String, String>{
'command': kind, 'command': kind,
}; };
if (timeout != null) if (timeout != null) {
result['timeout'] = '${timeout!.inMilliseconds}'; result['timeout'] = '${timeout!.inMilliseconds}';
}
return result; return result;
} }
} }
......
...@@ -95,8 +95,9 @@ class NoTransientCallbacks extends SerializableWaitCondition { ...@@ -95,8 +95,9 @@ class NoTransientCallbacks extends SerializableWaitCondition {
/// The [json] argument must not be null. /// The [json] argument must not be null.
factory NoTransientCallbacks.deserialize(Map<String, String> json) { factory NoTransientCallbacks.deserialize(Map<String, String> json) {
assert(json != null); assert(json != null);
if (json['conditionName'] != 'NoTransientCallbacksCondition') if (json['conditionName'] != 'NoTransientCallbacksCondition') {
throw SerializationException('Error occurred during deserializing the NoTransientCallbacksCondition JSON string: $json'); throw SerializationException('Error occurred during deserializing the NoTransientCallbacksCondition JSON string: $json');
}
return const NoTransientCallbacks(); return const NoTransientCallbacks();
} }
...@@ -115,8 +116,9 @@ class NoPendingFrame extends SerializableWaitCondition { ...@@ -115,8 +116,9 @@ class NoPendingFrame extends SerializableWaitCondition {
/// The [json] argument must not be null. /// The [json] argument must not be null.
factory NoPendingFrame.deserialize(Map<String, String> json) { factory NoPendingFrame.deserialize(Map<String, String> json) {
assert(json != null); assert(json != null);
if (json['conditionName'] != 'NoPendingFrameCondition') if (json['conditionName'] != 'NoPendingFrameCondition') {
throw SerializationException('Error occurred during deserializing the NoPendingFrameCondition JSON string: $json'); throw SerializationException('Error occurred during deserializing the NoPendingFrameCondition JSON string: $json');
}
return const NoPendingFrame(); return const NoPendingFrame();
} }
...@@ -135,8 +137,9 @@ class FirstFrameRasterized extends SerializableWaitCondition { ...@@ -135,8 +137,9 @@ class FirstFrameRasterized extends SerializableWaitCondition {
/// The [json] argument must not be null. /// The [json] argument must not be null.
factory FirstFrameRasterized.deserialize(Map<String, String> json) { factory FirstFrameRasterized.deserialize(Map<String, String> json) {
assert(json != null); assert(json != null);
if (json['conditionName'] != 'FirstFrameRasterizedCondition') if (json['conditionName'] != 'FirstFrameRasterizedCondition') {
throw SerializationException('Error occurred during deserializing the FirstFrameRasterizedCondition JSON string: $json'); throw SerializationException('Error occurred during deserializing the FirstFrameRasterizedCondition JSON string: $json');
}
return const FirstFrameRasterized(); return const FirstFrameRasterized();
} }
...@@ -158,8 +161,9 @@ class NoPendingPlatformMessages extends SerializableWaitCondition { ...@@ -158,8 +161,9 @@ class NoPendingPlatformMessages extends SerializableWaitCondition {
/// The [json] argument must not be null. /// The [json] argument must not be null.
factory NoPendingPlatformMessages.deserialize(Map<String, String> json) { factory NoPendingPlatformMessages.deserialize(Map<String, String> json) {
assert(json != null); assert(json != null);
if (json['conditionName'] != 'NoPendingPlatformMessagesCondition') if (json['conditionName'] != 'NoPendingPlatformMessagesCondition') {
throw SerializationException('Error occurred during deserializing the NoPendingPlatformMessagesCondition JSON string: $json'); throw SerializationException('Error occurred during deserializing the NoPendingPlatformMessagesCondition JSON string: $json');
}
return const NoPendingPlatformMessages(); return const NoPendingPlatformMessages();
} }
...@@ -181,8 +185,9 @@ class CombinedCondition extends SerializableWaitCondition { ...@@ -181,8 +185,9 @@ class CombinedCondition extends SerializableWaitCondition {
/// The [jsonMap] argument must not be null. /// The [jsonMap] argument must not be null.
factory CombinedCondition.deserialize(Map<String, String> jsonMap) { factory CombinedCondition.deserialize(Map<String, String> jsonMap) {
assert(jsonMap != null); assert(jsonMap != null);
if (jsonMap['conditionName'] != 'CombinedCondition') if (jsonMap['conditionName'] != 'CombinedCondition') {
throw SerializationException('Error occurred during deserializing the CombinedCondition JSON string: $jsonMap'); throw SerializationException('Error occurred during deserializing the CombinedCondition JSON string: $jsonMap');
}
if (jsonMap['conditions'] == null) { if (jsonMap['conditions'] == null) {
return const CombinedCondition(<SerializableWaitCondition>[]); return const CombinedCondition(<SerializableWaitCondition>[]);
} }
......
...@@ -410,23 +410,26 @@ class TimelineSummary { ...@@ -410,23 +410,26 @@ class TimelineSummary {
} }
double _averageInMillis(Iterable<Duration> durations) { double _averageInMillis(Iterable<Duration> durations) {
if (durations.isEmpty) if (durations.isEmpty) {
throw ArgumentError('durations is empty!'); throw ArgumentError('durations is empty!');
}
final double total = durations.fold<double>(0.0, (double t, Duration duration) => t + duration.inMicroseconds.toDouble() / 1000.0); final double total = durations.fold<double>(0.0, (double t, Duration duration) => t + duration.inMicroseconds.toDouble() / 1000.0);
return total / durations.length; return total / durations.length;
} }
double _percentileInMillis(Iterable<Duration> durations, double percentile) { double _percentileInMillis(Iterable<Duration> durations, double percentile) {
if (durations.isEmpty) if (durations.isEmpty) {
throw ArgumentError('durations is empty!'); throw ArgumentError('durations is empty!');
}
assert(percentile >= 0.0 && percentile <= 100.0); assert(percentile >= 0.0 && percentile <= 100.0);
final List<double> doubles = durations.map<double>((Duration duration) => duration.inMicroseconds.toDouble() / 1000.0).toList(); final List<double> doubles = durations.map<double>((Duration duration) => duration.inMicroseconds.toDouble() / 1000.0).toList();
return findPercentile(doubles, percentile); return findPercentile(doubles, percentile);
} }
double _maxInMillis(Iterable<Duration> durations) { double _maxInMillis(Iterable<Duration> durations) {
if (durations.isEmpty) if (durations.isEmpty) {
throw ArgumentError('durations is empty!'); throw ArgumentError('durations is empty!');
}
return durations return durations
.map<double>((Duration duration) => duration.inMicroseconds.toDouble() / 1000.0) .map<double>((Duration duration) => duration.inMicroseconds.toDouble() / 1000.0)
.reduce(math.max); .reduce(math.max);
......
...@@ -321,14 +321,16 @@ class VMServiceFlutterDriver extends FlutterDriver { ...@@ -321,14 +321,16 @@ class VMServiceFlutterDriver extends FlutterDriver {
stackTrace, stackTrace,
); );
} }
if ((response['isError'] as bool?) ?? false) if ((response['isError'] as bool?) ?? false) {
throw DriverError('Error in Flutter application: ${response['response']}'); throw DriverError('Error in Flutter application: ${response['response']}');
}
return response['response'] as Map<String, dynamic>; return response['response'] as Map<String, dynamic>;
} }
void _logCommunication(String message) { void _logCommunication(String message) {
if (_printCommunication) if (_printCommunication) {
_log(message); _log(message);
}
if (_logCommunicationToFile) { if (_logCommunicationToFile) {
assert(_logFilePathName != null); assert(_logFilePathName != null);
final f.File file = fs.file(_logFilePathName); final f.File file = fs.file(_logFilePathName);
...@@ -533,8 +535,9 @@ String _getWebSocketUrl(String url) { ...@@ -533,8 +535,9 @@ String _getWebSocketUrl(String url) {
if (uri.pathSegments.isNotEmpty) uri.pathSegments.first, if (uri.pathSegments.isNotEmpty) uri.pathSegments.first,
'ws', 'ws',
]; ];
if (uri.scheme == 'http') if (uri.scheme == 'http') {
uri = uri.replace(scheme: 'ws', pathSegments: pathSegments); uri = uri.replace(scheme: 'ws', pathSegments: pathSegments);
}
return uri.toString(); return uri.toString();
} }
......
...@@ -377,8 +377,9 @@ class FlutterDriverExtension with DeserializeFinderFactory, CreateFinderFactory, ...@@ -377,8 +377,9 @@ class FlutterDriverExtension with DeserializeFinderFactory, CreateFinderFactory,
return _makeResponse(message, isError: true); return _makeResponse(message, isError: true);
} catch (error, stackTrace) { } catch (error, stackTrace) {
final String message = 'Uncaught extension error while executing $commandKind: $error\n$stackTrace'; final String message = 'Uncaught extension error while executing $commandKind: $error\n$stackTrace';
if (!_silenceErrors) if (!_silenceErrors) {
_log(message); _log(message);
}
return _makeResponse(message, isError: true); return _makeResponse(message, isError: true);
} }
} }
......
...@@ -43,8 +43,9 @@ class _InternalNoTransientCallbacksCondition implements WaitCondition { ...@@ -43,8 +43,9 @@ class _InternalNoTransientCallbacksCondition implements WaitCondition {
/// The [condition] argument must not be null. /// The [condition] argument must not be null.
factory _InternalNoTransientCallbacksCondition.deserialize(SerializableWaitCondition condition) { factory _InternalNoTransientCallbacksCondition.deserialize(SerializableWaitCondition condition) {
assert(condition != null); assert(condition != null);
if (condition.conditionName != 'NoTransientCallbacksCondition') if (condition.conditionName != 'NoTransientCallbacksCondition') {
throw SerializationException('Error occurred during deserializing from the given condition: ${condition.serialize()}'); throw SerializationException('Error occurred during deserializing from the given condition: ${condition.serialize()}');
}
return const _InternalNoTransientCallbacksCondition(); return const _InternalNoTransientCallbacksCondition();
} }
...@@ -71,8 +72,9 @@ class _InternalNoPendingFrameCondition implements WaitCondition { ...@@ -71,8 +72,9 @@ class _InternalNoPendingFrameCondition implements WaitCondition {
/// The [condition] argument must not be null. /// The [condition] argument must not be null.
factory _InternalNoPendingFrameCondition.deserialize(SerializableWaitCondition condition) { factory _InternalNoPendingFrameCondition.deserialize(SerializableWaitCondition condition) {
assert(condition != null); assert(condition != null);
if (condition.conditionName != 'NoPendingFrameCondition') if (condition.conditionName != 'NoPendingFrameCondition') {
throw SerializationException('Error occurred during deserializing from the given condition: ${condition.serialize()}'); throw SerializationException('Error occurred during deserializing from the given condition: ${condition.serialize()}');
}
return const _InternalNoPendingFrameCondition(); return const _InternalNoPendingFrameCondition();
} }
...@@ -99,8 +101,9 @@ class _InternalFirstFrameRasterizedCondition implements WaitCondition { ...@@ -99,8 +101,9 @@ class _InternalFirstFrameRasterizedCondition implements WaitCondition {
/// The [condition] argument must not be null. /// The [condition] argument must not be null.
factory _InternalFirstFrameRasterizedCondition.deserialize(SerializableWaitCondition condition) { factory _InternalFirstFrameRasterizedCondition.deserialize(SerializableWaitCondition condition) {
assert(condition != null); assert(condition != null);
if (condition.conditionName != 'FirstFrameRasterizedCondition') if (condition.conditionName != 'FirstFrameRasterizedCondition') {
throw SerializationException('Error occurred during deserializing from the given condition: ${condition.serialize()}'); throw SerializationException('Error occurred during deserializing from the given condition: ${condition.serialize()}');
}
return const _InternalFirstFrameRasterizedCondition(); return const _InternalFirstFrameRasterizedCondition();
} }
...@@ -125,8 +128,9 @@ class _InternalNoPendingPlatformMessagesCondition implements WaitCondition { ...@@ -125,8 +128,9 @@ class _InternalNoPendingPlatformMessagesCondition implements WaitCondition {
/// The [condition] argument must not be null. /// The [condition] argument must not be null.
factory _InternalNoPendingPlatformMessagesCondition.deserialize(SerializableWaitCondition condition) { factory _InternalNoPendingPlatformMessagesCondition.deserialize(SerializableWaitCondition condition) {
assert(condition != null); assert(condition != null);
if (condition.conditionName != 'NoPendingPlatformMessagesCondition') if (condition.conditionName != 'NoPendingPlatformMessagesCondition') {
throw SerializationException('Error occurred during deserializing from the given condition: ${condition.serialize()}'); throw SerializationException('Error occurred during deserializing from the given condition: ${condition.serialize()}');
}
return const _InternalNoPendingPlatformMessagesCondition(); return const _InternalNoPendingPlatformMessagesCondition();
} }
...@@ -161,8 +165,9 @@ class _InternalCombinedCondition implements WaitCondition { ...@@ -161,8 +165,9 @@ class _InternalCombinedCondition implements WaitCondition {
/// The [condition] argument must not be null. /// The [condition] argument must not be null.
factory _InternalCombinedCondition.deserialize(SerializableWaitCondition condition) { factory _InternalCombinedCondition.deserialize(SerializableWaitCondition condition) {
assert(condition != null); assert(condition != null);
if (condition.conditionName != 'CombinedCondition') if (condition.conditionName != 'CombinedCondition') {
throw SerializationException('Error occurred during deserializing from the given condition: ${condition.serialize()}'); throw SerializationException('Error occurred during deserializing from the given condition: ${condition.serialize()}');
}
final CombinedCondition combinedCondition = condition as CombinedCondition; final CombinedCondition combinedCondition = condition as CombinedCondition;
final List<WaitCondition> conditions = combinedCondition.conditions.map(deserializeCondition).toList(); final List<WaitCondition> conditions = combinedCondition.conditions.map(deserializeCondition).toList();
return _InternalCombinedCondition(conditions); return _InternalCombinedCondition(conditions);
......
...@@ -314,8 +314,9 @@ class FlutterPreSubmitFileComparator extends FlutterGoldenFileComparator { ...@@ -314,8 +314,9 @@ class FlutterPreSubmitFileComparator extends FlutterGoldenFileComparator {
suffix: 'flutter_goldens_presubmit.', suffix: 'flutter_goldens_presubmit.',
); );
if (!baseDirectory.existsSync()) if (!baseDirectory.existsSync()) {
baseDirectory.createSync(recursive: true); baseDirectory.createSync(recursive: true);
}
goldens ??= SkiaGoldClient(baseDirectory); goldens ??= SkiaGoldClient(baseDirectory);
...@@ -535,8 +536,9 @@ class FlutterLocalFileComparator extends FlutterGoldenFileComparator with LocalC ...@@ -535,8 +536,9 @@ class FlutterLocalFileComparator extends FlutterGoldenFileComparator with LocalC
goldenBytes, goldenBytes,
); );
if (result.passed) if (result.passed) {
return true; return true;
}
final String error = await generateFailureOutput(result, golden, basedir); final String error = await generateFailureOutput(result, golden, basedir);
throw FlutterError(error); throw FlutterError(error);
......
...@@ -83,8 +83,9 @@ class SkiaGoldClient { ...@@ -83,8 +83,9 @@ class SkiaGoldClient {
/// Used by the [FlutterPostSubmitFileComparator] and the /// Used by the [FlutterPostSubmitFileComparator] and the
/// [FlutterPreSubmitFileComparator]. /// [FlutterPreSubmitFileComparator].
Future<void> auth() async { Future<void> auth() async {
if (await clientIsAuthorized()) if (await clientIsAuthorized()) {
return; return;
}
final List<String> authCommand = <String>[ final List<String> authCommand = <String>[
_goldctl, _goldctl,
'auth', 'auth',
...@@ -124,8 +125,9 @@ class SkiaGoldClient { ...@@ -124,8 +125,9 @@ class SkiaGoldClient {
/// [FlutterPostSubmitFileComparator]. /// [FlutterPostSubmitFileComparator].
Future<void> imgtestInit() async { Future<void> imgtestInit() async {
// This client has already been intialized // This client has already been intialized
if (_initialized) if (_initialized) {
return; return;
}
final File keys = workDirectory.childFile('keys.json'); final File keys = workDirectory.childFile('keys.json');
final File failures = workDirectory.childFile('failures.json'); final File failures = workDirectory.childFile('failures.json');
...@@ -234,8 +236,9 @@ class SkiaGoldClient { ...@@ -234,8 +236,9 @@ class SkiaGoldClient {
/// [FlutterPreSubmitFileComparator]. /// [FlutterPreSubmitFileComparator].
Future<void> tryjobInit() async { Future<void> tryjobInit() async {
// This client has already been initialized // This client has already been initialized
if (_tryjobInitialized) if (_tryjobInitialized) {
return; return;
}
final File keys = workDirectory.childFile('keys.json'); final File keys = workDirectory.childFile('keys.json');
final File failures = workDirectory.childFile('failures.json'); final File failures = workDirectory.childFile('failures.json');
...@@ -385,8 +388,9 @@ class SkiaGoldClient { ...@@ -385,8 +388,9 @@ class SkiaGoldClient {
final io.HttpClientResponse response = await request.close(); final io.HttpClientResponse response = await request.close();
rawResponse = await utf8.decodeStream(response); rawResponse = await utf8.decodeStream(response);
final dynamic jsonResponse = json.decode(rawResponse); final dynamic jsonResponse = json.decode(rawResponse);
if (jsonResponse is! Map<String, dynamic>) if (jsonResponse is! Map<String, dynamic>) {
throw const FormatException('Skia gold expectations do not match expected format.'); throw const FormatException('Skia gold expectations do not match expected format.');
}
expectation = jsonResponse['digest'] as String?; expectation = jsonResponse['digest'] as String?;
} on FormatException catch (error) { } on FormatException catch (error) {
// Ideally we'd use something like package:test's printOnError, but best reliabilty // Ideally we'd use something like package:test's printOnError, but best reliabilty
......
...@@ -436,8 +436,9 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations { ...@@ -436,8 +436,9 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
@override @override
TimeOfDayFormat timeOfDayFormat({ bool alwaysUse24HourFormat = false }) { TimeOfDayFormat timeOfDayFormat({ bool alwaysUse24HourFormat = false }) {
assert(alwaysUse24HourFormat != null); assert(alwaysUse24HourFormat != null);
if (alwaysUse24HourFormat) if (alwaysUse24HourFormat) {
return _get24HourVersionOf(timeOfDayFormatRaw); return _get24HourVersionOf(timeOfDayFormatRaw);
}
return timeOfDayFormatRaw; return timeOfDayFormatRaw;
} }
......
...@@ -7,8 +7,9 @@ void encodeBundleTranslations(Map<String, dynamic> bundle) { ...@@ -7,8 +7,9 @@ void encodeBundleTranslations(Map<String, dynamic> bundle) {
for (final String key in bundle.keys) { for (final String key in bundle.keys) {
// The ARB file resource "attributes" for foo are called @foo. Don't need // The ARB file resource "attributes" for foo are called @foo. Don't need
// to encode them. // to encode them.
if (key.startsWith('@')) if (key.startsWith('@')) {
continue; continue;
}
final String translation = bundle[key] as String; final String translation = bundle[key] as String;
// Rewrite the string as a series of unicode characters in JSON format. // Rewrite the string as a series of unicode characters in JSON format.
// Like "\u0012\u0123\u1234". // Like "\u0012\u0123\u1234".
......
...@@ -1428,8 +1428,9 @@ void main() { ...@@ -1428,8 +1428,9 @@ void main() {
Locale('de', 'DE'), Locale('de', 'DE'),
], ],
localeResolutionCallback: (Locale? locale, Iterable<Locale> supportedLocales) { localeResolutionCallback: (Locale? locale, Iterable<Locale> supportedLocales) {
if (locale == null) if (locale == null) {
return const Locale('und', 'US'); return const Locale('und', 'US');
}
return const Locale('en', 'US'); return const Locale('en', 'US');
}, },
buildContent: (BuildContext context) { buildContent: (BuildContext context) {
......
...@@ -173,11 +173,12 @@ mixin LocalComparisonOutput { ...@@ -173,11 +173,12 @@ mixin LocalComparisonOutput {
/// Returns a [ComparisonResult] to describe the pixel differential of the /// Returns a [ComparisonResult] to describe the pixel differential of the
/// [test] and [master] image bytes provided. /// [test] and [master] image bytes provided.
Future<ComparisonResult> compareLists(List<int>? test, List<int>? master) async { Future<ComparisonResult> compareLists(List<int>? test, List<int>? master) async {
if (identical(test, master)) if (identical(test, master)) {
return ComparisonResult( return ComparisonResult(
passed: true, passed: true,
diffPercent: 0.0, diffPercent: 0.0,
); );
}
if (test == null || master == null || test.isEmpty || master.isEmpty) { if (test == null || master == null || test.isEmpty || master.isEmpty) {
return ComparisonResult( return ComparisonResult(
......
...@@ -91,8 +91,9 @@ class MatchesGoldenFile extends AsyncMatcher { ...@@ -91,8 +91,9 @@ class MatchesGoldenFile extends AsyncMatcher {
throw AssertionError('Future<Image> completed to null'); throw AssertionError('Future<Image> completed to null');
} }
final ByteData? bytes = await image.toByteData(format: ui.ImageByteFormat.png); final ByteData? bytes = await image.toByteData(format: ui.ImageByteFormat.png);
if (bytes == null) if (bytes == null) {
return 'could not encode screenshot.'; return 'could not encode screenshot.';
}
if (autoUpdateGoldenFiles) { if (autoUpdateGoldenFiles) {
await goldenFileComparator.update(testNameUri, bytes.buffer.asUint8List()); await goldenFileComparator.update(testNameUri, bytes.buffer.asUint8List());
return null; return null;
......
...@@ -62,8 +62,9 @@ class _DepthFirstChildIterator implements Iterator<Element> { ...@@ -62,8 +62,9 @@ class _DepthFirstChildIterator implements Iterator<Element> {
@override @override
bool moveNext() { bool moveNext() {
if (_stack.isEmpty) if (_stack.isEmpty) {
return false; return false;
}
_current = _stack.removeLast(); _current = _stack.removeLast();
_fillChildren(_current); _fillChildren(_current);
......
...@@ -500,8 +500,9 @@ class _RenderRootableRepaintBoundary extends RenderRepaintBoundary { ...@@ -500,8 +500,9 @@ class _RenderRootableRepaintBoundary extends RenderRepaintBoundary {
TransformLayer _rootLayer() { TransformLayer _rootLayer() {
Layer layer = this.layer!; Layer layer = this.layer!;
while (layer.parent != null) while (layer.parent != null) {
layer = layer.parent!; layer = layer.parent!;
}
return layer as TransformLayer; return layer as TransformLayer;
} }
} }
......
...@@ -179,8 +179,9 @@ abstract class TestWidgetsFlutterBinding extends BindingBase ...@@ -179,8 +179,9 @@ abstract class TestWidgetsFlutterBinding extends BindingBase
_restorationManager = null; _restorationManager = null;
resetGestureBinding(); resetGestureBinding();
testTextInput.reset(); testTextInput.reset();
if (registerTestTextInput) if (registerTestTextInput) {
_testTextInput.register(); _testTextInput.register();
}
} }
@override @override
...@@ -306,8 +307,9 @@ abstract class TestWidgetsFlutterBinding extends BindingBase ...@@ -306,8 +307,9 @@ abstract class TestWidgetsFlutterBinding extends BindingBase
/// ///
/// This is called automatically by [testWidgets]. /// This is called automatically by [testWidgets].
static TestWidgetsFlutterBinding ensureInitialized([@visibleForTesting Map<String, String>? environment]) { static TestWidgetsFlutterBinding ensureInitialized([@visibleForTesting Map<String, String>? environment]) {
if (_instance != null) if (_instance != null) {
return _instance!; return _instance!;
}
return binding.ensureInitialized(environment); return binding.ensureInitialized(environment);
} }
...@@ -435,8 +437,9 @@ abstract class TestWidgetsFlutterBinding extends BindingBase ...@@ -435,8 +437,9 @@ abstract class TestWidgetsFlutterBinding extends BindingBase
Future<void> setSurfaceSize(Size? size) { Future<void> setSurfaceSize(Size? size) {
return TestAsyncUtils.guard<void>(() async { return TestAsyncUtils.guard<void>(() async {
assert(inTest); assert(inTest);
if (_surfaceSize == size) if (_surfaceSize == size) {
return; return;
}
_surfaceSize = size; _surfaceSize = size;
handleMetricsChanged(); handleMetricsChanged();
}); });
...@@ -663,8 +666,9 @@ abstract class TestWidgetsFlutterBinding extends BindingBase ...@@ -663,8 +666,9 @@ abstract class TestWidgetsFlutterBinding extends BindingBase
reportTestException(_pendingExceptionDetails!, testDescription); reportTestException(_pendingExceptionDetails!, testDescription);
_pendingExceptionDetails = null; _pendingExceptionDetails = null;
} }
if (!completer.isCompleted) if (!completer.isCompleted) {
completer.complete(); completer.complete();
}
}; };
} }
...@@ -714,10 +718,12 @@ abstract class TestWidgetsFlutterBinding extends BindingBase ...@@ -714,10 +718,12 @@ abstract class TestWidgetsFlutterBinding extends BindingBase
// information to stack traces, in this case the Trace and Chain classes // information to stack traces, in this case the Trace and Chain classes
// can be present. Because these StackTrace implementations do not follow // can be present. Because these StackTrace implementations do not follow
// the format the framework expects, we covert them to a vm trace here. // the format the framework expects, we covert them to a vm trace here.
if (stack is stack_trace.Trace) if (stack is stack_trace.Trace) {
return stack.vmTrace; return stack.vmTrace;
if (stack is stack_trace.Chain) }
if (stack is stack_trace.Chain) {
return stack.toTrace().vmTrace; return stack.toTrace().vmTrace;
}
return stack; return stack;
}; };
final Completer<void> testCompleter = Completer<void>(); final Completer<void> testCompleter = Completer<void>();
...@@ -789,13 +795,15 @@ abstract class TestWidgetsFlutterBinding extends BindingBase ...@@ -789,13 +795,15 @@ abstract class TestWidgetsFlutterBinding extends BindingBase
return FlutterError.defaultStackFilter(frames.skip(stackLinesToOmit)); return FlutterError.defaultStackFilter(frames.skip(stackLinesToOmit));
}, },
informationCollector: () sync* { informationCollector: () sync* {
if (stackLinesToOmit > 0) if (stackLinesToOmit > 0) {
yield* omittedFrames; yield* omittedFrames;
}
if (showAppDumpInErrors) { if (showAppDumpInErrors) {
yield DiagnosticsProperty<DiagnosticsNode>('At the time of the failure, the widget tree looked as follows', treeDump, linePrefix: '# ', style: DiagnosticsTreeStyle.flat); yield DiagnosticsProperty<DiagnosticsNode>('At the time of the failure, the widget tree looked as follows', treeDump, linePrefix: '# ', style: DiagnosticsTreeStyle.flat);
} }
if (description.isNotEmpty) if (description.isNotEmpty) {
yield DiagnosticsProperty<String>('The test description was', description, style: DiagnosticsTreeStyle.errorProperty); yield DiagnosticsProperty<String>('The test description was', description, style: DiagnosticsTreeStyle.errorProperty);
}
}, },
)); ));
assert(_parentZone != null); assert(_parentZone != null);
...@@ -839,8 +847,9 @@ abstract class TestWidgetsFlutterBinding extends BindingBase ...@@ -839,8 +847,9 @@ abstract class TestWidgetsFlutterBinding extends BindingBase
// alone so that we don't cause more spurious errors. // alone so that we don't cause more spurious errors.
runApp(Container(key: UniqueKey(), child: _postTestMessage)); // Unmount any remaining widgets. runApp(Container(key: UniqueKey(), child: _postTestMessage)); // Unmount any remaining widgets.
await pump(); await pump();
if (registerTestTextInput) if (registerTestTextInput) {
_testTextInput.unregister(); _testTextInput.unregister();
}
invariantTester(); invariantTester();
_verifyAutoUpdateGoldensUnset(autoUpdateGoldensBeforeTest && !isBrowser); _verifyAutoUpdateGoldensUnset(autoUpdateGoldensBeforeTest && !isBrowser);
_verifyReportTestExceptionUnset(reportTestExceptionBeforeTest); _verifyReportTestExceptionUnset(reportTestExceptionBeforeTest);
...@@ -995,8 +1004,9 @@ class AutomatedTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding { ...@@ -995,8 +1004,9 @@ class AutomatedTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding {
/// will select the correct test binding implementation /// will select the correct test binding implementation
/// automatically. /// automatically.
static AutomatedTestWidgetsFlutterBinding ensureInitialized() { static AutomatedTestWidgetsFlutterBinding ensureInitialized() {
if (AutomatedTestWidgetsFlutterBinding._instance == null) if (AutomatedTestWidgetsFlutterBinding._instance == null) {
AutomatedTestWidgetsFlutterBinding(); AutomatedTestWidgetsFlutterBinding();
}
return AutomatedTestWidgetsFlutterBinding.instance; return AutomatedTestWidgetsFlutterBinding.instance;
} }
...@@ -1033,8 +1043,9 @@ class AutomatedTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding { ...@@ -1033,8 +1043,9 @@ class AutomatedTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding {
return TestAsyncUtils.guard<void>(() { return TestAsyncUtils.guard<void>(() {
assert(inTest); assert(inTest);
assert(_clock != null); assert(_clock != null);
if (duration != null) if (duration != null) {
_currentFakeAsync!.elapse(duration); _currentFakeAsync!.elapse(duration);
}
_phase = newPhase; _phase = newPhase;
if (hasScheduledFrame) { if (hasScheduledFrame) {
addTime(const Duration(milliseconds: 500)); addTime(const Duration(milliseconds: 500));
...@@ -1057,8 +1068,9 @@ class AutomatedTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding { ...@@ -1057,8 +1068,9 @@ class AutomatedTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding {
}) { }) {
assert(additionalTime != null); assert(additionalTime != null);
assert(() { assert(() {
if (_pendingAsyncTasks == null) if (_pendingAsyncTasks == null) {
return true; return true;
}
fail( fail(
'Reentrant call to runAsync() denied.\n' 'Reentrant call to runAsync() denied.\n'
'runAsync() was called, then before its future completed, it ' 'runAsync() was called, then before its future completed, it '
...@@ -1451,8 +1463,9 @@ class LiveTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding { ...@@ -1451,8 +1463,9 @@ class LiveTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding {
/// will select the correct test binding implementation /// will select the correct test binding implementation
/// automatically. /// automatically.
static LiveTestWidgetsFlutterBinding ensureInitialized() { static LiveTestWidgetsFlutterBinding ensureInitialized() {
if (LiveTestWidgetsFlutterBinding._instance == null) if (LiveTestWidgetsFlutterBinding._instance == null) {
LiveTestWidgetsFlutterBinding(); LiveTestWidgetsFlutterBinding();
}
return LiveTestWidgetsFlutterBinding.instance; return LiveTestWidgetsFlutterBinding.instance;
} }
...@@ -1499,15 +1512,19 @@ class LiveTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding { ...@@ -1499,15 +1512,19 @@ class LiveTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding {
@override @override
void scheduleFrame() { void scheduleFrame() {
if (framePolicy == LiveTestWidgetsFlutterBindingFramePolicy.benchmark) if (framePolicy == LiveTestWidgetsFlutterBindingFramePolicy.benchmark) {
return; // In benchmark mode, don't actually schedule any engine frames. // In benchmark mode, don't actually schedule any engine frames.
return;
}
super.scheduleFrame(); super.scheduleFrame();
} }
@override @override
void scheduleForcedFrame() { void scheduleForcedFrame() {
if (framePolicy == LiveTestWidgetsFlutterBindingFramePolicy.benchmark) if (framePolicy == LiveTestWidgetsFlutterBindingFramePolicy.benchmark) {
return; // In benchmark mode, don't actually schedule any engine frames. // In benchmark mode, don't actually schedule any engine frames.
return;
}
super.scheduleForcedFrame(); super.scheduleForcedFrame();
} }
...@@ -1538,8 +1555,9 @@ class LiveTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding { ...@@ -1538,8 +1555,9 @@ class LiveTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding {
@override @override
void handleDrawFrame() { void handleDrawFrame() {
assert(_doDrawThisFrame != null); assert(_doDrawThisFrame != null);
if (_doDrawThisFrame!) if (_doDrawThisFrame!) {
super.handleDrawFrame(); super.handleDrawFrame();
}
_doDrawThisFrame = null; _doDrawThisFrame = null;
_viewNeedsPaint = false; _viewNeedsPaint = false;
_expectingFrameToReassemble = false; _expectingFrameToReassemble = false;
...@@ -1595,8 +1613,9 @@ class LiveTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding { ...@@ -1595,8 +1613,9 @@ class LiveTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding {
final _LiveTestPointerRecord? record = _liveTestRenderView._pointers[event.pointer]; final _LiveTestPointerRecord? record = _liveTestRenderView._pointers[event.pointer];
if (record != null) { if (record != null) {
record.position = event.position; record.position = event.position;
if (!event.down) if (!event.down) {
record.decay = _kPointerDecay; record.decay = _kPointerDecay;
}
_handleViewNeedsPaint(); _handleViewNeedsPaint();
} else if (event.down) { } else if (event.down) {
_liveTestRenderView._pointers[event.pointer] = _LiveTestPointerRecord( _liveTestRenderView._pointers[event.pointer] = _LiveTestPointerRecord(
...@@ -1630,8 +1649,9 @@ class LiveTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding { ...@@ -1630,8 +1649,9 @@ class LiveTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding {
case TestBindingEventSource.device: case TestBindingEventSource.device:
assert(hitTestResult != null || event is PointerAddedEvent || event is PointerRemovedEvent); assert(hitTestResult != null || event is PointerAddedEvent || event is PointerRemovedEvent);
assert(deviceEventDispatcher != null); assert(deviceEventDispatcher != null);
if (hitTestResult != null) if (hitTestResult != null) {
deviceEventDispatcher!.dispatchEvent(event, hitTestResult); deviceEventDispatcher!.dispatchEvent(event, hitTestResult);
}
break; break;
} }
} }
...@@ -1667,8 +1687,9 @@ class LiveTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding { ...@@ -1667,8 +1687,9 @@ class LiveTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding {
Duration additionalTime = const Duration(milliseconds: 1000), Duration additionalTime = const Duration(milliseconds: 1000),
}) async { }) async {
assert(() { assert(() {
if (!_runningAsyncTasks) if (!_runningAsyncTasks) {
return true; return true;
}
fail( fail(
'Reentrant call to runAsync() denied.\n' 'Reentrant call to runAsync() denied.\n'
'runAsync() was called, then before its future completed, it ' 'runAsync() was called, then before its future completed, it '
...@@ -1890,8 +1911,9 @@ class _LiveTestRenderView extends RenderView { ...@@ -1890,8 +1911,9 @@ class _LiveTestRenderView extends RenderView {
final _LiveTestPointerRecord record = _pointers[pointer]!; final _LiveTestPointerRecord record = _pointers[pointer]!;
paint.color = record.color.withOpacity(record.decay < 0 ? (record.decay / (_kPointerDecay - 1)) : 1.0); paint.color = record.color.withOpacity(record.decay < 0 ? (record.decay / (_kPointerDecay - 1)) : 1.0);
canvas.drawPath(path.shift(record.position), paint); canvas.drawPath(path.shift(record.position), paint);
if (record.decay < 0) if (record.decay < 0) {
dirty = true; dirty = true;
}
record.decay += 1; record.decay += 1;
} }
_pointers _pointers
...@@ -1899,8 +1921,9 @@ class _LiveTestRenderView extends RenderView { ...@@ -1899,8 +1921,9 @@ class _LiveTestRenderView extends RenderView {
.where((int pointer) => _pointers[pointer]!.decay == 0) .where((int pointer) => _pointers[pointer]!.decay == 0)
.toList() .toList()
.forEach(_pointers.remove); .forEach(_pointers.remove);
if (dirty && onNeedPaint != null) if (dirty && onNeedPaint != null) {
scheduleMicrotask(onNeedPaint); scheduleMicrotask(onNeedPaint);
}
} }
_label?.paint(context.canvas, offset - const Offset(0.0, 10.0)); _label?.paint(context.canvas, offset - const Offset(0.0, 10.0));
} }
......
...@@ -182,8 +182,9 @@ abstract class WidgetController { ...@@ -182,8 +182,9 @@ abstract class WidgetController {
T _stateOf<T extends State>(Element element, Finder finder) { T _stateOf<T extends State>(Element element, Finder finder) {
TestAsyncUtils.guardSync(); TestAsyncUtils.guardSync();
if (element is StatefulElement) if (element is StatefulElement) {
return element.state as T; return element.state as T;
}
throw StateError('Widget of type ${element.widget.runtimeType}, with ${finder.description}, is not a StatefulWidget.'); throw StateError('Widget of type ${element.widget.runtimeType}, with ${finder.description}, is not a StatefulWidget.');
} }
...@@ -1155,8 +1156,9 @@ abstract class WidgetController { ...@@ -1155,8 +1156,9 @@ abstract class WidgetController {
/// Will throw a [StateError] if the finder returns more than one element or /// Will throw a [StateError] if the finder returns more than one element or
/// if no semantics are found or are not enabled. /// if no semantics are found or are not enabled.
SemanticsNode getSemantics(Finder finder) { SemanticsNode getSemantics(Finder finder) {
if (binding.pipelineOwner.semanticsOwner == null) if (binding.pipelineOwner.semanticsOwner == null) {
throw StateError('Semantics are not enabled.'); throw StateError('Semantics are not enabled.');
}
final Iterable<Element> candidates = finder.evaluate(); final Iterable<Element> candidates = finder.evaluate();
if (candidates.isEmpty) { if (candidates.isEmpty) {
throw StateError('Finder returned no matching elements.'); throw StateError('Finder returned no matching elements.');
...@@ -1171,8 +1173,9 @@ abstract class WidgetController { ...@@ -1171,8 +1173,9 @@ abstract class WidgetController {
renderObject = renderObject.parent as RenderObject?; renderObject = renderObject.parent as RenderObject?;
result = renderObject?.debugSemantics; result = renderObject?.debugSemantics;
} }
if (result == null) if (result == null) {
throw StateError('No Semantics data found.'); throw StateError('No Semantics data found.');
}
return result; return result;
} }
...@@ -1297,8 +1300,9 @@ class LiveWidgetController extends WidgetController { ...@@ -1297,8 +1300,9 @@ class LiveWidgetController extends WidgetController {
@override @override
Future<void> pump([Duration? duration]) async { Future<void> pump([Duration? duration]) async {
if (duration != null) if (duration != null) {
await Future<void>.delayed(duration); await Future<void>.delayed(duration);
}
binding.scheduleFrame(); binding.scheduleFrame();
await binding.endOfFrame; await binding.endOfFrame;
} }
......
...@@ -30,8 +30,9 @@ class _WebKeyLocationPair { ...@@ -30,8 +30,9 @@ class _WebKeyLocationPair {
String? _keyLabel(LogicalKeyboardKey key) { String? _keyLabel(LogicalKeyboardKey key) {
final String keyLabel = key.keyLabel; final String keyLabel = key.keyLabel;
if (keyLabel.length == 1) if (keyLabel.length == 1) {
return keyLabel.toLowerCase(); return keyLabel.toLowerCase();
}
return null; return null;
} }
...@@ -700,8 +701,9 @@ class KeyEventSimulator { ...@@ -700,8 +701,9 @@ class KeyEventSimulator {
final Map<String, PhysicalKeyboardKey> result = <String, PhysicalKeyboardKey>{}; final Map<String, PhysicalKeyboardKey> result = <String, PhysicalKeyboardKey>{};
for (final PhysicalKeyboardKey key in PhysicalKeyboardKey.knownPhysicalKeys) { for (final PhysicalKeyboardKey key in PhysicalKeyboardKey.knownPhysicalKeys) {
final String? debugName = key.debugName; final String? debugName = key.debugName;
if (debugName != null) if (debugName != null) {
result[debugName] = key; result[debugName] = key;
}
} }
return result; return result;
})(); })();
......
...@@ -435,10 +435,11 @@ class CommonFinders { ...@@ -435,10 +435,11 @@ class CommonFinders {
/// If the `skipOffstage` argument is true (the default), then this skips /// If the `skipOffstage` argument is true (the default), then this skips
/// nodes that are [Offstage] or that are from inactive [Route]s. /// nodes that are [Offstage] or that are from inactive [Route]s.
Finder bySemanticsLabel(Pattern label, { bool skipOffstage = true }) { Finder bySemanticsLabel(Pattern label, { bool skipOffstage = true }) {
if (WidgetsBinding.instance.pipelineOwner.semanticsOwner == null) if (WidgetsBinding.instance.pipelineOwner.semanticsOwner == null) {
throw StateError('Semantics are not enabled. ' throw StateError('Semantics are not enabled. '
'Make sure to call tester.ensureSemantics() before using ' 'Make sure to call tester.ensureSemantics() before using '
'this finder, and call dispose on its return value after.'); 'this finder, and call dispose on its return value after.');
}
return byElementPredicate( return byElementPredicate(
(Element element) { (Element element) {
// Multiple elements can have the same renderObject - we want the "owner" // Multiple elements can have the same renderObject - we want the "owner"
...@@ -550,12 +551,15 @@ abstract class Finder { ...@@ -550,12 +551,15 @@ abstract class Finder {
final String additional = skipOffstage ? ' (ignoring offstage widgets)' : ''; final String additional = skipOffstage ? ' (ignoring offstage widgets)' : '';
final List<Element> widgets = evaluate().toList(); final List<Element> widgets = evaluate().toList();
final int count = widgets.length; final int count = widgets.length;
if (count == 0) if (count == 0) {
return 'zero widgets with $description$additional'; return 'zero widgets with $description$additional';
if (count == 1) }
if (count == 1) {
return 'exactly one widget with $description$additional: ${widgets.single}'; return 'exactly one widget with $description$additional: ${widgets.single}';
if (count < 4) }
if (count < 4) {
return '$count widgets with $description$additional: $widgets'; return '$count widgets with $description$additional: $widgets';
}
return '$count widgets with $description$additional: ${widgets[0]}, ${widgets[1]}, ${widgets[2]}, ...'; return '$count widgets with $description$additional: ${widgets[0]}, ${widgets[1]}, ${widgets[2]}, ...';
} }
} }
...@@ -911,8 +915,9 @@ class _DescendantFinder extends Finder { ...@@ -911,8 +915,9 @@ class _DescendantFinder extends Finder {
@override @override
String get description { String get description {
if (matchRoot) if (matchRoot) {
return '${descendant.description} in the subtree(s) beginning with ${ancestor.description}'; return '${descendant.description} in the subtree(s) beginning with ${ancestor.description}';
}
return '${descendant.description} that has ancestor(s) with ${ancestor.description}'; return '${descendant.description} that has ancestor(s) with ${ancestor.description}';
} }
...@@ -927,8 +932,9 @@ class _DescendantFinder extends Finder { ...@@ -927,8 +932,9 @@ class _DescendantFinder extends Finder {
final List<Element> candidates = ancestorElements.expand<Element>( final List<Element> candidates = ancestorElements.expand<Element>(
(Element element) => collectAllElementsFrom(element, skipOffstage: skipOffstage) (Element element) => collectAllElementsFrom(element, skipOffstage: skipOffstage)
).toSet().toList(); ).toSet().toList();
if (matchRoot) if (matchRoot) {
candidates.insertAll(0, ancestorElements); candidates.insertAll(0, ancestorElements);
}
return candidates; return candidates;
} }
} }
...@@ -942,8 +948,9 @@ class _AncestorFinder extends Finder { ...@@ -942,8 +948,9 @@ class _AncestorFinder extends Finder {
@override @override
String get description { String get description {
if (matchRoot) if (matchRoot) {
return 'ancestor ${ancestor.description} beginning with ${descendant.description}'; return 'ancestor ${ancestor.description} beginning with ${descendant.description}';
}
return '${ancestor.description} which is an ancestor of ${descendant.description}'; return '${ancestor.description} which is an ancestor of ${descendant.description}';
} }
...@@ -957,8 +964,9 @@ class _AncestorFinder extends Finder { ...@@ -957,8 +964,9 @@ class _AncestorFinder extends Finder {
final List<Element> candidates = <Element>[]; final List<Element> candidates = <Element>[];
for (final Element root in descendant.evaluate()) { for (final Element root in descendant.evaluate()) {
final List<Element> ancestors = <Element>[]; final List<Element> ancestors = <Element>[];
if (matchRoot) if (matchRoot) {
ancestors.add(root); ancestors.add(root);
}
root.visitAncestorElements((Element element) { root.visitAncestorElements((Element element) {
ancestors.add(element); ancestors.add(element);
return true; return true;
......
...@@ -86,8 +86,9 @@ abstract class GoldenFileComparator { ...@@ -86,8 +86,9 @@ abstract class GoldenFileComparator {
/// Version numbers are used in golden file tests for package:flutter. You can /// Version numbers are used in golden file tests for package:flutter. You can
/// learn more about these tests [here](https://github.com/flutter/flutter/wiki/Writing-a-golden-file-test-for-package:flutter). /// learn more about these tests [here](https://github.com/flutter/flutter/wiki/Writing-a-golden-file-test-for-package:flutter).
Uri getTestUri(Uri key, int? version) { Uri getTestUri(Uri key, int? version) {
if (version == null) if (version == null) {
return key; return key;
}
final String keyString = key.toString(); final String keyString = key.toString();
final String extension = path.extension(keyString); final String extension = path.extension(keyString);
return Uri.parse('${keyString.split(extension).join()}.$version$extension'); return Uri.parse('${keyString.split(extension).join()}.$version$extension');
...@@ -193,8 +194,9 @@ abstract class WebGoldenComparator { ...@@ -193,8 +194,9 @@ abstract class WebGoldenComparator {
/// Version numbers are used in golden file tests for package:flutter. You can /// Version numbers are used in golden file tests for package:flutter. You can
/// learn more about these tests [here](https://github.com/flutter/flutter/wiki/Writing-a-golden-file-test-for-package:flutter). /// learn more about these tests [here](https://github.com/flutter/flutter/wiki/Writing-a-golden-file-test-for-package:flutter).
Uri getTestUri(Uri key, int? version) { Uri getTestUri(Uri key, int? version) {
if (version == null) if (version == null) {
return key; return key;
}
final String keyString = key.toString(); final String keyString = key.toString();
final String extension = path.extension(keyString); final String extension = path.extension(keyString);
return Uri.parse('${keyString.split(extension).join()}.$version$extension'); return Uri.parse('${keyString.split(extension).join()}.$version$extension');
......
...@@ -632,11 +632,12 @@ Matcher matchesSemantics({ ...@@ -632,11 +632,12 @@ Matcher matchesSemantics({
if (hasSetTextAction) SemanticsAction.setText, if (hasSetTextAction) SemanticsAction.setText,
]; ];
SemanticsHintOverrides? hintOverrides; SemanticsHintOverrides? hintOverrides;
if (onTapHint != null || onLongPressHint != null) if (onTapHint != null || onLongPressHint != null) {
hintOverrides = SemanticsHintOverrides( hintOverrides = SemanticsHintOverrides(
onTapHint: onTapHint, onTapHint: onTapHint,
onLongPressHint: onLongPressHint, onLongPressHint: onLongPressHint,
); );
}
return _MatchesSemanticsData( return _MatchesSemanticsData(
label: label, label: label,
...@@ -712,16 +713,20 @@ class _FindsWidgetMatcher extends Matcher { ...@@ -712,16 +713,20 @@ class _FindsWidgetMatcher extends Matcher {
int count = 0; int count = 0;
final Iterator<Element> iterator = finder.evaluate().iterator; final Iterator<Element> iterator = finder.evaluate().iterator;
if (min != null) { if (min != null) {
while (count < min! && iterator.moveNext()) while (count < min! && iterator.moveNext()) {
count += 1; count += 1;
if (count < min!) }
if (count < min!) {
return false; return false;
}
} }
if (max != null) { if (max != null) {
while (count <= max! && iterator.moveNext()) while (count <= max! && iterator.moveNext()) {
count += 1; count += 1;
if (count > max!) }
if (count > max!) {
return false; return false;
}
} }
return true; return true;
} }
...@@ -730,20 +735,24 @@ class _FindsWidgetMatcher extends Matcher { ...@@ -730,20 +735,24 @@ class _FindsWidgetMatcher extends Matcher {
Description describe(Description description) { Description describe(Description description) {
assert(min != null || max != null); assert(min != null || max != null);
if (min == max) { if (min == max) {
if (min == 1) if (min == 1) {
return description.add('exactly one matching node in the widget tree'); return description.add('exactly one matching node in the widget tree');
}
return description.add('exactly $min matching nodes in the widget tree'); return description.add('exactly $min matching nodes in the widget tree');
} }
if (min == null) { if (min == null) {
if (max == 0) if (max == 0) {
return description.add('no matching nodes in the widget tree'); return description.add('no matching nodes in the widget tree');
if (max == 1) }
if (max == 1) {
return description.add('at most one matching node in the widget tree'); return description.add('at most one matching node in the widget tree');
}
return description.add('at most $max matching nodes in the widget tree'); return description.add('at most $max matching nodes in the widget tree');
} }
if (max == null) { if (max == null) {
if (min == 1) if (min == 1) {
return description.add('at least one matching node in the widget tree'); return description.add('at least one matching node in the widget tree');
}
return description.add('at least $min matching nodes in the widget tree'); return description.add('at least $min matching nodes in the widget tree');
} }
return description.add('between $min and $max matching nodes in the widget tree (inclusive)'); return description.add('between $min and $max matching nodes in the widget tree (inclusive)');
...@@ -760,17 +769,20 @@ class _FindsWidgetMatcher extends Matcher { ...@@ -760,17 +769,20 @@ class _FindsWidgetMatcher extends Matcher {
final int count = finder.evaluate().length; final int count = finder.evaluate().length;
if (count == 0) { if (count == 0) {
assert(min != null && min! > 0); assert(min != null && min! > 0);
if (min == 1 && max == 1) if (min == 1 && max == 1) {
return mismatchDescription.add('means none were found but one was expected'); return mismatchDescription.add('means none were found but one was expected');
}
return mismatchDescription.add('means none were found but some were expected'); return mismatchDescription.add('means none were found but some were expected');
} }
if (max == 0) { if (max == 0) {
if (count == 1) if (count == 1) {
return mismatchDescription.add('means one was found but none were expected'); return mismatchDescription.add('means one was found but none were expected');
}
return mismatchDescription.add('means some were found but none were expected'); return mismatchDescription.add('means some were found but none were expected');
} }
if (min != null && count < min!) if (min != null && count < min!) {
return mismatchDescription.add('is not enough'); return mismatchDescription.add('is not enough');
}
assert(max != null && count > min!); assert(max != null && count > min!);
return mismatchDescription.add('is too many'); return mismatchDescription.add('is too many');
} }
...@@ -778,8 +790,9 @@ class _FindsWidgetMatcher extends Matcher { ...@@ -778,8 +790,9 @@ class _FindsWidgetMatcher extends Matcher {
bool _hasAncestorMatching(Finder finder, bool Function(Widget widget) predicate) { bool _hasAncestorMatching(Finder finder, bool Function(Widget widget) predicate) {
final Iterable<Element> nodes = finder.evaluate(); final Iterable<Element> nodes = finder.evaluate();
if (nodes.length != 1) if (nodes.length != 1) {
return false; return false;
}
bool result = false; bool result = false;
nodes.single.visitAncestorElements((Element ancestor) { nodes.single.visitAncestorElements((Element ancestor) {
if (predicate(ancestor.widget)) { if (predicate(ancestor.widget)) {
...@@ -801,8 +814,9 @@ class _IsOffstage extends Matcher { ...@@ -801,8 +814,9 @@ class _IsOffstage extends Matcher {
@override @override
bool matches(covariant Finder finder, Map<dynamic, dynamic> matchState) { bool matches(covariant Finder finder, Map<dynamic, dynamic> matchState) {
return _hasAncestorMatching(finder, (Widget widget) { return _hasAncestorMatching(finder, (Widget widget) {
if (widget is Offstage) if (widget is Offstage) {
return widget.offstage; return widget.offstage;
}
return false; return false;
}); });
} }
...@@ -817,8 +831,9 @@ class _IsOnstage extends Matcher { ...@@ -817,8 +831,9 @@ class _IsOnstage extends Matcher {
@override @override
bool matches(covariant Finder finder, Map<dynamic, dynamic> matchState) { bool matches(covariant Finder finder, Map<dynamic, dynamic> matchState) {
final Iterable<Element> nodes = finder.evaluate(); final Iterable<Element> nodes = finder.evaluate();
if (nodes.length != 1) if (nodes.length != 1) {
return false; return false;
}
bool result = true; bool result = true;
nodes.single.visitAncestorElements((Element ancestor) { nodes.single.visitAncestorElements((Element ancestor) {
final Widget widget = ancestor.widget; final Widget widget = ancestor.widget;
...@@ -940,8 +955,9 @@ bool _isVerticalLine(int c) { ...@@ -940,8 +955,9 @@ bool _isVerticalLine(int c) {
bool _isAllTreeConnectorCharacters(String line) { bool _isAllTreeConnectorCharacters(String line) {
for (int i = 0; i < line.length; ++i) { for (int i = 0; i < line.length; ++i) {
final int c = line.codeUnitAt(i); final int c = line.codeUnitAt(i);
if (!_isWhitespace(c) && !_isVerticalLine(c)) if (!_isWhitespace(c) && !_isVerticalLine(c)) {
return false; return false;
}
} }
return true; return true;
} }
...@@ -963,27 +979,33 @@ class _HasGoodToStringDeep extends Matcher { ...@@ -963,27 +979,33 @@ class _HasGoodToStringDeep extends Matcher {
issues.add('Not terminated with a line break.'); issues.add('Not terminated with a line break.');
} }
if (description.trim() != description) if (description.trim() != description) {
issues.add('Has trailing whitespace.'); issues.add('Has trailing whitespace.');
}
final List<String> lines = description.split('\n'); final List<String> lines = description.split('\n');
if (lines.length < 2) if (lines.length < 2) {
issues.add('Does not have multiple lines.'); issues.add('Does not have multiple lines.');
}
if (description.contains('Instance of ')) if (description.contains('Instance of ')) {
issues.add('Contains text "Instance of ".'); issues.add('Contains text "Instance of ".');
}
for (int i = 0; i < lines.length; ++i) { for (int i = 0; i < lines.length; ++i) {
final String line = lines[i]; final String line = lines[i];
if (line.isEmpty) if (line.isEmpty) {
issues.add('Line ${i+1} is empty.'); issues.add('Line ${i+1} is empty.');
}
if (line.trimRight() != line) if (line.trimRight() != line) {
issues.add('Line ${i+1} has trailing whitespace.'); issues.add('Line ${i+1} has trailing whitespace.');
}
} }
if (_isAllTreeConnectorCharacters(lines.last)) if (_isAllTreeConnectorCharacters(lines.last)) {
issues.add('Last line is all tree connector characters.'); issues.add('Last line is all tree connector characters.');
}
// If a toStringDeep method doesn't properly handle nested values that // If a toStringDeep method doesn't properly handle nested values that
// contain line breaks it can fail to add the required prefixes to all // contain line breaks it can fail to add the required prefixes to all
...@@ -1000,12 +1022,14 @@ class _HasGoodToStringDeep extends Matcher { ...@@ -1000,12 +1022,14 @@ class _HasGoodToStringDeep extends Matcher {
0, descriptionWithPrefixes.length - 1); 0, descriptionWithPrefixes.length - 1);
} }
final List<String> linesWithPrefixes = descriptionWithPrefixes.split('\n'); final List<String> linesWithPrefixes = descriptionWithPrefixes.split('\n');
if (!linesWithPrefixes.first.startsWith(prefixLineOne)) if (!linesWithPrefixes.first.startsWith(prefixLineOne)) {
prefixIssues.add('First line does not contain expected prefix.'); prefixIssues.add('First line does not contain expected prefix.');
}
for (int i = 1; i < linesWithPrefixes.length; ++i) { for (int i = 1; i < linesWithPrefixes.length; ++i) {
if (!linesWithPrefixes[i].startsWith(prefixOtherLines)) if (!linesWithPrefixes[i].startsWith(prefixOtherLines)) {
prefixIssues.add('Line ${i+1} does not contain the expected prefix.'); prefixIssues.add('Line ${i+1} does not contain the expected prefix.');
}
} }
final StringBuffer errorDescription = StringBuffer(); final StringBuffer errorDescription = StringBuffer();
...@@ -1180,10 +1204,12 @@ class _IsWithinDistance<T> extends Matcher { ...@@ -1180,10 +1204,12 @@ class _IsWithinDistance<T> extends Matcher {
@override @override
bool matches(dynamic object, Map<dynamic, dynamic> matchState) { bool matches(dynamic object, Map<dynamic, dynamic> matchState) {
if (object is! T) if (object is! T) {
return false; return false;
if (object == value) }
if (object == value) {
return true; return true;
}
final num distance = distanceFunction(object, value); final num distance = distanceFunction(object, value);
if (distance < 0) { if (distance < 0) {
throw ArgumentError( throw ArgumentError(
...@@ -1220,10 +1246,12 @@ class _MoreOrLessEquals extends Matcher { ...@@ -1220,10 +1246,12 @@ class _MoreOrLessEquals extends Matcher {
@override @override
bool matches(dynamic object, Map<dynamic, dynamic> matchState) { bool matches(dynamic object, Map<dynamic, dynamic> matchState) {
if (object is! double) if (object is! double) {
return false; return false;
if (object == value) }
if (object == value) {
return true; return true;
}
return (object - value).abs() <= epsilon; return (object - value).abs() <= epsilon;
} }
...@@ -1245,39 +1273,48 @@ class _IsMethodCall extends Matcher { ...@@ -1245,39 +1273,48 @@ class _IsMethodCall extends Matcher {
@override @override
bool matches(dynamic item, Map<dynamic, dynamic> matchState) { bool matches(dynamic item, Map<dynamic, dynamic> matchState) {
if (item is! MethodCall) if (item is! MethodCall) {
return false; return false;
if (item.method != name) }
if (item.method != name) {
return false; return false;
}
return _deepEquals(item.arguments, arguments); return _deepEquals(item.arguments, arguments);
} }
bool _deepEquals(dynamic a, dynamic b) { bool _deepEquals(dynamic a, dynamic b) {
if (a == b) if (a == b) {
return true; return true;
if (a is List) }
if (a is List) {
return b is List && _deepEqualsList(a, b); return b is List && _deepEqualsList(a, b);
if (a is Map) }
if (a is Map) {
return b is Map && _deepEqualsMap(a, b); return b is Map && _deepEqualsMap(a, b);
}
return false; return false;
} }
bool _deepEqualsList(List<dynamic> a, List<dynamic> b) { bool _deepEqualsList(List<dynamic> a, List<dynamic> b) {
if (a.length != b.length) if (a.length != b.length) {
return false; return false;
}
for (int i = 0; i < a.length; i++) { for (int i = 0; i < a.length; i++) {
if (!_deepEquals(a[i], b[i])) if (!_deepEquals(a[i], b[i])) {
return false; return false;
}
} }
return true; return true;
} }
bool _deepEqualsMap(Map<dynamic, dynamic> a, Map<dynamic, dynamic> b) { bool _deepEqualsMap(Map<dynamic, dynamic> a, Map<dynamic, dynamic> b) {
if (a.length != b.length) if (a.length != b.length) {
return false; return false;
}
for (final dynamic key in a.keys) { for (final dynamic key in a.keys) {
if (!b.containsKey(key) || !_deepEquals(a[key], b[key])) if (!b.containsKey(key) || !_deepEquals(a[key], b[key])) {
return false; return false;
}
} }
return true; return true;
} }
...@@ -1383,8 +1420,9 @@ class _MatchAnythingExceptClip extends _FailWithDescriptionMatcher { ...@@ -1383,8 +1420,9 @@ class _MatchAnythingExceptClip extends _FailWithDescriptionMatcher {
@override @override
bool matches(covariant Finder finder, Map<dynamic, dynamic> matchState) { bool matches(covariant Finder finder, Map<dynamic, dynamic> matchState) {
final Iterable<Element> nodes = finder.evaluate(); final Iterable<Element> nodes = finder.evaluate();
if (nodes.length != 1) if (nodes.length != 1) {
return failWithDescription(matchState, 'did not have a exactly one child element'); return failWithDescription(matchState, 'did not have a exactly one child element');
}
final RenderObject renderObject = nodes.single.renderObject!; final RenderObject renderObject = nodes.single.renderObject!;
switch (renderObject.runtimeType) { switch (renderObject.runtimeType) {
...@@ -1413,15 +1451,18 @@ abstract class _MatchRenderObject<M extends RenderObject, T extends RenderObject ...@@ -1413,15 +1451,18 @@ abstract class _MatchRenderObject<M extends RenderObject, T extends RenderObject
@override @override
bool matches(covariant Finder finder, Map<dynamic, dynamic> matchState) { bool matches(covariant Finder finder, Map<dynamic, dynamic> matchState) {
final Iterable<Element> nodes = finder.evaluate(); final Iterable<Element> nodes = finder.evaluate();
if (nodes.length != 1) if (nodes.length != 1) {
return failWithDescription(matchState, 'did not have a exactly one child element'); return failWithDescription(matchState, 'did not have a exactly one child element');
}
final RenderObject renderObject = nodes.single.renderObject!; final RenderObject renderObject = nodes.single.renderObject!;
if (renderObject.runtimeType == T) if (renderObject.runtimeType == T) {
return renderObjectMatchesT(matchState, renderObject as T); return renderObjectMatchesT(matchState, renderObject as T);
}
if (renderObject.runtimeType == M) if (renderObject.runtimeType == M) {
return renderObjectMatchesM(matchState, renderObject as M); return renderObjectMatchesM(matchState, renderObject as M);
}
return failWithDescription(matchState, 'had a root render object of type: ${renderObject.runtimeType}'); return failWithDescription(matchState, 'had a root render object of type: ${renderObject.runtimeType}');
} }
...@@ -1440,26 +1481,31 @@ class _RendersOnPhysicalModel extends _MatchRenderObject<RenderPhysicalShape, Re ...@@ -1440,26 +1481,31 @@ class _RendersOnPhysicalModel extends _MatchRenderObject<RenderPhysicalShape, Re
@override @override
bool renderObjectMatchesT(Map<dynamic, dynamic> matchState, RenderPhysicalModel renderObject) { bool renderObjectMatchesT(Map<dynamic, dynamic> matchState, RenderPhysicalModel renderObject) {
if (shape != null && renderObject.shape != shape) if (shape != null && renderObject.shape != shape) {
return failWithDescription(matchState, 'had shape: ${renderObject.shape}'); return failWithDescription(matchState, 'had shape: ${renderObject.shape}');
}
if (borderRadius != null && renderObject.borderRadius != borderRadius) if (borderRadius != null && renderObject.borderRadius != borderRadius) {
return failWithDescription(matchState, 'had borderRadius: ${renderObject.borderRadius}'); return failWithDescription(matchState, 'had borderRadius: ${renderObject.borderRadius}');
}
if (elevation != null && renderObject.elevation != elevation) if (elevation != null && renderObject.elevation != elevation) {
return failWithDescription(matchState, 'had elevation: ${renderObject.elevation}'); return failWithDescription(matchState, 'had elevation: ${renderObject.elevation}');
}
return true; return true;
} }
@override @override
bool renderObjectMatchesM(Map<dynamic, dynamic> matchState, RenderPhysicalShape renderObject) { bool renderObjectMatchesM(Map<dynamic, dynamic> matchState, RenderPhysicalShape renderObject) {
if (renderObject.clipper.runtimeType != ShapeBorderClipper) if (renderObject.clipper.runtimeType != ShapeBorderClipper) {
return failWithDescription(matchState, 'clipper was: ${renderObject.clipper}'); return failWithDescription(matchState, 'clipper was: ${renderObject.clipper}');
}
final ShapeBorderClipper shapeClipper = renderObject.clipper! as ShapeBorderClipper; final ShapeBorderClipper shapeClipper = renderObject.clipper! as ShapeBorderClipper;
if (borderRadius != null && !assertRoundedRectangle(shapeClipper, borderRadius!, matchState)) if (borderRadius != null && !assertRoundedRectangle(shapeClipper, borderRadius!, matchState)) {
return false; return false;
}
if ( if (
borderRadius == null && borderRadius == null &&
...@@ -1477,36 +1523,43 @@ class _RendersOnPhysicalModel extends _MatchRenderObject<RenderPhysicalShape, Re ...@@ -1477,36 +1523,43 @@ class _RendersOnPhysicalModel extends _MatchRenderObject<RenderPhysicalShape, Re
return false; return false;
} }
if (elevation != null && renderObject.elevation != elevation) if (elevation != null && renderObject.elevation != elevation) {
return failWithDescription(matchState, 'had elevation: ${renderObject.elevation}'); return failWithDescription(matchState, 'had elevation: ${renderObject.elevation}');
}
return true; return true;
} }
bool assertRoundedRectangle(ShapeBorderClipper shapeClipper, BorderRadius borderRadius, Map<dynamic, dynamic> matchState) { bool assertRoundedRectangle(ShapeBorderClipper shapeClipper, BorderRadius borderRadius, Map<dynamic, dynamic> matchState) {
if (shapeClipper.shape.runtimeType != RoundedRectangleBorder) if (shapeClipper.shape.runtimeType != RoundedRectangleBorder) {
return failWithDescription(matchState, 'had shape border: ${shapeClipper.shape}'); return failWithDescription(matchState, 'had shape border: ${shapeClipper.shape}');
}
final RoundedRectangleBorder border = shapeClipper.shape as RoundedRectangleBorder; final RoundedRectangleBorder border = shapeClipper.shape as RoundedRectangleBorder;
if (border.borderRadius != borderRadius) if (border.borderRadius != borderRadius) {
return failWithDescription(matchState, 'had borderRadius: ${border.borderRadius}'); return failWithDescription(matchState, 'had borderRadius: ${border.borderRadius}');
}
return true; return true;
} }
bool assertCircle(ShapeBorderClipper shapeClipper, Map<dynamic, dynamic> matchState) { bool assertCircle(ShapeBorderClipper shapeClipper, Map<dynamic, dynamic> matchState) {
if (shapeClipper.shape.runtimeType != CircleBorder) if (shapeClipper.shape.runtimeType != CircleBorder) {
return failWithDescription(matchState, 'had shape border: ${shapeClipper.shape}'); return failWithDescription(matchState, 'had shape border: ${shapeClipper.shape}');
}
return true; return true;
} }
@override @override
Description describe(Description description) { Description describe(Description description) {
description.add('renders on a physical model'); description.add('renders on a physical model');
if (shape != null) if (shape != null) {
description.add(' with shape $shape'); description.add(' with shape $shape');
if (borderRadius != null) }
if (borderRadius != null) {
description.add(' with borderRadius $borderRadius'); description.add(' with borderRadius $borderRadius');
if (elevation != null) }
if (elevation != null) {
description.add(' with elevation $elevation'); description.add(' with elevation $elevation');
}
return description; return description;
} }
} }
...@@ -1522,15 +1575,18 @@ class _RendersOnPhysicalShape extends _MatchRenderObject<RenderPhysicalShape, Re ...@@ -1522,15 +1575,18 @@ class _RendersOnPhysicalShape extends _MatchRenderObject<RenderPhysicalShape, Re
@override @override
bool renderObjectMatchesM(Map<dynamic, dynamic> matchState, RenderPhysicalShape renderObject) { bool renderObjectMatchesM(Map<dynamic, dynamic> matchState, RenderPhysicalShape renderObject) {
if (renderObject.clipper.runtimeType != ShapeBorderClipper) if (renderObject.clipper.runtimeType != ShapeBorderClipper) {
return failWithDescription(matchState, 'clipper was: ${renderObject.clipper}'); return failWithDescription(matchState, 'clipper was: ${renderObject.clipper}');
}
final ShapeBorderClipper shapeClipper = renderObject.clipper! as ShapeBorderClipper; final ShapeBorderClipper shapeClipper = renderObject.clipper! as ShapeBorderClipper;
if (shapeClipper.shape != shape) if (shapeClipper.shape != shape) {
return failWithDescription(matchState, 'shape was: ${shapeClipper.shape}'); return failWithDescription(matchState, 'shape was: ${shapeClipper.shape}');
}
if (elevation != null && renderObject.elevation != elevation) if (elevation != null && renderObject.elevation != elevation) {
return failWithDescription(matchState, 'had elevation: ${renderObject.elevation}'); return failWithDescription(matchState, 'had elevation: ${renderObject.elevation}');
}
return true; return true;
} }
...@@ -1543,8 +1599,9 @@ class _RendersOnPhysicalShape extends _MatchRenderObject<RenderPhysicalShape, Re ...@@ -1543,8 +1599,9 @@ class _RendersOnPhysicalShape extends _MatchRenderObject<RenderPhysicalShape, Re
@override @override
Description describe(Description description) { Description describe(Description description) {
description.add('renders on a physical model with shape $shape'); description.add('renders on a physical model with shape $shape');
if (elevation != null) if (elevation != null) {
description.add(' with elevation $elevation'); description.add(' with elevation $elevation');
}
return description; return description;
} }
} }
...@@ -1554,21 +1611,25 @@ class _ClipsWithBoundingRect extends _MatchRenderObject<RenderClipPath, RenderCl ...@@ -1554,21 +1611,25 @@ class _ClipsWithBoundingRect extends _MatchRenderObject<RenderClipPath, RenderCl
@override @override
bool renderObjectMatchesT(Map<dynamic, dynamic> matchState, RenderClipRect renderObject) { bool renderObjectMatchesT(Map<dynamic, dynamic> matchState, RenderClipRect renderObject) {
if (renderObject.clipper != null) if (renderObject.clipper != null) {
return failWithDescription(matchState, 'had a non null clipper ${renderObject.clipper}'); return failWithDescription(matchState, 'had a non null clipper ${renderObject.clipper}');
}
return true; return true;
} }
@override @override
bool renderObjectMatchesM(Map<dynamic, dynamic> matchState, RenderClipPath renderObject) { bool renderObjectMatchesM(Map<dynamic, dynamic> matchState, RenderClipPath renderObject) {
if (renderObject.clipper.runtimeType != ShapeBorderClipper) if (renderObject.clipper.runtimeType != ShapeBorderClipper) {
return failWithDescription(matchState, 'clipper was: ${renderObject.clipper}'); return failWithDescription(matchState, 'clipper was: ${renderObject.clipper}');
}
final ShapeBorderClipper shapeClipper = renderObject.clipper! as ShapeBorderClipper; final ShapeBorderClipper shapeClipper = renderObject.clipper! as ShapeBorderClipper;
if (shapeClipper.shape.runtimeType != RoundedRectangleBorder) if (shapeClipper.shape.runtimeType != RoundedRectangleBorder) {
return failWithDescription(matchState, 'shape was: ${shapeClipper.shape}'); return failWithDescription(matchState, 'shape was: ${shapeClipper.shape}');
}
final RoundedRectangleBorder border = shapeClipper.shape as RoundedRectangleBorder; final RoundedRectangleBorder border = shapeClipper.shape as RoundedRectangleBorder;
if (border.borderRadius != BorderRadius.zero) if (border.borderRadius != BorderRadius.zero) {
return failWithDescription(matchState, 'borderRadius was: ${border.borderRadius}'); return failWithDescription(matchState, 'borderRadius was: ${border.borderRadius}');
}
return true; return true;
} }
...@@ -1585,25 +1646,30 @@ class _ClipsWithBoundingRRect extends _MatchRenderObject<RenderClipPath, RenderC ...@@ -1585,25 +1646,30 @@ class _ClipsWithBoundingRRect extends _MatchRenderObject<RenderClipPath, RenderC
@override @override
bool renderObjectMatchesT(Map<dynamic, dynamic> matchState, RenderClipRRect renderObject) { bool renderObjectMatchesT(Map<dynamic, dynamic> matchState, RenderClipRRect renderObject) {
if (renderObject.clipper != null) if (renderObject.clipper != null) {
return failWithDescription(matchState, 'had a non null clipper ${renderObject.clipper}'); return failWithDescription(matchState, 'had a non null clipper ${renderObject.clipper}');
}
if (renderObject.borderRadius != borderRadius) if (renderObject.borderRadius != borderRadius) {
return failWithDescription(matchState, 'had borderRadius: ${renderObject.borderRadius}'); return failWithDescription(matchState, 'had borderRadius: ${renderObject.borderRadius}');
}
return true; return true;
} }
@override @override
bool renderObjectMatchesM(Map<dynamic, dynamic> matchState, RenderClipPath renderObject) { bool renderObjectMatchesM(Map<dynamic, dynamic> matchState, RenderClipPath renderObject) {
if (renderObject.clipper.runtimeType != ShapeBorderClipper) if (renderObject.clipper.runtimeType != ShapeBorderClipper) {
return failWithDescription(matchState, 'clipper was: ${renderObject.clipper}'); return failWithDescription(matchState, 'clipper was: ${renderObject.clipper}');
}
final ShapeBorderClipper shapeClipper = renderObject.clipper! as ShapeBorderClipper; final ShapeBorderClipper shapeClipper = renderObject.clipper! as ShapeBorderClipper;
if (shapeClipper.shape.runtimeType != RoundedRectangleBorder) if (shapeClipper.shape.runtimeType != RoundedRectangleBorder) {
return failWithDescription(matchState, 'shape was: ${shapeClipper.shape}'); return failWithDescription(matchState, 'shape was: ${shapeClipper.shape}');
}
final RoundedRectangleBorder border = shapeClipper.shape as RoundedRectangleBorder; final RoundedRectangleBorder border = shapeClipper.shape as RoundedRectangleBorder;
if (border.borderRadius != borderRadius) if (border.borderRadius != borderRadius) {
return failWithDescription(matchState, 'had borderRadius: ${border.borderRadius}'); return failWithDescription(matchState, 'had borderRadius: ${border.borderRadius}');
}
return true; return true;
} }
...@@ -1619,11 +1685,13 @@ class _ClipsWithShapeBorder extends _MatchRenderObject<RenderClipPath, RenderCli ...@@ -1619,11 +1685,13 @@ class _ClipsWithShapeBorder extends _MatchRenderObject<RenderClipPath, RenderCli
@override @override
bool renderObjectMatchesM(Map<dynamic, dynamic> matchState, RenderClipPath renderObject) { bool renderObjectMatchesM(Map<dynamic, dynamic> matchState, RenderClipPath renderObject) {
if (renderObject.clipper.runtimeType != ShapeBorderClipper) if (renderObject.clipper.runtimeType != ShapeBorderClipper) {
return failWithDescription(matchState, 'clipper was: ${renderObject.clipper}'); return failWithDescription(matchState, 'clipper was: ${renderObject.clipper}');
}
final ShapeBorderClipper shapeClipper = renderObject.clipper! as ShapeBorderClipper; final ShapeBorderClipper shapeClipper = renderObject.clipper! as ShapeBorderClipper;
if (shapeClipper.shape != shape) if (shapeClipper.shape != shape) {
return failWithDescription(matchState, 'shape was: ${shapeClipper.shape}'); return failWithDescription(matchState, 'shape was: ${shapeClipper.shape}');
}
return true; return true;
} }
...@@ -1665,29 +1733,33 @@ class _CoversSameAreaAs extends Matcher { ...@@ -1665,29 +1733,33 @@ class _CoversSameAreaAs extends Matcher {
j * (areaToCompare.height / sampleSize), j * (areaToCompare.height / sampleSize),
); );
if (!_samplePoint(matchState, actualPath, offset)) if (!_samplePoint(matchState, actualPath, offset)) {
return false; return false;
}
final Offset noise = Offset( final Offset noise = Offset(
maxHorizontalNoise * random.nextDouble(), maxHorizontalNoise * random.nextDouble(),
maxVerticalNoise * random.nextDouble(), maxVerticalNoise * random.nextDouble(),
); );
if (!_samplePoint(matchState, actualPath, offset + noise)) if (!_samplePoint(matchState, actualPath, offset + noise)) {
return false; return false;
}
} }
} }
return true; return true;
} }
bool _samplePoint(Map<dynamic, dynamic> matchState, Path actualPath, Offset offset) { bool _samplePoint(Map<dynamic, dynamic> matchState, Path actualPath, Offset offset) {
if (expectedPath.contains(offset) == actualPath.contains(offset)) if (expectedPath.contains(offset) == actualPath.contains(offset)) {
return true; return true;
}
if (actualPath.contains(offset)) if (actualPath.contains(offset)) {
return failWithDescription(matchState, '$offset is contained in the actual path but not in the expected path'); return failWithDescription(matchState, '$offset is contained in the actual path but not in the expected path');
else } else {
return failWithDescription(matchState, '$offset is contained in the expected path but not in the actual path'); return failWithDescription(matchState, '$offset is contained in the expected path but not in the actual path');
}
} }
bool failWithDescription(Map<dynamic, dynamic> matchState, String description) { bool failWithDescription(Map<dynamic, dynamic> matchState, String description) {
...@@ -1719,8 +1791,9 @@ class _ColorMatcher extends Matcher { ...@@ -1719,8 +1791,9 @@ class _ColorMatcher extends Matcher {
@override @override
bool matches(dynamic item, Map<dynamic, dynamic> matchState) { bool matches(dynamic item, Map<dynamic, dynamic> matchState) {
if (item is Color) if (item is Color) {
return item == targetColor || item.value == targetColor.value; return item == targetColor || item.value == targetColor.value;
}
return false; return false;
} }
...@@ -1769,15 +1842,18 @@ class _MatchesReferenceImage extends AsyncMatcher { ...@@ -1769,15 +1842,18 @@ class _MatchesReferenceImage extends AsyncMatcher {
return binding.runAsync<String?>(() async { return binding.runAsync<String?>(() async {
final ui.Image image = await imageFuture; final ui.Image image = await imageFuture;
final ByteData? bytes = await image.toByteData(); final ByteData? bytes = await image.toByteData();
if (bytes == null) if (bytes == null) {
return 'could not be encoded.'; return 'could not be encoded.';
}
final ByteData? referenceBytes = await referenceImage.toByteData(); final ByteData? referenceBytes = await referenceImage.toByteData();
if (referenceBytes == null) if (referenceBytes == null) {
return 'could not have its reference image encoded.'; return 'could not have its reference image encoded.';
}
if (referenceImage.height != image.height || referenceImage.width != image.width) if (referenceImage.height != image.height || referenceImage.width != image.width) {
return 'does not match as width or height do not match. $image != $referenceImage'; return 'does not match as width or height do not match. $image != $referenceImage';
}
final int countDifferentPixels = _countDifferentPixels( final int countDifferentPixels = _countDifferentPixels(
Uint8List.view(bytes.buffer), Uint8List.view(bytes.buffer),
...@@ -1849,63 +1925,88 @@ class _MatchesSemanticsData extends Matcher { ...@@ -1849,63 +1925,88 @@ class _MatchesSemanticsData extends Matcher {
@override @override
Description describe(Description description) { Description describe(Description description) {
description.add('has semantics'); description.add('has semantics');
if (label != null) if (label != null) {
description.add(' with label: $label'); description.add(' with label: $label');
if (attributedLabel != null) }
if (attributedLabel != null) {
description.add(' with attributedLabel: $attributedLabel'); description.add(' with attributedLabel: $attributedLabel');
if (value != null) }
if (value != null) {
description.add(' with value: $value'); description.add(' with value: $value');
if (attributedValue != null) }
if (attributedValue != null) {
description.add(' with attributedValue: $attributedValue'); description.add(' with attributedValue: $attributedValue');
if (hint != null) }
if (hint != null) {
description.add(' with hint: $hint'); description.add(' with hint: $hint');
if (attributedHint != null) }
if (attributedHint != null) {
description.add(' with attributedHint: $attributedHint'); description.add(' with attributedHint: $attributedHint');
if (increasedValue != null) }
if (increasedValue != null) {
description.add(' with increasedValue: $increasedValue '); description.add(' with increasedValue: $increasedValue ');
if (attributedIncreasedValue != null) }
if (attributedIncreasedValue != null) {
description.add(' with attributedIncreasedValue: $attributedIncreasedValue'); description.add(' with attributedIncreasedValue: $attributedIncreasedValue');
if (decreasedValue != null) }
if (decreasedValue != null) {
description.add(' with decreasedValue: $decreasedValue '); description.add(' with decreasedValue: $decreasedValue ');
if (attributedDecreasedValue != null) }
if (attributedDecreasedValue != null) {
description.add(' with attributedDecreasedValue: $attributedDecreasedValue'); description.add(' with attributedDecreasedValue: $attributedDecreasedValue');
if (tooltip != null) }
if (tooltip != null) {
description.add(' with tooltip: $tooltip'); description.add(' with tooltip: $tooltip');
if (actions != null) }
if (actions != null) {
description.add(' with actions: ').addDescriptionOf(actions); description.add(' with actions: ').addDescriptionOf(actions);
if (flags != null) }
if (flags != null) {
description.add(' with flags: ').addDescriptionOf(flags); description.add(' with flags: ').addDescriptionOf(flags);
if (textDirection != null) }
if (textDirection != null) {
description.add(' with textDirection: $textDirection '); description.add(' with textDirection: $textDirection ');
if (rect != null) }
if (rect != null) {
description.add(' with rect: $rect'); description.add(' with rect: $rect');
if (size != null) }
if (size != null) {
description.add(' with size: $size'); description.add(' with size: $size');
if (elevation != null) }
if (elevation != null) {
description.add(' with elevation: $elevation'); description.add(' with elevation: $elevation');
if (thickness != null) }
if (thickness != null) {
description.add(' with thickness: $thickness'); description.add(' with thickness: $thickness');
if (platformViewId != null) }
if (platformViewId != null) {
description.add(' with platformViewId: $platformViewId'); description.add(' with platformViewId: $platformViewId');
if (maxValueLength != null) }
if (maxValueLength != null) {
description.add(' with maxValueLength: $maxValueLength'); description.add(' with maxValueLength: $maxValueLength');
if (currentValueLength != null) }
if (currentValueLength != null) {
description.add(' with currentValueLength: $currentValueLength'); description.add(' with currentValueLength: $currentValueLength');
if (customActions != null) }
if (customActions != null) {
description.add(' with custom actions: $customActions'); description.add(' with custom actions: $customActions');
if (hintOverrides != null) }
if (hintOverrides != null) {
description.add(' with custom hints: $hintOverrides'); description.add(' with custom hints: $hintOverrides');
}
if (children != null) { if (children != null) {
description.add(' with children:\n'); description.add(' with children:\n');
for (final _MatchesSemanticsData child in children!.cast<_MatchesSemanticsData>()) for (final _MatchesSemanticsData child in children!.cast<_MatchesSemanticsData>()) {
child.describe(description); child.describe(description);
}
} }
return description; return description;
} }
bool _stringAttributesEqual(List<StringAttribute> first, List<StringAttribute> second) { bool _stringAttributesEqual(List<StringAttribute> first, List<StringAttribute> second) {
if (first.length != second.length) if (first.length != second.length) {
return false; return false;
}
for (int i = 0; i < first.length; i++) { for (int i = 0; i < first.length; i++) {
if (first[i] is SpellOutStringAttribute && if (first[i] is SpellOutStringAttribute &&
(second[i] is! SpellOutStringAttribute || (second[i] is! SpellOutStringAttribute ||
...@@ -1924,72 +2025,88 @@ class _MatchesSemanticsData extends Matcher { ...@@ -1924,72 +2025,88 @@ class _MatchesSemanticsData extends Matcher {
@override @override
bool matches(dynamic node, Map<dynamic, dynamic> matchState) { bool matches(dynamic node, Map<dynamic, dynamic> matchState) {
if (node == null) if (node == null) {
return failWithDescription(matchState, 'No SemanticsData provided. ' return failWithDescription(matchState, 'No SemanticsData provided. '
'Maybe you forgot to enable semantics?'); 'Maybe you forgot to enable semantics?');
}
final SemanticsData data = node is SemanticsNode ? node.getSemanticsData() : (node as SemanticsData); final SemanticsData data = node is SemanticsNode ? node.getSemanticsData() : (node as SemanticsData);
if (label != null && label != data.label) if (label != null && label != data.label) {
return failWithDescription(matchState, 'label was: ${data.label}'); return failWithDescription(matchState, 'label was: ${data.label}');
}
if (attributedLabel != null && if (attributedLabel != null &&
(attributedLabel!.string != data.attributedLabel.string || (attributedLabel!.string != data.attributedLabel.string ||
!_stringAttributesEqual(attributedLabel!.attributes, data.attributedLabel.attributes))) { !_stringAttributesEqual(attributedLabel!.attributes, data.attributedLabel.attributes))) {
return failWithDescription( return failWithDescription(
matchState, 'attributedLabel was: ${data.attributedLabel}'); matchState, 'attributedLabel was: ${data.attributedLabel}');
} }
if (hint != null && hint != data.hint) if (hint != null && hint != data.hint) {
return failWithDescription(matchState, 'hint was: ${data.hint}'); return failWithDescription(matchState, 'hint was: ${data.hint}');
}
if (attributedHint != null && if (attributedHint != null &&
(attributedHint!.string != data.attributedHint.string || (attributedHint!.string != data.attributedHint.string ||
!_stringAttributesEqual(attributedHint!.attributes, data.attributedHint.attributes))) { !_stringAttributesEqual(attributedHint!.attributes, data.attributedHint.attributes))) {
return failWithDescription( return failWithDescription(
matchState, 'attributedHint was: ${data.attributedHint}'); matchState, 'attributedHint was: ${data.attributedHint}');
} }
if (value != null && value != data.value) if (value != null && value != data.value) {
return failWithDescription(matchState, 'value was: ${data.value}'); return failWithDescription(matchState, 'value was: ${data.value}');
}
if (attributedValue != null && if (attributedValue != null &&
(attributedValue!.string != data.attributedValue.string || (attributedValue!.string != data.attributedValue.string ||
!_stringAttributesEqual(attributedValue!.attributes, data.attributedValue.attributes))) { !_stringAttributesEqual(attributedValue!.attributes, data.attributedValue.attributes))) {
return failWithDescription( return failWithDescription(
matchState, 'attributedValue was: ${data.attributedValue}'); matchState, 'attributedValue was: ${data.attributedValue}');
} }
if (increasedValue != null && increasedValue != data.increasedValue) if (increasedValue != null && increasedValue != data.increasedValue) {
return failWithDescription(matchState, 'increasedValue was: ${data.increasedValue}'); return failWithDescription(matchState, 'increasedValue was: ${data.increasedValue}');
}
if (attributedIncreasedValue != null && if (attributedIncreasedValue != null &&
(attributedIncreasedValue!.string != data.attributedIncreasedValue.string || (attributedIncreasedValue!.string != data.attributedIncreasedValue.string ||
!_stringAttributesEqual(attributedIncreasedValue!.attributes, data.attributedIncreasedValue.attributes))) { !_stringAttributesEqual(attributedIncreasedValue!.attributes, data.attributedIncreasedValue.attributes))) {
return failWithDescription( return failWithDescription(
matchState, 'attributedIncreasedValue was: ${data.attributedIncreasedValue}'); matchState, 'attributedIncreasedValue was: ${data.attributedIncreasedValue}');
} }
if (decreasedValue != null && decreasedValue != data.decreasedValue) if (decreasedValue != null && decreasedValue != data.decreasedValue) {
return failWithDescription(matchState, 'decreasedValue was: ${data.decreasedValue}'); return failWithDescription(matchState, 'decreasedValue was: ${data.decreasedValue}');
}
if (attributedDecreasedValue != null && if (attributedDecreasedValue != null &&
(attributedDecreasedValue!.string != data.attributedDecreasedValue.string || (attributedDecreasedValue!.string != data.attributedDecreasedValue.string ||
!_stringAttributesEqual(attributedDecreasedValue!.attributes, data.attributedDecreasedValue.attributes))) { !_stringAttributesEqual(attributedDecreasedValue!.attributes, data.attributedDecreasedValue.attributes))) {
return failWithDescription( return failWithDescription(
matchState, 'attributedDecreasedValue was: ${data.attributedDecreasedValue}'); matchState, 'attributedDecreasedValue was: ${data.attributedDecreasedValue}');
} }
if (tooltip != null && tooltip != data.tooltip) if (tooltip != null && tooltip != data.tooltip) {
return failWithDescription(matchState, 'tooltip was: ${data.tooltip}'); return failWithDescription(matchState, 'tooltip was: ${data.tooltip}');
if (textDirection != null && textDirection != data.textDirection) }
if (textDirection != null && textDirection != data.textDirection) {
return failWithDescription(matchState, 'textDirection was: $textDirection'); return failWithDescription(matchState, 'textDirection was: $textDirection');
if (rect != null && rect != data.rect) }
if (rect != null && rect != data.rect) {
return failWithDescription(matchState, 'rect was: ${data.rect}'); return failWithDescription(matchState, 'rect was: ${data.rect}');
if (size != null && size != data.rect.size) }
if (size != null && size != data.rect.size) {
return failWithDescription(matchState, 'size was: ${data.rect.size}'); return failWithDescription(matchState, 'size was: ${data.rect.size}');
if (elevation != null && elevation != data.elevation) }
if (elevation != null && elevation != data.elevation) {
return failWithDescription(matchState, 'elevation was: ${data.elevation}'); return failWithDescription(matchState, 'elevation was: ${data.elevation}');
if (thickness != null && thickness != data.thickness) }
if (thickness != null && thickness != data.thickness) {
return failWithDescription(matchState, 'thickness was: ${data.thickness}'); return failWithDescription(matchState, 'thickness was: ${data.thickness}');
if (platformViewId != null && platformViewId != data.platformViewId) }
if (platformViewId != null && platformViewId != data.platformViewId) {
return failWithDescription(matchState, 'platformViewId was: ${data.platformViewId}'); return failWithDescription(matchState, 'platformViewId was: ${data.platformViewId}');
if (currentValueLength != null && currentValueLength != data.currentValueLength) }
if (currentValueLength != null && currentValueLength != data.currentValueLength) {
return failWithDescription(matchState, 'currentValueLength was: ${data.currentValueLength}'); return failWithDescription(matchState, 'currentValueLength was: ${data.currentValueLength}');
if (maxValueLength != null && maxValueLength != data.maxValueLength) }
if (maxValueLength != null && maxValueLength != data.maxValueLength) {
return failWithDescription(matchState, 'maxValueLength was: ${data.maxValueLength}'); return failWithDescription(matchState, 'maxValueLength was: ${data.maxValueLength}');
}
if (actions != null) { if (actions != null) {
int actionBits = 0; int actionBits = 0;
for (final SemanticsAction action in actions!) for (final SemanticsAction action in actions!) {
actionBits |= action.index; actionBits |= action.index;
}
if (actionBits != data.actions) { if (actionBits != data.actions) {
final List<String> actionSummary = <String>[ final List<String> actionSummary = <String>[
for (final SemanticsAction action in SemanticsAction.values.values) for (final SemanticsAction action in SemanticsAction.values.values)
...@@ -2004,26 +2121,31 @@ class _MatchesSemanticsData extends Matcher { ...@@ -2004,26 +2121,31 @@ class _MatchesSemanticsData extends Matcher {
return CustomSemanticsAction.getAction(id)!; return CustomSemanticsAction.getAction(id)!;
}).toList() ?? <CustomSemanticsAction>[]; }).toList() ?? <CustomSemanticsAction>[];
final List<CustomSemanticsAction> expectedCustomActions = customActions?.toList() ?? <CustomSemanticsAction>[]; final List<CustomSemanticsAction> expectedCustomActions = customActions?.toList() ?? <CustomSemanticsAction>[];
if (hintOverrides?.onTapHint != null) if (hintOverrides?.onTapHint != null) {
expectedCustomActions.add(CustomSemanticsAction.overridingAction(hint: hintOverrides!.onTapHint!, action: SemanticsAction.tap)); expectedCustomActions.add(CustomSemanticsAction.overridingAction(hint: hintOverrides!.onTapHint!, action: SemanticsAction.tap));
if (hintOverrides?.onLongPressHint != null) }
if (hintOverrides?.onLongPressHint != null) {
expectedCustomActions.add(CustomSemanticsAction.overridingAction(hint: hintOverrides!.onLongPressHint!, action: SemanticsAction.longPress)); expectedCustomActions.add(CustomSemanticsAction.overridingAction(hint: hintOverrides!.onLongPressHint!, action: SemanticsAction.longPress));
if (expectedCustomActions.length != providedCustomActions.length) }
if (expectedCustomActions.length != providedCustomActions.length) {
return failWithDescription(matchState, 'custom actions where: $providedCustomActions'); return failWithDescription(matchState, 'custom actions where: $providedCustomActions');
}
int sortActions(CustomSemanticsAction left, CustomSemanticsAction right) { int sortActions(CustomSemanticsAction left, CustomSemanticsAction right) {
return CustomSemanticsAction.getIdentifier(left) - CustomSemanticsAction.getIdentifier(right); return CustomSemanticsAction.getIdentifier(left) - CustomSemanticsAction.getIdentifier(right);
} }
expectedCustomActions.sort(sortActions); expectedCustomActions.sort(sortActions);
providedCustomActions.sort(sortActions); providedCustomActions.sort(sortActions);
for (int i = 0; i < expectedCustomActions.length; i++) { for (int i = 0; i < expectedCustomActions.length; i++) {
if (expectedCustomActions[i] != providedCustomActions[i]) if (expectedCustomActions[i] != providedCustomActions[i]) {
return failWithDescription(matchState, 'custom actions where: $providedCustomActions'); return failWithDescription(matchState, 'custom actions where: $providedCustomActions');
}
} }
} }
if (flags != null) { if (flags != null) {
int flagBits = 0; int flagBits = 0;
for (final SemanticsFlag flag in flags!) for (final SemanticsFlag flag in flags!) {
flagBits |= flag.index; flagBits |= flag.index;
}
if (flagBits != data.flags) { if (flagBits != data.flags) {
final List<String> flagSummary = <String>[ final List<String> flagSummary = <String>[
for (final SemanticsFlag flag in SemanticsFlag.values.values) for (final SemanticsFlag flag in SemanticsFlag.values.values)
...@@ -2074,8 +2196,9 @@ class _MatchesAccessibilityGuideline extends AsyncMatcher { ...@@ -2074,8 +2196,9 @@ class _MatchesAccessibilityGuideline extends AsyncMatcher {
@override @override
Future<String?> matchAsync(covariant WidgetTester tester) async { Future<String?> matchAsync(covariant WidgetTester tester) async {
final Evaluation result = await guideline.evaluate(tester); final Evaluation result = await guideline.evaluate(tester);
if (result.passed) if (result.passed) {
return null; return null;
}
return result.reason; return result.reason;
} }
} }
...@@ -2093,8 +2216,9 @@ class _DoesNotMatchAccessibilityGuideline extends AsyncMatcher { ...@@ -2093,8 +2216,9 @@ class _DoesNotMatchAccessibilityGuideline extends AsyncMatcher {
@override @override
Future<String?> matchAsync(covariant WidgetTester tester) async { Future<String?> matchAsync(covariant WidgetTester tester) async {
final Evaluation result = await guideline.evaluate(tester); final Evaluation result = await guideline.evaluate(tester);
if (result.passed) if (result.passed) {
return 'Failed'; return 'Failed';
}
return null; return null;
} }
} }
...@@ -78,8 +78,9 @@ class TestAsyncUtils { ...@@ -78,8 +78,9 @@ class TestAsyncUtils {
final List<DiagnosticsNode> information = <DiagnosticsNode>[]; final List<DiagnosticsNode> information = <DiagnosticsNode>[];
while (_scopeStack.isNotEmpty) { while (_scopeStack.isNotEmpty) {
closedScope = _scopeStack.removeLast(); closedScope = _scopeStack.removeLast();
if (closedScope == scope) if (closedScope == scope) {
break; break;
}
if (!leaked) { if (!leaked) {
information.add(ErrorSummary('Asynchronous call to guarded function leaked.')); information.add(ErrorSummary('Asynchronous call to guarded function leaked.'));
information.add(ErrorHint('You must use "await" with all Future-returning test APIs.')); information.add(ErrorHint('You must use "await" with all Future-returning test APIs.'));
...@@ -107,8 +108,9 @@ class TestAsyncUtils { ...@@ -107,8 +108,9 @@ class TestAsyncUtils {
} }
throw FlutterError.fromParts(information); throw FlutterError.fromParts(information);
} }
if (error != null) if (error != null) {
return Future<T>.error(error! as Object, stack); return Future<T>.error(error! as Object, stack);
}
return Future<T>.value(resultValue); return Future<T>.value(resultValue);
} }
return result.then<T>( return result.then<T>(
...@@ -123,8 +125,9 @@ class TestAsyncUtils { ...@@ -123,8 +125,9 @@ class TestAsyncUtils {
static Zone? get _currentScopeZone { static Zone? get _currentScopeZone {
Zone? zone = Zone.current; Zone? zone = Zone.current;
while (zone != null) { while (zone != null) {
if (zone[_scopeStack] == true) if (zone[_scopeStack] == true) {
return zone; return zone;
}
zone = zone.parent; zone = zone.parent;
} }
return null; return null;
...@@ -174,8 +177,9 @@ class TestAsyncUtils { ...@@ -174,8 +177,9 @@ class TestAsyncUtils {
skipCount += 1; skipCount += 1;
scope = candidateScope; scope = candidateScope;
if (skipCount >= _scopeStack.length) { if (skipCount >= _scopeStack.length) {
if (zone == null) if (zone == null) {
break; break;
}
// Some people have reported reaching this point, but it's not clear // Some people have reported reaching this point, but it's not clear
// why. For now, just silently return. // why. For now, just silently return.
// TODO(ianh): If we ever get a test case that shows how we reach // TODO(ianh): If we ever get a test case that shows how we reach
......
...@@ -89,11 +89,13 @@ class TestDefaultBinaryMessenger extends BinaryMessenger { ...@@ -89,11 +89,13 @@ class TestDefaultBinaryMessenger extends BinaryMessenger {
ui.PlatformMessageResponseCallback? callback, ui.PlatformMessageResponseCallback? callback,
) { ) {
Future<ByteData?>? result; Future<ByteData?>? result;
if (_inboundHandlers.containsKey(channel)) if (_inboundHandlers.containsKey(channel)) {
result = _inboundHandlers[channel]!(data); result = _inboundHandlers[channel]!(data);
}
result ??= Future<ByteData?>.value(); result ??= Future<ByteData?>.value();
if (callback != null) if (callback != null) {
result = result.then((ByteData? result) { callback(result); return result; }); result = result.then((ByteData? result) { callback(result); return result; });
}
return result; return result;
} }
......
...@@ -36,8 +36,9 @@ void _defaultTestExceptionReporter(FlutterErrorDetails errorDetails, String test ...@@ -36,8 +36,9 @@ void _defaultTestExceptionReporter(FlutterErrorDetails errorDetails, String test
// get the same effect here by calling that error handler directly or indeed just throwing. // get the same effect here by calling that error handler directly or indeed just throwing.
// However, we call registerException because that's the semantically correct thing... // However, we call registerException because that's the semantically correct thing...
String additional = ''; String additional = '';
if (testDescription.isNotEmpty) if (testDescription.isNotEmpty) {
additional = '\nThe test description was: $testDescription'; additional = '\nThe test description was: $testDescription';
}
test_package.registerException('Test failed. See exception logs above.$additional', _emptyStackTrace); test_package.registerException('Test failed. See exception logs above.$additional', _emptyStackTrace);
} }
......
...@@ -98,8 +98,9 @@ class TestPointer { ...@@ -98,8 +98,9 @@ class TestPointer {
int? buttons, int? buttons,
}) { }) {
_location = newLocation; _location = newLocation;
if (buttons != null) if (buttons != null) {
_buttons = buttons; _buttons = buttons;
}
switch (event.runtimeType) { switch (event.runtimeType) {
case PointerDownEvent: case PointerDownEvent:
assert(!isDown); assert(!isDown);
...@@ -132,8 +133,9 @@ class TestPointer { ...@@ -132,8 +133,9 @@ class TestPointer {
assert(!isPanZoomActive); assert(!isPanZoomActive);
_isDown = true; _isDown = true;
_location = newLocation; _location = newLocation;
if (buttons != null) if (buttons != null) {
_buttons = buttons; _buttons = buttons;
}
return PointerDownEvent( return PointerDownEvent(
timeStamp: timeStamp, timeStamp: timeStamp,
kind: kind, kind: kind,
...@@ -167,8 +169,9 @@ class TestPointer { ...@@ -167,8 +169,9 @@ class TestPointer {
assert(!isPanZoomActive); assert(!isPanZoomActive);
final Offset delta = newLocation - location!; final Offset delta = newLocation - location!;
_location = newLocation; _location = newLocation;
if (buttons != null) if (buttons != null) {
_buttons = buttons; _buttons = buttons;
}
return PointerMoveEvent( return PointerMoveEvent(
timeStamp: timeStamp, timeStamp: timeStamp,
kind: kind, kind: kind,
......
...@@ -69,8 +69,9 @@ E? _lastWhereOrNull<E>(Iterable<E> list, bool Function(E) test) { ...@@ -69,8 +69,9 @@ E? _lastWhereOrNull<E>(Iterable<E> list, bool Function(E) test) {
foundMatching = true; foundMatching = true;
} }
} }
if (foundMatching) if (foundMatching) {
return result; return result;
}
return null; return null;
} }
...@@ -414,8 +415,9 @@ Future<void> benchmarkWidgets( ...@@ -414,8 +415,9 @@ Future<void> benchmarkWidgets(
bool semanticsEnabled = false, bool semanticsEnabled = false,
}) { }) {
assert(() { assert(() {
if (mayRunWithAsserts) if (mayRunWithAsserts) {
return true; return true;
}
debugPrint(kDebugWarning); debugPrint(kDebugWarning);
return true; return true;
}()); }());
...@@ -499,8 +501,9 @@ Future<void> expectLater( ...@@ -499,8 +501,9 @@ Future<void> expectLater(
/// `testWidgets`) can be used as the `vsync` for `AnimationController` objects. /// `testWidgets`) can be used as the `vsync` for `AnimationController` objects.
class WidgetTester extends WidgetController implements HitTestDispatcher, TickerProvider { class WidgetTester extends WidgetController implements HitTestDispatcher, TickerProvider {
WidgetTester._(super.binding) { WidgetTester._(super.binding) {
if (binding is LiveTestWidgetsFlutterBinding) if (binding is LiveTestWidgetsFlutterBinding) {
(binding as LiveTestWidgetsFlutterBinding).deviceEventDispatcher = this; (binding as LiveTestWidgetsFlutterBinding).deviceEventDispatcher = this;
}
} }
/// The description string of the test currently being run. /// The description string of the test currently being run.
...@@ -663,8 +666,9 @@ class WidgetTester extends WidgetController implements HitTestDispatcher, Ticker ...@@ -663,8 +666,9 @@ class WidgetTester extends WidgetController implements HitTestDispatcher, Ticker
final DateTime endTime = binding.clock.fromNowBy(timeout); final DateTime endTime = binding.clock.fromNowBy(timeout);
int count = 0; int count = 0;
do { do {
if (binding.clock.now().isAfter(endTime)) if (binding.clock.now().isAfter(endTime)) {
throw FlutterError('pumpAndSettle timed out'); throw FlutterError('pumpAndSettle timed out');
}
await binding.pump(duration, phase); await binding.pump(duration, phase);
count += 1; count += 1;
} while (binding.hasScheduledFrame); } while (binding.hasScheduledFrame);
...@@ -837,8 +841,9 @@ class WidgetTester extends WidgetController implements HitTestDispatcher, Ticker ...@@ -837,8 +841,9 @@ class WidgetTester extends WidgetController implements HitTestDispatcher, Ticker
int totalNumber = 0; int totalNumber = 0;
printToConsole('Some possible finders for the widgets at ${event.position}:'); printToConsole('Some possible finders for the widgets at ${event.position}:');
for (final Element element in candidates) { for (final Element element in candidates) {
if (totalNumber > 13) // an arbitrary number of finders that feels useful without being overwhelming if (totalNumber > 13) {
break; break;
}
totalNumber += 1; // optimistically assume we'll be able to describe it totalNumber += 1; // optimistically assume we'll be able to describe it
final Widget widget = element.widget; final Widget widget = element.widget;
...@@ -912,8 +917,9 @@ class WidgetTester extends WidgetController implements HitTestDispatcher, Ticker ...@@ -912,8 +917,9 @@ class WidgetTester extends WidgetController implements HitTestDispatcher, Ticker
totalNumber -= 1; // if we got here, we didn't actually find something to say about it totalNumber -= 1; // if we got here, we didn't actually find something to say about it
} }
if (totalNumber == 0) if (totalNumber == 0) {
printToConsole(' <could not come up with any unique finders>'); printToConsole(' <could not come up with any unique finders>');
}
} }
} }
......
...@@ -569,8 +569,9 @@ class FakeAccessibilityFeatures implements ui.AccessibilityFeatures { ...@@ -569,8 +569,9 @@ class FakeAccessibilityFeatures implements ui.AccessibilityFeatures {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType) {
return false; return false;
}
return other is FakeAccessibilityFeatures return other is FakeAccessibilityFeatures
&& other.accessibleNavigation == accessibleNavigation && other.accessibleNavigation == accessibleNavigation
&& other.invertColors == invertColors && other.invertColors == invertColors
......
...@@ -416,12 +416,13 @@ void main() { ...@@ -416,12 +416,13 @@ void main() {
const String b = '$kSecondaryMouseButton'; const String b = '$kSecondaryMouseButton';
for(int i = 0; i < logs.length; i++) { for(int i = 0; i < logs.length; i++) {
if (i == 0) if (i == 0) {
expect(logs[i], 'down $b'); expect(logs[i], 'down $b');
else if (i != logs.length - 1) } else if (i != logs.length - 1) {
expect(logs[i], 'move $b'); expect(logs[i], 'move $b');
else } else {
expect(logs[i], 'up 0'); expect(logs[i], 'up 0');
}
} }
}, },
); );
...@@ -472,12 +473,13 @@ void main() { ...@@ -472,12 +473,13 @@ void main() {
const String b = '$kSecondaryMouseButton'; const String b = '$kSecondaryMouseButton';
for(int i = 0; i < logs.length; i++) { for(int i = 0; i < logs.length; i++) {
if (i == 0) if (i == 0) {
expect(logs[i], 'down $b'); expect(logs[i], 'down $b');
else if (i != logs.length - 1) } else if (i != logs.length - 1) {
expect(logs[i], 'move $b'); expect(logs[i], 'move $b');
else } else {
expect(logs[i], 'up 0'); expect(logs[i], 'up 0');
}
} }
}, },
); );
...@@ -503,12 +505,13 @@ void main() { ...@@ -503,12 +505,13 @@ void main() {
const String b = '$kSecondaryMouseButton'; const String b = '$kSecondaryMouseButton';
for(int i = 0; i < logs.length; i++) { for(int i = 0; i < logs.length; i++) {
if (i == 0) if (i == 0) {
expect(logs[i], 'down $b'); expect(logs[i], 'down $b');
else if (i != logs.length - 1) } else if (i != logs.length - 1) {
expect(logs[i], 'move $b'); expect(logs[i], 'move $b');
else } else {
expect(logs[i], 'up 0'); expect(logs[i], 'up 0');
}
} }
}, },
); );
...@@ -535,12 +538,13 @@ void main() { ...@@ -535,12 +538,13 @@ void main() {
const String b = '$kSecondaryMouseButton'; const String b = '$kSecondaryMouseButton';
for(int i = 0; i < logs.length; i++) { for(int i = 0; i < logs.length; i++) {
if (i == 0) if (i == 0) {
expect(logs[i], 'down $b'); expect(logs[i], 'down $b');
else if (i != logs.length - 1) } else if (i != logs.length - 1) {
expect(logs[i], 'move $b'); expect(logs[i], 'move $b');
else } else {
expect(logs[i], 'up 0'); expect(logs[i], 'up 0');
}
} }
}, },
); );
...@@ -599,12 +603,13 @@ void main() { ...@@ -599,12 +603,13 @@ void main() {
const String b = '$kSecondaryMouseButton'; const String b = '$kSecondaryMouseButton';
for(int i = 0; i < logs.length; i++) { for(int i = 0; i < logs.length; i++) {
if (i == 0) if (i == 0) {
expect(logs[i], 'down $b'); expect(logs[i], 'down $b');
else if (i != logs.length - 1) } else if (i != logs.length - 1) {
expect(logs[i], 'move $b'); expect(logs[i], 'move $b');
else } else {
expect(logs[i], 'up 0'); expect(logs[i], 'up 0');
}
} }
}, },
); );
......
...@@ -15,8 +15,9 @@ import 'package:flutter_test/flutter_test.dart'; ...@@ -15,8 +15,9 @@ import 'package:flutter_test/flutter_test.dart';
class _MockToStringDeep { class _MockToStringDeep {
_MockToStringDeep(String str) : _lines = <String>[] { _MockToStringDeep(String str) : _lines = <String>[] {
final List<String> lines = str.split('\n'); final List<String> lines = str.split('\n');
for (int i = 0; i < lines.length - 1; ++i) for (int i = 0; i < lines.length - 1; ++i) {
_lines.add('${lines[i]}\n'); _lines.add('${lines[i]}\n');
}
// If the last line is empty, that really just means that the previous // If the last line is empty, that really just means that the previous
// line was terminated with a line break. // line was terminated with a line break.
...@@ -34,11 +35,13 @@ class _MockToStringDeep { ...@@ -34,11 +35,13 @@ class _MockToStringDeep {
String toStringDeep({ String prefixLineOne = '', String prefixOtherLines = '' }) { String toStringDeep({ String prefixLineOne = '', String prefixOtherLines = '' }) {
final StringBuffer sb = StringBuffer(); final StringBuffer sb = StringBuffer();
if (_lines.isNotEmpty) if (_lines.isNotEmpty) {
sb.write('$prefixLineOne${_lines.first}'); sb.write('$prefixLineOne${_lines.first}');
}
for (int i = 1; i < _lines.length; ++i) for (int i = 1; i < _lines.length; ++i) {
sb.write('$prefixOtherLines${_lines[i]}'); sb.write('$prefixOtherLines${_lines[i]}');
}
return sb.toString(); return sb.toString();
} }
...@@ -560,12 +563,15 @@ void main() { ...@@ -560,12 +563,15 @@ void main() {
int actions = 0; int actions = 0;
int flags = 0; int flags = 0;
const CustomSemanticsAction action = CustomSemanticsAction(label: 'test'); const CustomSemanticsAction action = CustomSemanticsAction(label: 'test');
for (final int index in SemanticsAction.values.keys) for (final int index in SemanticsAction.values.keys) {
actions |= index; actions |= index;
for (final int index in SemanticsFlag.values.keys) }
for (final int index in SemanticsFlag.values.keys) {
// TODO(mdebbar): Remove this if after https://github.com/flutter/engine/pull/9894 // TODO(mdebbar): Remove this if after https://github.com/flutter/engine/pull/9894
if (SemanticsFlag.values[index] != SemanticsFlag.isMultiline) if (SemanticsFlag.values[index] != SemanticsFlag.isMultiline) {
flags |= index; flags |= index;
}
}
final SemanticsData data = SemanticsData( final SemanticsData data = SemanticsData(
flags: flags, flags: flags,
actions: actions, actions: actions,
......
...@@ -158,10 +158,11 @@ class Registrar extends BinaryMessenger { ...@@ -158,10 +158,11 @@ class Registrar extends BinaryMessenger {
@override @override
void setMessageHandler(String channel, MessageHandler? handler) { void setMessageHandler(String channel, MessageHandler? handler) {
if (handler == null) if (handler == null) {
_handlers.remove(channel); _handlers.remove(channel);
else } else {
_handlers[channel] = handler; _handlers[channel] = handler;
}
} }
} }
......
...@@ -154,8 +154,9 @@ https://flutter.dev/docs/testing/integration-tests#testing-on-firebase-test-lab ...@@ -154,8 +154,9 @@ https://flutter.dev/docs/testing/integration-tests#testing-on-firebase-test-lab
/// ///
/// * [WidgetsFlutterBinding.ensureInitialized], the equivalent in the widgets framework. /// * [WidgetsFlutterBinding.ensureInitialized], the equivalent in the widgets framework.
static IntegrationTestWidgetsFlutterBinding ensureInitialized() { static IntegrationTestWidgetsFlutterBinding ensureInitialized() {
if (_instance == null) if (_instance == null) {
IntegrationTestWidgetsFlutterBinding(); IntegrationTestWidgetsFlutterBinding();
}
return _instance!; return _instance!;
} }
......
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