// 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/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';

import 'multi_view_testing.dart';
import 'semantics_tester.dart';

void main() {
  test('OverlayEntry dispatches memory events', () async {
    await expectLater(
      await memoryEvents(
        () => OverlayEntry(builder: (BuildContext context) => Container()).dispose(),
        OverlayEntry,
      ),
      areCreateAndDispose,
    );
  });

  testWidgets('OverflowEntries context contains Overlay', (WidgetTester tester) async {
    final GlobalKey overlayKey = GlobalKey();
    var didBuild = false;
    late final OverlayEntry overlayEntry1;
    addTearDown(
      () => overlayEntry1
        ..remove()
        ..dispose(),
    );
    late final OverlayEntry overlayEntry2;
    addTearDown(
      () => overlayEntry2
        ..remove()
        ..dispose(),
    );

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(
          key: overlayKey,
          initialEntries: <OverlayEntry>[
            overlayEntry1 = OverlayEntry(
              builder: (BuildContext context) {
                didBuild = true;
                final Overlay overlay = context.findAncestorWidgetOfExactType<Overlay>()!;
                expect(overlay.key, equals(overlayKey));
                return Container();
              },
            ),
            overlayEntry2 = OverlayEntry(builder: (BuildContext context) => Container()),
          ],
        ),
      ),
    );
    expect(didBuild, isTrue);
    final RenderObject theater = overlayKey.currentContext!.findRenderObject()!;

    expect(theater, hasAGoodToStringDeep);
    expect(
      theater.toStringDeep(minLevel: DiagnosticLevel.info),
      equalsIgnoringHashCodes(
        '_RenderTheater#744c9\n'
        ' │ parentData: <none>\n'
        ' │ constraints: BoxConstraints(w=800.0, h=600.0)\n'
        ' │ size: Size(800.0, 600.0)\n'
        ' │ skipCount: 0\n'
        ' │ textDirection: ltr\n'
        ' │\n'
        ' ├─onstage 1: RenderLimitedBox#bb803\n'
        ' │ │ parentData: not positioned; offset=Offset(0.0, 0.0) (can use\n'
        ' │ │   size)\n'
        ' │ │ constraints: BoxConstraints(w=800.0, h=600.0)\n'
        ' │ │ size: Size(800.0, 600.0)\n'
        ' │ │ maxWidth: 0.0\n'
        ' │ │ maxHeight: 0.0\n'
        ' │ │\n'
        ' │ └─child: RenderConstrainedBox#62707\n'
        ' │     parentData: <none> (can use size)\n'
        ' │     constraints: BoxConstraints(w=800.0, h=600.0)\n'
        ' │     size: Size(800.0, 600.0)\n'
        ' │     additionalConstraints: BoxConstraints(biggest)\n'
        ' │\n'
        ' ├─onstage 2: RenderLimitedBox#af5f1\n'
        ' ╎ │ parentData: not positioned; offset=Offset(0.0, 0.0) (can use\n'
        ' ╎ │   size)\n'
        ' ╎ │ constraints: BoxConstraints(w=800.0, h=600.0)\n'
        ' ╎ │ size: Size(800.0, 600.0)\n'
        ' ╎ │ maxWidth: 0.0\n'
        ' ╎ │ maxHeight: 0.0\n'
        ' ╎ │\n'
        ' ╎ └─child: RenderConstrainedBox#69c48\n'
        ' ╎     parentData: <none> (can use size)\n'
        ' ╎     constraints: BoxConstraints(w=800.0, h=600.0)\n'
        ' ╎     size: Size(800.0, 600.0)\n'
        ' ╎     additionalConstraints: BoxConstraints(biggest)\n'
        ' ╎\n'
        ' └╌no offstage children\n',
      ),
    );
  });

  testWidgets('Offstage overlay', (WidgetTester tester) async {
    final GlobalKey overlayKey = GlobalKey();
    late final OverlayEntry overlayEntry1;
    addTearDown(
      () => overlayEntry1
        ..remove()
        ..dispose(),
    );
    late final OverlayEntry overlayEntry2;
    addTearDown(
      () => overlayEntry2
        ..remove()
        ..dispose(),
    );
    late final OverlayEntry overlayEntry3;
    addTearDown(
      () => overlayEntry3
        ..remove()
        ..dispose(),
    );

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(
          key: overlayKey,
          initialEntries: <OverlayEntry>[
            overlayEntry1 = OverlayEntry(
              opaque: true,
              maintainState: true,
              builder: (BuildContext context) => Container(),
            ),
            overlayEntry2 = OverlayEntry(
              opaque: true,
              maintainState: true,
              builder: (BuildContext context) => Container(),
            ),
            overlayEntry3 = OverlayEntry(
              opaque: true,
              maintainState: true,
              builder: (BuildContext context) => Container(),
            ),
          ],
        ),
      ),
    );
    final RenderObject theater = overlayKey.currentContext!.findRenderObject()!;

    expect(theater, hasAGoodToStringDeep);
    expect(
      theater.toStringDeep(minLevel: DiagnosticLevel.info),
      equalsIgnoringHashCodes(
        '_RenderTheater#385b3\n'
        ' │ parentData: <none>\n'
        ' │ constraints: BoxConstraints(w=800.0, h=600.0)\n'
        ' │ size: Size(800.0, 600.0)\n'
        ' │ skipCount: 2\n'
        ' │ textDirection: ltr\n'
        ' │\n'
        ' ├─onstage 1: RenderLimitedBox#0a77a\n'
        ' ╎ │ parentData: not positioned; offset=Offset(0.0, 0.0) (can use\n'
        ' ╎ │   size)\n'
        ' ╎ │ constraints: BoxConstraints(w=800.0, h=600.0)\n'
        ' ╎ │ size: Size(800.0, 600.0)\n'
        ' ╎ │ maxWidth: 0.0\n'
        ' ╎ │ maxHeight: 0.0\n'
        ' ╎ │\n'
        ' ╎ └─child: RenderConstrainedBox#21f3a\n'
        ' ╎     parentData: <none> (can use size)\n'
        ' ╎     constraints: BoxConstraints(w=800.0, h=600.0)\n'
        ' ╎     size: Size(800.0, 600.0)\n'
        ' ╎     additionalConstraints: BoxConstraints(biggest)\n'
        ' ╎\n'
        ' ╎╌offstage 1: RenderLimitedBox#62c8c NEEDS-LAYOUT NEEDS-PAINT\n'
        ' ╎ │ parentData: not positioned; offset=Offset(0.0, 0.0)\n'
        ' ╎ │ constraints: MISSING\n'
        ' ╎ │ size: MISSING\n'
        ' ╎ │ maxWidth: 0.0\n'
        ' ╎ │ maxHeight: 0.0\n'
        ' ╎ │\n'
        ' ╎ └─child: RenderConstrainedBox#425fa NEEDS-LAYOUT NEEDS-PAINT\n'
        ' ╎     parentData: <none>\n'
        ' ╎     constraints: MISSING\n'
        ' ╎     size: MISSING\n'
        ' ╎     additionalConstraints: BoxConstraints(biggest)\n'
        ' ╎\n'
        ' └╌offstage 2: RenderLimitedBox#03ae2 NEEDS-LAYOUT NEEDS-PAINT\n'
        '   │ parentData: not positioned; offset=Offset(0.0, 0.0)\n'
        '   │ constraints: MISSING\n'
        '   │ size: MISSING\n'
        '   │ maxWidth: 0.0\n'
        '   │ maxHeight: 0.0\n'
        '   │\n'
        '   └─child: RenderConstrainedBox#b4d48 NEEDS-LAYOUT NEEDS-PAINT\n'
        '       parentData: <none>\n'
        '       constraints: MISSING\n'
        '       size: MISSING\n'
        '       additionalConstraints: BoxConstraints(biggest)\n',
      ),
    );
  });

  test('of method calls getElementForInheritedWidgetOfExactType', () async {
    final context = FakeBuildContext();
    expect(context.called, isFalse);
    expect(Overlay.maybeOf(context), isNull);
    expect(context.called, isTrue);
  });

  testWidgets('insert top', (WidgetTester tester) async {
    final GlobalKey overlayKey = GlobalKey();
    final buildOrder = <String>[];
    late final OverlayEntry baseEntry;
    addTearDown(
      () => baseEntry
        ..remove()
        ..dispose(),
    );

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(
          key: overlayKey,
          initialEntries: <OverlayEntry>[
            baseEntry = OverlayEntry(
              builder: (BuildContext context) {
                buildOrder.add('Base');
                return Container();
              },
            ),
          ],
        ),
      ),
    );

    expect(buildOrder, <String>['Base']);

    buildOrder.clear();
    final overlay = overlayKey.currentState! as OverlayState;
    late final OverlayEntry newEntry;
    addTearDown(
      () => newEntry
        ..remove()
        ..dispose(),
    );
    overlay.insert(
      newEntry = OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add('New');
          return Container();
        },
      ),
    );
    await tester.pump();

    expect(buildOrder, <String>['Base', 'New']);
  });

  testWidgets('insert below', (WidgetTester tester) async {
    final GlobalKey overlayKey = GlobalKey();
    late final OverlayEntry baseEntry;
    addTearDown(
      () => baseEntry
        ..remove()
        ..dispose(),
    );
    final buildOrder = <String>[];

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(
          key: overlayKey,
          initialEntries: <OverlayEntry>[
            baseEntry = OverlayEntry(
              builder: (BuildContext context) {
                buildOrder.add('Base');
                return Container();
              },
            ),
          ],
        ),
      ),
    );

    expect(buildOrder, <String>['Base']);

    buildOrder.clear();
    final overlay = overlayKey.currentState! as OverlayState;
    late final OverlayEntry newEntry;
    addTearDown(
      () => newEntry
        ..remove()
        ..dispose(),
    );
    overlay.insert(
      newEntry = OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add('New');
          return Container();
        },
      ),
      below: baseEntry,
    );
    await tester.pump();

    expect(buildOrder, <String>['New', 'Base']);
  });

  testWidgets('insert above', (WidgetTester tester) async {
    final GlobalKey overlayKey = GlobalKey();
    late final OverlayEntry baseEntry;
    addTearDown(
      () => baseEntry
        ..remove()
        ..dispose(),
    );
    late final OverlayEntry topEntry;
    addTearDown(
      () => topEntry
        ..remove()
        ..dispose(),
    );
    final buildOrder = <String>[];

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(
          key: overlayKey,
          initialEntries: <OverlayEntry>[
            baseEntry = OverlayEntry(
              builder: (BuildContext context) {
                buildOrder.add('Base');
                return Container();
              },
            ),
            topEntry = OverlayEntry(
              builder: (BuildContext context) {
                buildOrder.add('Top');
                return Container();
              },
            ),
          ],
        ),
      ),
    );

    expect(buildOrder, <String>['Base', 'Top']);

    buildOrder.clear();
    final overlay = overlayKey.currentState! as OverlayState;
    late final OverlayEntry newEntry;
    addTearDown(
      () => newEntry
        ..remove()
        ..dispose(),
    );
    overlay.insert(
      newEntry = OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add('New');
          return Container();
        },
      ),
      above: baseEntry,
    );
    await tester.pump();

    expect(buildOrder, <String>['Base', 'New', 'Top']);
  });

  testWidgets('insertAll top', (WidgetTester tester) async {
    final GlobalKey overlayKey = GlobalKey();
    final buildOrder = <String>[];
    late final OverlayEntry baseEntry;
    addTearDown(
      () => baseEntry
        ..remove()
        ..dispose(),
    );

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(
          key: overlayKey,
          initialEntries: <OverlayEntry>[
            baseEntry = OverlayEntry(
              builder: (BuildContext context) {
                buildOrder.add('Base');
                return Container();
              },
            ),
          ],
        ),
      ),
    );

    expect(buildOrder, <String>['Base']);

    final entries = <OverlayEntry>[
      OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add('New1');
          return Container();
        },
      ),
      OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add('New2');
          return Container();
        },
      ),
    ];
    addTearDown(() {
      for (final entry in entries) {
        entry
          ..remove()
          ..dispose();
      }
    });

    buildOrder.clear();
    final overlay = overlayKey.currentState! as OverlayState;
    overlay.insertAll(entries);
    await tester.pump();

    expect(buildOrder, <String>['Base', 'New1', 'New2']);
  });

  testWidgets('insertAll below', (WidgetTester tester) async {
    final GlobalKey overlayKey = GlobalKey();
    late final OverlayEntry baseEntry;
    addTearDown(
      () => baseEntry
        ..remove()
        ..dispose(),
    );
    final buildOrder = <String>[];

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(
          key: overlayKey,
          initialEntries: <OverlayEntry>[
            baseEntry = OverlayEntry(
              builder: (BuildContext context) {
                buildOrder.add('Base');
                return Container();
              },
            ),
          ],
        ),
      ),
    );

    expect(buildOrder, <String>['Base']);

    final entries = <OverlayEntry>[
      OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add('New1');
          return Container();
        },
      ),
      OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add('New2');
          return Container();
        },
      ),
    ];
    addTearDown(() {
      for (final entry in entries) {
        entry
          ..remove()
          ..dispose();
      }
    });

    buildOrder.clear();
    final overlay = overlayKey.currentState! as OverlayState;
    overlay.insertAll(entries, below: baseEntry);
    await tester.pump();

    expect(buildOrder, <String>['New1', 'New2', 'Base']);
  });

  testWidgets('insertAll above', (WidgetTester tester) async {
    final GlobalKey overlayKey = GlobalKey();
    final buildOrder = <String>[];
    late final OverlayEntry baseEntry;
    addTearDown(
      () => baseEntry
        ..remove()
        ..dispose(),
    );
    late final OverlayEntry topEntry;
    addTearDown(
      () => topEntry
        ..remove()
        ..dispose(),
    );

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(
          key: overlayKey,
          initialEntries: <OverlayEntry>[
            baseEntry = OverlayEntry(
              builder: (BuildContext context) {
                buildOrder.add('Base');
                return Container();
              },
            ),
            topEntry = OverlayEntry(
              builder: (BuildContext context) {
                buildOrder.add('Top');
                return Container();
              },
            ),
          ],
        ),
      ),
    );

    expect(buildOrder, <String>['Base', 'Top']);

    final entries = <OverlayEntry>[
      OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add('New1');
          return Container();
        },
      ),
      OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add('New2');
          return Container();
        },
      ),
    ];
    addTearDown(() {
      for (final entry in entries) {
        entry
          ..remove()
          ..dispose();
      }
    });

    buildOrder.clear();
    final overlay = overlayKey.currentState! as OverlayState;
    overlay.insertAll(entries, above: baseEntry);
    await tester.pump();

    expect(buildOrder, <String>['Base', 'New1', 'New2', 'Top']);
  });

  testWidgets('rearrange', (WidgetTester tester) async {
    final GlobalKey overlayKey = GlobalKey();
    final buildOrder = <int>[];
    final initialEntries = <OverlayEntry>[
      OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add(0);
          return Container();
        },
      ),
      OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add(1);
          return Container();
        },
      ),
      OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add(2);
          return Container();
        },
      ),
      OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add(3);
          return Container();
        },
      ),
    ];
    addTearDown(() {
      for (final entry in initialEntries) {
        entry
          ..remove()
          ..dispose();
      }
    });

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(key: overlayKey, initialEntries: initialEntries),
      ),
    );

    expect(buildOrder, <int>[0, 1, 2, 3]);

    late final OverlayEntry newEntry;
    addTearDown(
      () => newEntry
        ..remove()
        ..dispose(),
    );
    final rearranged = <OverlayEntry>[
      initialEntries[3],
      newEntry = OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add(4);
          return Container();
        },
      ),
      initialEntries[2],
      // 1 intentionally missing, will end up on top
      initialEntries[0],
    ];

    buildOrder.clear();
    final overlay = overlayKey.currentState! as OverlayState;
    overlay.rearrange(rearranged);
    await tester.pump();

    expect(buildOrder, <int>[3, 4, 2, 0, 1]);
  });

  testWidgets('rearrange above', (WidgetTester tester) async {
    final GlobalKey overlayKey = GlobalKey();
    final buildOrder = <int>[];

    final initialEntries = <OverlayEntry>[
      OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add(0);
          return Container();
        },
      ),
      OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add(1);
          return Container();
        },
      ),
      OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add(2);
          return Container();
        },
      ),
      OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add(3);
          return Container();
        },
      ),
    ];
    addTearDown(() {
      for (final entry in initialEntries) {
        entry
          ..remove()
          ..dispose();
      }
    });

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(key: overlayKey, initialEntries: initialEntries),
      ),
    );

    expect(buildOrder, <int>[0, 1, 2, 3]);

    late final OverlayEntry newEntry;
    addTearDown(
      () => newEntry
        ..remove()
        ..dispose(),
    );
    final rearranged = <OverlayEntry>[
      initialEntries[3],
      newEntry = OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add(4);
          return Container();
        },
      ),
      initialEntries[2],
      // 1 intentionally missing
      initialEntries[0],
    ];

    buildOrder.clear();
    final overlay = overlayKey.currentState! as OverlayState;
    overlay.rearrange(rearranged, above: initialEntries[2]);
    await tester.pump();

    expect(buildOrder, <int>[3, 4, 2, 1, 0]);
  });

  testWidgets('rearrange below', (WidgetTester tester) async {
    final GlobalKey overlayKey = GlobalKey();
    final buildOrder = <int>[];
    final initialEntries = <OverlayEntry>[
      OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add(0);
          return Container();
        },
      ),
      OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add(1);
          return Container();
        },
      ),
      OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add(2);
          return Container();
        },
      ),
      OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add(3);
          return Container();
        },
      ),
    ];
    addTearDown(() {
      for (final entry in initialEntries) {
        entry
          ..remove()
          ..dispose();
      }
    });

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(key: overlayKey, initialEntries: initialEntries),
      ),
    );

    expect(buildOrder, <int>[0, 1, 2, 3]);

    late final OverlayEntry newEntry;
    addTearDown(
      () => newEntry
        ..remove()
        ..dispose(),
    );
    final rearranged = <OverlayEntry>[
      initialEntries[3],
      newEntry = OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add(4);
          return Container();
        },
      ),
      initialEntries[2],
      // 1 intentionally missing
      initialEntries[0],
    ];

    buildOrder.clear();
    final overlay = overlayKey.currentState! as OverlayState;
    overlay.rearrange(rearranged, below: initialEntries[2]);
    await tester.pump();

    expect(buildOrder, <int>[3, 4, 1, 2, 0]);
  });

  testWidgets('debugVerifyInsertPosition', (WidgetTester tester) async {
    final GlobalKey overlayKey = GlobalKey();
    late OverlayEntry base;

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(
          key: overlayKey,
          initialEntries: <OverlayEntry>[
            base = _buildOverlayEntry((BuildContext context) {
              return Container();
            }),
          ],
        ),
      ),
    );

    final overlay = overlayKey.currentState! as OverlayState;

    try {
      overlay.insert(
        _buildOverlayEntry((BuildContext context) {
          return Container();
        }),
        above: _buildOverlayEntry((BuildContext context) {
          return Container();
        }),
        below: _buildOverlayEntry((BuildContext context) {
          return Container();
        }),
      );
    } on AssertionError catch (e) {
      expect(e.message, 'Only one of `above` and `below` may be specified.');
    }

    expect(
      () => overlay.insert(
        _buildOverlayEntry((BuildContext context) {
          return Container();
        }),
        above: base,
      ),
      isNot(throwsAssertionError),
    );

    try {
      overlay.insert(
        _buildOverlayEntry((BuildContext context) {
          return Container();
        }),
        above: _buildOverlayEntry((BuildContext context) {
          return Container();
        }),
      );
    } on AssertionError catch (e) {
      expect(e.message, 'The provided entry used for `above` must be present in the Overlay.');
    }

    try {
      overlay.rearrange(
        <OverlayEntry>[base],
        above: _buildOverlayEntry((BuildContext context) {
          return Container();
        }),
      );
    } on AssertionError catch (e) {
      expect(
        e.message,
        'The provided entry used for `above` must be present in the Overlay and in the `newEntriesList`.',
      );
    }

    await tester.pump();
  });

  testWidgets('OverlayState.of() throws when called if an Overlay does not exist', (
    WidgetTester tester,
  ) async {
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Builder(
          builder: (BuildContext context) {
            late FlutterError error;
            final Widget debugRequiredFor = Container();
            try {
              Overlay.of(context, debugRequiredFor: debugRequiredFor);
            } on FlutterError catch (e) {
              error = e;
            } finally {
              expect(error, isNotNull);
              expect(error.diagnostics.length, 5);
              expect(error.diagnostics[2].level, DiagnosticLevel.hint);
              expect(
                error.diagnostics[2].toStringDeep(),
                equalsIgnoringHashCodes(
                  'The most common way to add an Overlay to an application is to\n'
                  'include a MaterialApp, CupertinoApp or Navigator widget in the\n'
                  'runApp() call.\n',
                ),
              );
              expect(error.diagnostics[3], isA<DiagnosticsProperty<Widget>>());
              expect(error.diagnostics[3].value, debugRequiredFor);
              expect(error.diagnostics[4], isA<DiagnosticsProperty<Element>>());
              expect(
                error.toStringDeep(),
                equalsIgnoringHashCodes(
                  'FlutterError\n'
                  '   No Overlay widget found.\n'
                  '   Container widgets require an Overlay widget ancestor for correct\n'
                  '   operation.\n'
                  '   The most common way to add an Overlay to an application is to\n'
                  '   include a MaterialApp, CupertinoApp or Navigator widget in the\n'
                  '   runApp() call.\n'
                  '   The specific widget that failed to find an overlay was:\n'
                  '     Container\n'
                  '   The context from which that widget was searching for an overlay\n'
                  '   was:\n'
                  '     Builder\n',
                ),
              );
            }
            return Container();
          },
        ),
      ),
    );
  });

  testWidgets("OverlayState.maybeOf() works when an Overlay does and doesn't exist", (
    WidgetTester tester,
  ) async {
    final GlobalKey overlayKey = GlobalKey();
    OverlayState? foundState;
    late final OverlayEntry baseEntry;
    addTearDown(
      () => baseEntry
        ..remove()
        ..dispose(),
    );

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(
          key: overlayKey,
          initialEntries: <OverlayEntry>[
            baseEntry = OverlayEntry(
              builder: (BuildContext context) {
                foundState = Overlay.maybeOf(context);
                return Container();
              },
            ),
          ],
        ),
      ),
    );

    expect(tester.takeException(), isNull);
    expect(foundState, isNotNull);
    foundState = null;

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Builder(
          builder: (BuildContext context) {
            foundState = Overlay.maybeOf(context);
            return const SizedBox();
          },
        ),
      ),
    );

    expect(tester.takeException(), isNull);
    expect(foundState, isNull);
  });

  testWidgets(
    'OverlayEntry.opaque can be changed when OverlayEntry is not part of an Overlay (yet)',
    (WidgetTester tester) async {
      final overlayKey = GlobalKey<OverlayState>();
      final Key root = UniqueKey();
      final Key top = UniqueKey();
      final rootEntry = OverlayEntry(
        builder: (BuildContext context) {
          return Container(key: root);
        },
      );
      addTearDown(
        () => rootEntry
          ..remove()
          ..dispose(),
      );

      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: Overlay(key: overlayKey, initialEntries: <OverlayEntry>[rootEntry]),
        ),
      );

      expect(find.byKey(root), findsOneWidget);

      final newEntry = OverlayEntry(
        builder: (BuildContext context) {
          return Container(key: top);
        },
      );
      addTearDown(
        () => newEntry
          ..remove()
          ..dispose(),
      );
      expect(newEntry.opaque, isFalse);
      newEntry.opaque = true; // Does neither trigger an assert nor throw.
      expect(newEntry.opaque, isTrue);

      // The new opaqueness is honored when inserted into an overlay.
      overlayKey.currentState!.insert(newEntry);
      await tester.pumpAndSettle();

      expect(find.byKey(root), findsNothing);
      expect(find.byKey(top), findsOneWidget);
    },
  );

  testWidgets('OverlayEntries do not rebuild when opaqueness changes', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/45797.

    final overlayKey = GlobalKey<OverlayState>();
    final Key bottom = UniqueKey();
    final Key middle = UniqueKey();
    final Key top = UniqueKey();
    final Widget bottomWidget = StatefulTestWidget(key: bottom);
    final Widget middleWidget = StatefulTestWidget(key: middle);
    final Widget topWidget = StatefulTestWidget(key: top);

    final bottomEntry = OverlayEntry(
      maintainState: true,
      builder: (BuildContext context) {
        return bottomWidget;
      },
    );
    addTearDown(
      () => bottomEntry
        ..remove()
        ..dispose(),
    );
    final middleEntry = OverlayEntry(
      maintainState: true,
      builder: (BuildContext context) {
        return middleWidget;
      },
    );
    addTearDown(
      () => middleEntry
        ..remove()
        ..dispose(),
    );
    final topEntry = OverlayEntry(
      maintainState: true,
      builder: (BuildContext context) {
        return topWidget;
      },
    );
    addTearDown(
      () => topEntry
        ..remove()
        ..dispose(),
    );

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(
          key: overlayKey,
          initialEntries: <OverlayEntry>[bottomEntry, middleEntry, topEntry],
        ),
      ),
    );

    // All widgets are onstage.
    expect(tester.state<StatefulTestState>(find.byKey(bottom)).rebuildCount, 1);
    expect(tester.state<StatefulTestState>(find.byKey(middle)).rebuildCount, 1);
    expect(tester.state<StatefulTestState>(find.byKey(top)).rebuildCount, 1);

    middleEntry.opaque = true;
    await tester.pump();

    // Bottom widget is offstage and did not rebuild.
    expect(find.byKey(bottom), findsNothing);
    expect(
      tester.state<StatefulTestState>(find.byKey(bottom, skipOffstage: false)).rebuildCount,
      1,
    );
    expect(tester.state<StatefulTestState>(find.byKey(middle)).rebuildCount, 1);
    expect(tester.state<StatefulTestState>(find.byKey(top)).rebuildCount, 1);
  });

  testWidgets('OverlayEntries do not rebuild when opaque entry is added', (
    WidgetTester tester,
  ) async {
    // Regression test for https://github.com/flutter/flutter/issues/45797.

    final overlayKey = GlobalKey<OverlayState>();
    final Key bottom = UniqueKey();
    final Key middle = UniqueKey();
    final Key top = UniqueKey();
    final Widget bottomWidget = StatefulTestWidget(key: bottom);
    final Widget middleWidget = StatefulTestWidget(key: middle);
    final Widget topWidget = StatefulTestWidget(key: top);

    final bottomEntry = OverlayEntry(
      maintainState: true,
      builder: (BuildContext context) {
        return bottomWidget;
      },
    );
    addTearDown(
      () => bottomEntry
        ..remove()
        ..dispose(),
    );
    final middleEntry = OverlayEntry(
      opaque: true,
      maintainState: true,
      builder: (BuildContext context) {
        return middleWidget;
      },
    );
    addTearDown(
      () => middleEntry
        ..remove()
        ..dispose(),
    );
    final topEntry = OverlayEntry(
      maintainState: true,
      builder: (BuildContext context) {
        return topWidget;
      },
    );
    addTearDown(
      () => topEntry
        ..remove()
        ..dispose(),
    );

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(key: overlayKey, initialEntries: <OverlayEntry>[bottomEntry, topEntry]),
      ),
    );

    // Both widgets are onstage.
    expect(tester.state<StatefulTestState>(find.byKey(bottom)).rebuildCount, 1);
    expect(tester.state<StatefulTestState>(find.byKey(top)).rebuildCount, 1);

    overlayKey.currentState!.rearrange(<OverlayEntry>[bottomEntry, middleEntry, topEntry]);
    await tester.pump();

    // Bottom widget is offstage and did not rebuild.
    expect(find.byKey(bottom), findsNothing);
    expect(
      tester.state<StatefulTestState>(find.byKey(bottom, skipOffstage: false)).rebuildCount,
      1,
    );
    expect(tester.state<StatefulTestState>(find.byKey(middle)).rebuildCount, 1);
    expect(tester.state<StatefulTestState>(find.byKey(top)).rebuildCount, 1);
  });

  testWidgets('entries below opaque entries are ignored for hit testing', (
    WidgetTester tester,
  ) async {
    final overlayKey = GlobalKey<OverlayState>();
    var bottomTapCount = 0;
    late final OverlayEntry baseEntry;
    addTearDown(
      () => baseEntry
        ..remove()
        ..dispose(),
    );

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(
          key: overlayKey,
          initialEntries: <OverlayEntry>[
            baseEntry = OverlayEntry(
              maintainState: true,
              builder: (BuildContext context) {
                return GestureDetector(
                  onTap: () {
                    bottomTapCount++;
                  },
                );
              },
            ),
          ],
        ),
      ),
    );

    expect(bottomTapCount, 0);
    await tester.tap(
      find.byKey(overlayKey),
      warnIfMissed: false,
    ); // gesture detector is translucent; no hit is registered between it and the render view
    expect(bottomTapCount, 1);

    late final OverlayEntry newEntry1;
    addTearDown(
      () => newEntry1
        ..remove()
        ..dispose(),
    );
    overlayKey.currentState!.insert(
      newEntry1 = OverlayEntry(
        maintainState: true,
        opaque: true,
        builder: (BuildContext context) {
          return Container();
        },
      ),
    );
    await tester.pump();

    // Bottom is offstage and does not receive tap events.
    expect(find.byType(GestureDetector), findsNothing);
    expect(find.byType(GestureDetector, skipOffstage: false), findsOneWidget);
    await tester.tap(
      find.byKey(overlayKey),
      warnIfMissed: false,
    ); // gesture detector is translucent; no hit is registered between it and the render view
    expect(bottomTapCount, 1);

    var topTapCount = 0;
    late final OverlayEntry newEntry2;
    addTearDown(
      () => newEntry2
        ..remove()
        ..dispose(),
    );
    overlayKey.currentState!.insert(
      newEntry2 = OverlayEntry(
        maintainState: true,
        opaque: true,
        builder: (BuildContext context) {
          return GestureDetector(
            onTap: () {
              topTapCount++;
            },
          );
        },
      ),
    );
    await tester.pump();

    expect(topTapCount, 0);
    await tester.tap(
      find.byKey(overlayKey),
      warnIfMissed: false,
    ); // gesture detector is translucent; no hit is registered between it and the render view
    expect(topTapCount, 1);
    expect(bottomTapCount, 1);
  });

  testWidgets('Semantics of entries below opaque entries are ignored', (WidgetTester tester) async {
    final semantics = SemanticsTester(tester);
    final overlayKey = GlobalKey<OverlayState>();
    late final OverlayEntry bottomEntry;
    addTearDown(
      () => bottomEntry
        ..remove()
        ..dispose(),
    );
    late final OverlayEntry topEntry;
    addTearDown(
      () => topEntry
        ..remove()
        ..dispose(),
    );

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(
          key: overlayKey,
          initialEntries: <OverlayEntry>[
            bottomEntry = OverlayEntry(
              maintainState: true,
              builder: (BuildContext context) {
                return const Text('bottom');
              },
            ),
            topEntry = OverlayEntry(
              maintainState: true,
              opaque: true,
              builder: (BuildContext context) {
                return const Text('top');
              },
            ),
          ],
        ),
      ),
    );
    expect(find.text('bottom'), findsNothing);
    expect(find.text('bottom', skipOffstage: false), findsOneWidget);
    expect(find.text('top'), findsOneWidget);
    expect(semantics, includesNodeWith(label: 'top'));
    expect(semantics, isNot(includesNodeWith(label: 'bottom')));

    semantics.dispose();
  });

  testWidgets('Can use Positioned within OverlayEntry', (WidgetTester tester) async {
    late final OverlayEntry baseEntry;
    addTearDown(
      () => baseEntry
        ..remove()
        ..dispose(),
    );

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(
          initialEntries: <OverlayEntry>[
            baseEntry = OverlayEntry(
              builder: (BuildContext context) {
                return const Positioned(left: 145, top: 123, child: Text('positioned child'));
              },
            ),
          ],
        ),
      ),
    );

    expect(tester.getTopLeft(find.text('positioned child')), const Offset(145, 123));
  });

  testWidgets('Overlay can set and update clipBehavior', (WidgetTester tester) async {
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(
          initialEntries: <OverlayEntry>[
            _buildOverlayEntry(
              (BuildContext context) => Positioned(left: 2000, right: 2500, child: Container()),
            ),
          ],
        ),
      ),
    );

    // By default, clipBehavior should be Clip.hardEdge
    final RenderObject renderObject = tester.renderObject(find.byType(Overlay));
    expect((renderObject as dynamic).clipBehavior, equals(Clip.hardEdge));

    for (final Clip clip in Clip.values) {
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: Overlay(
            initialEntries: <OverlayEntry>[
              _buildOverlayEntry((BuildContext context) => Container()),
            ],
            clipBehavior: clip,
          ),
        ),
      );

      expect((renderObject as dynamic).clipBehavior, clip);
      var visited = false;
      renderObject.visitChildren((RenderObject child) {
        visited = true;
        switch (clip) {
          case Clip.none:
            expect(renderObject.describeApproximatePaintClip(child), null);
          case Clip.hardEdge:
          case Clip.antiAlias:
          case Clip.antiAliasWithSaveLayer:
            expect(
              renderObject.describeApproximatePaintClip(child),
              const Rect.fromLTRB(0, 0, 800, 600),
            );
        }
      });
      expect(visited, true);
    }
  });

  testWidgets('Overlay always applies clip', (WidgetTester tester) async {
    late final OverlayEntry baseEntry;
    addTearDown(
      () => baseEntry
        ..remove()
        ..dispose(),
    );

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(
          initialEntries: <OverlayEntry>[
            baseEntry = OverlayEntry(
              builder: (BuildContext context) =>
                  Positioned(left: 10, right: 10, child: Container()),
            ),
          ],
        ),
      ),
    );
    final RenderObject renderObject = tester.renderObject(find.byType(Overlay));
    expect(
      (renderObject as dynamic).paint,
      paints
        ..save()
        ..clipRect(rect: const Rect.fromLTWH(0.0, 0.0, 800.0, 600.0))
        ..restore(),
    );
  });

  testWidgets('OverlayEntry throws if inserted to an invalid Overlay', (WidgetTester tester) async {
    await tester.pumpWidget(
      const Directionality(textDirection: TextDirection.ltr, child: Overlay()),
    );
    final OverlayState overlay = tester.state(find.byType(Overlay));
    final entry = OverlayEntry(builder: (BuildContext context) => const SizedBox());
    addTearDown(
      () => entry
        ..remove()
        ..dispose(),
    );
    expect(() => overlay.insert(entry), returnsNormally);

    // Throws when inserted to the same Overlay.
    expect(
      () => overlay.insert(entry),
      throwsA(
        isA<FlutterError>().having(
          (FlutterError error) => error.toString(),
          'toString()',
          allOf(
            contains('The specified entry is already present in the target Overlay.'),
            contains('The OverlayEntry was'),
            contains('The Overlay the OverlayEntry was trying to insert to was'),
          ),
        ),
      ),
    );

    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: SizedBox(child: Overlay()),
      ),
    );

    // Throws if inserted to an already disposed Overlay.
    expect(
      () => overlay.insert(entry),
      throwsA(
        isA<FlutterError>().having(
          (FlutterError error) => error.toString(),
          'toString()',
          allOf(
            contains('Attempted to insert an OverlayEntry to an already disposed Overlay.'),
            contains('The OverlayEntry was'),
            contains('The Overlay the OverlayEntry was trying to insert to was'),
          ),
        ),
      ),
    );

    final OverlayState newOverlay = tester.state(find.byType(Overlay));
    // Throws when inserted to a different Overlay without calling remove.
    expect(
      () => newOverlay.insert(entry),
      throwsA(
        isA<FlutterError>().having(
          (FlutterError error) => error.toString(),
          'toString()',
          allOf(
            contains('The specified entry is already present in a different Overlay.'),
            contains('The OverlayEntry was'),
            contains('The Overlay the OverlayEntry was trying to insert to was'),
            contains("The OverlayEntry's current Overlay was"),
          ),
        ),
      ),
    );
  });

  group('OverlayEntry listenable', () {
    final GlobalKey overlayKey = GlobalKey();
    final Widget emptyOverlay = Directionality(
      textDirection: TextDirection.ltr,
      child: Overlay(key: overlayKey),
    );

    testWidgets('mounted state can be listened', (WidgetTester tester) async {
      await tester.pumpWidget(emptyOverlay);
      final overlay = overlayKey.currentState! as OverlayState;
      final mountedLog = <bool>[];
      final entry = OverlayEntry(builder: (BuildContext context) => Container());
      addTearDown(entry.dispose);

      entry.addListener(() {
        mountedLog.add(entry.mounted);
      });

      overlay.insert(entry);
      expect(mountedLog, isEmpty);

      // Pump a frame. The Overlay entry will be mounted.
      await tester.pump();
      expect(mountedLog, <bool>[true]);

      entry.remove();
      expect(mountedLog, <bool>[true]);
      await tester.pump();
      expect(mountedLog, <bool>[true, false]);

      // Insert & remove again.
      overlay.insert(entry);
      await tester.pump();
      entry.remove();
      await tester.pump();

      expect(mountedLog, <bool>[true, false, true, false]);
    });

    testWidgets('throw if disposed before removal', (WidgetTester tester) async {
      await tester.pumpWidget(emptyOverlay);
      final overlay = overlayKey.currentState! as OverlayState;
      final entry = OverlayEntry(builder: (BuildContext context) => Container());
      addTearDown(
        () => entry
          ..remove()
          ..dispose(),
      );

      overlay.insert(entry);
      Object? error;
      try {
        entry.dispose();
      } catch (e) {
        error = e;
      }

      expect(error, isAssertionError);
    });

    test('dispose works', () {
      final entry = OverlayEntry(builder: (BuildContext context) => Container());

      entry.dispose();
      expect(() => entry.addListener(() {}), throwsAssertionError);
    });

    testWidgets('delayed dispose', (WidgetTester tester) async {
      await tester.pumpWidget(emptyOverlay);
      final overlay = overlayKey.currentState! as OverlayState;
      final mountedLog = <bool>[];
      final entry = OverlayEntry(builder: (BuildContext context) => Container());
      entry.addListener(() {
        mountedLog.add(entry.mounted);
      });

      overlay.insert(entry);
      await tester.pump();
      expect(mountedLog, <bool>[true]);

      entry.remove();
      // Call dispose on the entry. The listeners should be notified for one
      // last time after this.
      entry.dispose();
      expect(mountedLog, <bool>[true]);
      await tester.pump();
      expect(mountedLog, <bool>[true, false]);
      expect(tester.takeException(), isNull);

      expect(() => entry.addListener(() {}), throwsAssertionError);
    });

    testWidgets('asserts when remove is called twice', (WidgetTester tester) async {
      await tester.pumpWidget(emptyOverlay);
      final overlay = overlayKey.currentState! as OverlayState;
      final entry = OverlayEntry(builder: (BuildContext context) => Container());
      addTearDown(entry.dispose);

      overlay.insert(entry);

      expect(
        () {
          entry.remove();
          entry.remove();
        },
        throwsA(
          isA<AssertionError>().having(
            (AssertionError e) => e.message,
            'message',
            'An OverlayEntry should be removed only once.',
          ),
        ),
      );
    });
  });

  group('LookupBoundary', () {
    testWidgets('hides Overlay from Overlay.maybeOf', (WidgetTester tester) async {
      OverlayState? overlay;
      late final OverlayEntry baseEntry;
      addTearDown(
        () => baseEntry
          ..remove()
          ..dispose(),
      );

      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: Overlay(
            initialEntries: <OverlayEntry>[
              baseEntry = OverlayEntry(
                builder: (BuildContext context) {
                  return LookupBoundary(
                    child: Builder(
                      builder: (BuildContext context) {
                        overlay = Overlay.maybeOf(context);
                        return Container();
                      },
                    ),
                  );
                },
              ),
            ],
          ),
        ),
      );

      expect(overlay, isNull);
    });

    testWidgets('hides Overlay from Overlay.of', (WidgetTester tester) async {
      late final OverlayEntry baseEntry;
      addTearDown(
        () => baseEntry
          ..remove()
          ..dispose(),
      );

      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: Overlay(
            initialEntries: <OverlayEntry>[
              baseEntry = OverlayEntry(
                builder: (BuildContext context) {
                  return LookupBoundary(
                    child: Builder(
                      builder: (BuildContext context) {
                        Overlay.of(context);
                        return Container();
                      },
                    ),
                  );
                },
              ),
            ],
          ),
        ),
      );
      final Object? exception = tester.takeException();
      expect(exception, isFlutterError);
      final error = exception! as FlutterError;

      expect(
        error.toStringDeep(),
        'FlutterError\n'
        '   No Overlay widget found within the closest LookupBoundary.\n'
        '   There is an ancestor Overlay widget, but it is hidden by a\n'
        '   LookupBoundary.\n'
        '   Some widgets require an Overlay widget ancestor for correct\n'
        '   operation.\n'
        '   The most common way to add an Overlay to an application is to\n'
        '   include a MaterialApp, CupertinoApp or Navigator widget in the\n'
        '   runApp() call.\n'
        '   The context from which that widget was searching for an overlay\n'
        '   was:\n'
        '     Builder\n',
      );
    });

    testWidgets('hides Overlay from debugCheckHasOverlay', (WidgetTester tester) async {
      late final OverlayEntry baseEntry;
      addTearDown(
        () => baseEntry
          ..remove()
          ..dispose(),
      );

      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: Overlay(
            initialEntries: <OverlayEntry>[
              baseEntry = OverlayEntry(
                builder: (BuildContext context) {
                  return LookupBoundary(
                    child: Builder(
                      builder: (BuildContext context) {
                        debugCheckHasOverlay(context);
                        return Container();
                      },
                    ),
                  );
                },
              ),
            ],
          ),
        ),
      );
      final Object? exception = tester.takeException();
      expect(exception, isFlutterError);
      final error = exception! as FlutterError;

      expect(
        error.toStringDeep(),
        startsWith(
          'FlutterError\n'
          '   No Overlay widget found within the closest LookupBoundary.\n'
          '   There is an ancestor Overlay widget, but it is hidden by a\n'
          '   LookupBoundary.\n'
          '   Builder widgets require an Overlay widget ancestor within the\n'
          '   closest LookupBoundary.\n'
          '   An overlay lets widgets float on top of other widget children.\n'
          '   To introduce an Overlay widget, you can either directly include\n'
          '   one, or use a widget that contains an Overlay itself, such as a\n'
          '   Navigator, WidgetApp, MaterialApp, or CupertinoApp.\n'
          '   The specific widget that could not find a Overlay ancestor was:\n'
          '     Builder\n'
          '   The ancestors of this widget were:\n'
          '     LookupBoundary\n',
        ),
      );
    });
  });

  testWidgets('Overlay.wrap', (WidgetTester tester) async {
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay.wrap(child: const Center(child: Text('Hello World'))),
      ),
    );

    final State overlayState = tester.state(find.byType(Overlay));
    expect(find.text('Hello World'), findsOneWidget);
    expect(find.text('Bye, bye'), findsNothing);

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay.wrap(child: const Center(child: Text('Bye, bye'))),
      ),
    );

    expect(find.text('Hello World'), findsNothing);
    expect(find.text('Bye, bye'), findsOneWidget);
    expect(tester.state(find.byType(Overlay)), same(overlayState));
  });

  testWidgets('Overlay.wrap is sized by child in an unconstrained environment', (
    WidgetTester tester,
  ) async {
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: UnconstrainedBox(
          child: Overlay.wrap(child: const Center(child: SizedBox(width: 123, height: 456))),
        ),
      ),
    );

    expect(tester.getSize(find.byType(Overlay)), const Size(123, 456));
  });

  testWidgets('Overlay is sized by child in an unconstrained environment', (
    WidgetTester tester,
  ) async {
    final initialEntry = OverlayEntry(
      opaque: true,
      canSizeOverlay: true,
      builder: (BuildContext context) {
        return const SizedBox(width: 123, height: 456);
      },
    );
    addTearDown(
      () => initialEntry
        ..remove()
        ..dispose(),
    );

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: UnconstrainedBox(child: Overlay(initialEntries: <OverlayEntry>[initialEntry])),
      ),
    );

    expect(tester.getSize(find.byType(Overlay)), const Size(123, 456));

    final OverlayState overlay = tester.state<OverlayState>(find.byType(Overlay));

    final nonSizingEntry = OverlayEntry(
      builder: (BuildContext context) {
        return const SizedBox(width: 600, height: 600, child: Center(child: Text('Hello')));
      },
    );
    addTearDown(nonSizingEntry.dispose);

    overlay.insert(nonSizingEntry);
    await tester.pump();
    expect(tester.getSize(find.byType(Overlay)), const Size(123, 456));
    expect(find.text('Hello'), findsOneWidget);

    final sizingEntry = OverlayEntry(
      canSizeOverlay: true,
      builder: (BuildContext context) {
        return const SizedBox(width: 222, height: 111, child: Center(child: Text('World')));
      },
    );
    addTearDown(sizingEntry.dispose);

    overlay.insert(sizingEntry);
    await tester.pump();
    expect(tester.getSize(find.byType(Overlay)), const Size(222, 111));
    expect(find.text('Hello'), findsOneWidget);
    expect(find.text('World'), findsOneWidget);

    nonSizingEntry.remove();
    await tester.pump();
    expect(tester.getSize(find.byType(Overlay)), const Size(222, 111));
    expect(find.text('Hello'), findsNothing);
    expect(find.text('World'), findsOneWidget);

    sizingEntry.remove();
    await tester.pump();
    expect(tester.getSize(find.byType(Overlay)), const Size(123, 456));
    expect(find.text('Hello'), findsNothing);
    expect(find.text('World'), findsNothing);
  });

  testWidgets('Overlay throws if unconstrained and has no child', (WidgetTester tester) async {
    final errors = <FlutterErrorDetails>[];
    final FlutterExceptionHandler? oldHandler = FlutterError.onError;
    FlutterError.onError = errors.add;

    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: UnconstrainedBox(child: Overlay()),
      ),
    );
    FlutterError.onError = oldHandler;

    expect(
      errors.first.toString().replaceAll('\n', ' '),
      contains('Overlay was given infinite constraints and cannot be sized by a suitable child.'),
    );
  });

  testWidgets('Overlay throws if unconstrained and only positioned child', (
    WidgetTester tester,
  ) async {
    final errors = <FlutterErrorDetails>[];
    final FlutterExceptionHandler? oldHandler = FlutterError.onError;
    FlutterError.onError = errors.add;

    final entry = OverlayEntry(
      canSizeOverlay: true,
      builder: (BuildContext context) {
        return const Positioned(top: 100, child: SizedBox(width: 600, height: 600));
      },
    );
    addTearDown(
      () => entry
        ..remove()
        ..dispose(),
    );

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: UnconstrainedBox(child: Overlay(initialEntries: <OverlayEntry>[entry])),
      ),
    );
    FlutterError.onError = oldHandler;

    expect(
      errors.first.toString().replaceAll('\n', ' '),
      contains('Overlay was given infinite constraints and cannot be sized by a suitable child.'),
    );
  });

  testWidgets('Overlay throws if unconstrained and no canSizeOverlay child', (
    WidgetTester tester,
  ) async {
    final errors = <FlutterErrorDetails>[];
    final FlutterExceptionHandler? oldHandler = FlutterError.onError;
    FlutterError.onError = errors.add;

    final entry = OverlayEntry(
      builder: (BuildContext context) {
        return const SizedBox(width: 600, height: 600);
      },
    );
    addTearDown(
      () => entry
        ..remove()
        ..dispose(),
    );

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: UnconstrainedBox(child: Overlay(initialEntries: <OverlayEntry>[entry])),
      ),
    );
    FlutterError.onError = oldHandler;

    expect(
      errors.first.toString().replaceAll('\n', ' '),
      contains('Overlay was given infinite constraints and cannot be sized by a suitable child.'),
    );
  });

  testWidgets(
    'Overlay.wrap with alwaysSizeToContent is sized by child in loose constraint environment',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: UnconstrainedBox(
            child: ConstrainedBox(
              constraints: BoxConstraints.loose(const Size(800, 600)),
              child: Overlay.wrap(
                alwaysSizeToContent: true,
                child: const SizedBox(width: 123, height: 456),
              ),
            ),
          ),
        ),
      );

      expect(tester.getSize(find.byType(Overlay)), const Size(123, 456));
    },
  );

  testWidgets('Overlay with alwaysSizeToContent throws without sizing child', (
    WidgetTester tester,
  ) async {
    final errors = <FlutterErrorDetails>[];
    final FlutterExceptionHandler? oldHandler = FlutterError.onError;
    FlutterError.onError = errors.add;

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: UnconstrainedBox(
          child: ConstrainedBox(
            constraints: BoxConstraints.loose(const Size(800, 600)),
            child: const Overlay(alwaysSizeToContent: true),
          ),
        ),
      ),
    );
    FlutterError.onError = oldHandler;

    expect(
      errors.first.toString().replaceAll('\n', ' '),
      contains('Overlay was asked to size itself to content but does not have a suitable child.'),
    );
  });

  testWidgets('Overlay is not visible from sub-views', (WidgetTester tester) async {
    OverlayState? outsideView;
    OverlayState? insideView;
    OverlayState? outsideViewAnchor;

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay.wrap(
          child: Builder(
            builder: (BuildContext context) {
              outsideViewAnchor = Overlay.maybeOf(context);
              return ViewAnchor(
                view: Builder(
                  builder: (BuildContext context) {
                    outsideView = Overlay.maybeOf(context);
                    return View(
                      view: FakeView(tester.view),
                      child: Builder(
                        builder: (BuildContext context) {
                          insideView = Overlay.maybeOf(context);
                          return const SizedBox();
                        },
                      ),
                    );
                  },
                ),
                child: const SizedBox(),
              );
            },
          ),
        ),
      ),
    );

    expect(outsideViewAnchor, isNotNull);
    expect(outsideView, isNull);
    expect(insideView, isNull);
  });

  testWidgets('Overlay does not crash at zero area', (WidgetTester tester) async {
    final overlayEntry1 = OverlayEntry(builder: (_) => const Text('X'));
    final overlayEntry2 = OverlayEntry(builder: (_) => const Text('Y'));
    addTearDown(
      () => overlayEntry1
        ..remove()
        ..dispose(),
    );
    addTearDown(
      () => overlayEntry2
        ..remove()
        ..dispose(),
    );
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Center(
          child: SizedBox.shrink(child: Overlay(initialEntries: [overlayEntry1, overlayEntry2])),
        ),
      ),
    );
    expect(tester.getSize(find.byType(Overlay)), Size.zero);
  });
}

class StatefulTestWidget extends StatefulWidget {
  const StatefulTestWidget({super.key});

  @override
  State<StatefulTestWidget> createState() => StatefulTestState();
}

class StatefulTestState extends State<StatefulTestWidget> {
  int rebuildCount = 0;

  @override
  Widget build(BuildContext context) {
    rebuildCount += 1;
    return Container();
  }
}

class FakeBuildContext extends BuildContext {
  bool called = false;

  @override
  bool get debugDoingBuild => throw UnimplementedError();

  @override
  InheritedWidget dependOnInheritedElement(InheritedElement ancestor, {Object? aspect}) {
    throw UnimplementedError();
  }

  @override
  T? dependOnInheritedWidgetOfExactType<T extends InheritedWidget>({Object? aspect}) {
    throw UnimplementedError();
  }

  @override
  DiagnosticsNode describeElement(
    String name, {
    DiagnosticsTreeStyle style = DiagnosticsTreeStyle.errorProperty,
  }) {
    throw UnimplementedError();
  }

  @override
  List<DiagnosticsNode> describeMissingAncestor({required Type expectedAncestorType}) {
    throw UnimplementedError();
  }

  @override
  DiagnosticsNode describeOwnershipChain(String name) {
    throw UnimplementedError();
  }

  @override
  DiagnosticsNode describeWidget(
    String name, {
    DiagnosticsTreeStyle style = DiagnosticsTreeStyle.errorProperty,
  }) {
    throw UnimplementedError();
  }

  @override
  void dispatchNotification(Notification notification) {}

  @override
  T? findAncestorRenderObjectOfType<T extends RenderObject>() {
    throw UnimplementedError();
  }

  @override
  T? findAncestorStateOfType<T extends State<StatefulWidget>>() {
    throw UnimplementedError();
  }

  @override
  T? findAncestorWidgetOfExactType<T extends Widget>() {
    throw UnimplementedError();
  }

  @override
  RenderObject? findRenderObject() {
    throw UnimplementedError();
  }

  @override
  T? findRootAncestorStateOfType<T extends State<StatefulWidget>>() {
    throw UnimplementedError();
  }

  @override
  InheritedElement? getElementForInheritedWidgetOfExactType<T extends InheritedWidget>() {
    called = true;
    return null;
  }

  @override
  T? getInheritedWidgetOfExactType<T extends InheritedWidget>() {
    throw UnimplementedError();
  }

  @override
  bool get mounted => throw UnimplementedError();

  @override
  BuildOwner? get owner => throw UnimplementedError();

  @override
  Size? get size => throw UnimplementedError();

  @override
  void visitAncestorElements(ConditionalElementVisitor visitor) {}

  @override
  void visitChildElements(ElementVisitor visitor) {}

  @override
  Widget get widget => throw UnimplementedError();
}

/// This helper makes leak tracker forgiving the entry is not disposed.
OverlayEntry _buildOverlayEntry(WidgetBuilder builder) => OverlayEntry(builder: builder);
