| // Copyright 2014 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'dart:html' as html; |
| |
| import 'package:flutter/foundation.dart'; |
| import 'package:flutter/widgets.dart'; |
| import 'package:meta/dart2js.dart'; |
| |
| // Tests that the framework prints stack traces in all build modes. |
| // |
| // Regression test for https://github.com/flutter/flutter/issues/68616. |
| // |
| // See also `dev/integration_tests/web/lib/stack_trace.dart` that tests the |
| // framework's ability to parse stack traces in all build modes. |
| Future<void> main() async { |
| final StringBuffer errorMessage = StringBuffer(); |
| debugPrint = (String? message, { int? wrapWidth }) { |
| errorMessage.writeln(message); |
| }; |
| |
| runApp(const ThrowingWidget()); |
| |
| // Let the framework flush error messages. |
| await Future<void>.delayed(Duration.zero); |
| |
| final StringBuffer output = StringBuffer(); |
| if (_errorMessageFormattedCorrectly(errorMessage.toString())) { |
| output.writeln('--- TEST SUCCEEDED ---'); |
| } else { |
| output.writeln('--- UNEXPECTED ERROR MESSAGE FORMAT ---'); |
| output.writeln(errorMessage); |
| output.writeln('--- TEST FAILED ---'); |
| } |
| |
| print(output); |
| html.HttpRequest.request( |
| '/test-result', |
| method: 'POST', |
| sendData: '$output', |
| ); |
| } |
| |
| bool _errorMessageFormattedCorrectly(String errorMessage) { |
| if (!errorMessage.contains('Test error message')) { |
| return false; |
| } |
| |
| // In release mode symbols are minified. No sense testing the contents of the stack trace. |
| if (kReleaseMode) { |
| return true; |
| } |
| |
| const List<String> expectedFunctions = <String>[ |
| 'topLevelFunction', |
| 'secondLevelFunction', |
| 'thirdLevelFunction', |
| ]; |
| |
| return expectedFunctions.every(errorMessage.contains); |
| } |
| |
| class ThrowingWidget extends StatefulWidget { |
| const ThrowingWidget({super.key}); |
| |
| @override |
| State<ThrowingWidget> createState() => _ThrowingWidgetState(); |
| } |
| |
| class _ThrowingWidgetState extends State<ThrowingWidget> { |
| @override |
| void initState() { |
| super.initState(); |
| topLevelFunction(); |
| } |
| |
| @override |
| Widget build(BuildContext context) { |
| return Container(); |
| } |
| } |
| |
| @noInline |
| void topLevelFunction() { |
| secondLevelFunction(); |
| } |
| |
| @noInline |
| void secondLevelFunction() { |
| thirdLevelFunction(); |
| } |
| |
| @noInline |
| void thirdLevelFunction() { |
| throw Exception('Test error message'); |
| } |