diff --git a/dev/e2e_app/integration_test/overflow_test.dart b/dev/e2e_app/integration_test/overflow_test.dart index 2e4f345b0..36108aee0 100644 --- a/dev/e2e_app/integration_test/overflow_test.dart +++ b/dev/e2e_app/integration_test/overflow_test.dart @@ -1,3 +1,6 @@ +// Uncomment to test `Multiple exceptions were thrown` issue +// import 'package:flutter/widgets.dart'; + import 'common.dart'; void main() { @@ -5,5 +8,8 @@ void main() { await createApp($); await $('Open overflow screen').scrollTo().tap(); + + // Uncomment to test `Multiple exceptions were thrown` issue + // return $(ValueKey('key')).scrollTo().tap(); }); } diff --git a/dev/e2e_app/lib/overflow_screen.dart b/dev/e2e_app/lib/overflow_screen.dart index e36de8c2d..51c838621 100644 --- a/dev/e2e_app/lib/overflow_screen.dart +++ b/dev/e2e_app/lib/overflow_screen.dart @@ -1,4 +1,6 @@ import 'package:flutter/material.dart'; +// Uncomment to test `Multiple exceptions were thrown` issue +// import 'package:flutter/services.dart'; class OverflowScreen extends StatelessWidget { const OverflowScreen({super.key}); @@ -12,12 +14,18 @@ class OverflowScreen extends StatelessWidget { // } // // Future throwPlatformException() async { - // await Future.delayed(const Duration(milliseconds: 150)); + // await Future.delayed(const Duration(milliseconds: 110)); // throw PlatformException(code: 'code'); // } // + // Future throwFormatException() async { + // await Future.delayed(const Duration(milliseconds: 120)); + // throw FormatException(); + // } + // // throwStackOverflowException(); // throwPlatformException(); + // throwFormatException(); return Scaffold( appBar: AppBar( diff --git a/packages/patrol/lib/src/binding.dart b/packages/patrol/lib/src/binding.dart index ff3faa2ad..bf2b532f8 100644 --- a/packages/patrol/lib/src/binding.dart +++ b/packages/patrol/lib/src/binding.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'dart:convert'; import 'dart:developer'; -import 'dart:io' as io; import 'dart:isolate'; import 'package:flutter/foundation.dart'; @@ -44,28 +43,6 @@ class PatrolBinding extends LiveTestWidgetsFlutterBinding { /// You most likely don't want to call it yourself. PatrolBinding(NativeAutomatorConfig config) : _serviceExtensions = DevtoolsServiceExtensions(config) { - final oldTestExceptionReporter = reportTestException; - - /// Wraps the default test exception reporter to report the test results to - /// the native side of Patrol. - reportTestException = (details, testDescription) { - if (_currentDartTest case final testName?) { - assert(!constants.hotRestartEnabled); - // On iOS in release mode, diagnostics are compacted or truncated. - // We use the exceptionAsString() and stack to get the information - // about the exception. See [DiagnosticLevel]. - final detailsAsString = (kReleaseMode && io.Platform.isIOS) - ? '${details.exceptionAsString()} \n ${details.stack}' - : details.toString(); - - testResults[testName] = Failure( - testDescription, - detailsAsString, - ); - } - oldTestExceptionReporter(details, testDescription); - }; - setUp(() { if (constants.hotRestartEnabled) { return; diff --git a/packages/patrol/lib/src/native/patrol_app_service.dart b/packages/patrol/lib/src/native/patrol_app_service.dart index 451d5c3ad..acf513b24 100644 --- a/packages/patrol/lib/src/native/patrol_app_service.dart +++ b/packages/patrol/lib/src/native/patrol_app_service.dart @@ -158,17 +158,22 @@ class PatrolAppService extends PatrolAppServiceServer { final previousOnError = FlutterError.onError; FlutterError.onError = (details) { - final previousDetails = - switch (patrolBinding.testResults[request.name] as Failure?) { + final previousDetails = switch (patrolBinding.testResults[request.name]) { Failure(:final details?) => FlutterErrorDetails(exception: details), _ => null, }; + final detailsAsString = (kReleaseMode && Platform.isIOS) + ? '${details.exceptionAsString()} \n ${details.stack}' + : details.toString(); patrolBinding.testResults[request.name] = Failure( request.name, - '$details\n$previousDetails', + '$detailsAsString\n$previousDetails', ); + + previousOnError?.call(details); }; + final testExecutionResult = await testExecutionCompleted; FlutterError.onError = previousOnError;