// 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 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  testWidgets('ErrorWidget displays actual error when throwing during build', (WidgetTester tester) async {
    final Key container = UniqueKey();
    const String errorText = 'Oh no, there was a crash!!1';

    await tester.pumpWidget(
      Container(
        key: container,
        color: Colors.red,
        padding: const EdgeInsets.all(10),
        child: Builder(
          builder: (BuildContext context) {
            throw UnsupportedError(errorText);
          },
        ),
      ),
    );

    expect(
      tester.takeException(),
      isA<UnsupportedError>().having((UnsupportedError error) => error.message, 'message', contains(errorText)),
    );

    final ErrorWidget errorWidget = tester.widget(find.byType(ErrorWidget));
    expect(errorWidget.message, contains(errorText));

    // Failure in one widget shouldn't ripple through the entire tree and effect
    // ancestors. Those should still be in the tree.
    expect(find.byKey(container), findsOneWidget);
  });

  testWidgets('when constructing an ErrorWidget due to a build failure throws an error, fail gracefully', (WidgetTester tester) async {
    final Key container = UniqueKey();
    await tester.pumpWidget(
      Container(
        key: container,
        color: Colors.red,
        padding: const EdgeInsets.all(10),
        // This widget throws during build, which causes the construction of an
        // ErrorWidget with the build error. However, during construction of
        // that ErrorWidget, another error is thrown.
        child: const MyDoubleThrowingWidget(),
      ),
    );

    expect(
      tester.takeException(),
      isA<UnsupportedError>().having((UnsupportedError error) => error.message, 'message', contains(MyThrowingElement.debugFillPropertiesErrorMessage)),
    );

    final ErrorWidget errorWidget = tester.widget(find.byType(ErrorWidget));
    expect(errorWidget.message, contains(MyThrowingElement.debugFillPropertiesErrorMessage));

    // Failure in one widget shouldn't ripple through the entire tree and effect
    // ancestors. Those should still be in the tree.
    expect(find.byKey(container), findsOneWidget);
  });
}

// This widget throws during its regular build and then again when the
// ErrorWidget is constructed, which calls MyThrowingElement.debugFillProperties.
class MyDoubleThrowingWidget extends StatelessWidget {
  const MyDoubleThrowingWidget({super.key});

  @override
  StatelessElement createElement() => MyThrowingElement(this);

  @override
  Widget build(BuildContext context) {
    throw UnsupportedError('You cannot build me!');
  }
}

class MyThrowingElement extends StatelessElement {
  MyThrowingElement(super.widget);

  static const String debugFillPropertiesErrorMessage = 'Crash during debugFillProperties';

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    throw UnsupportedError(debugFillPropertiesErrorMessage);
  }
}
