// 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'); }