// 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 'semantics_tester.dart';

void main() {
  testWidgets('OverflowEntries context contains Overlay', (WidgetTester tester) async {
    final GlobalKey overlayKey = GlobalKey();
    bool didBuild = false;
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(
          key: overlayKey,
          initialEntries: <OverlayEntry>[
            OverlayEntry(
              builder: (BuildContext context) {
                didBuild = true;
                final Overlay overlay = context.findAncestorWidgetOfExactType<Overlay>()!;
                expect(overlay.key, equals(overlayKey));
                return Container();
              },
            ),
            OverlayEntry(
              builder: (BuildContext context) => Container(),
            ),
          ],
        ),
      ),
    );
    expect(didBuild, isTrue);
    final RenderObject theater = overlayKey.currentContext!.findRenderObject()!;

    expect(theater, hasAGoodToStringDeep);
    expect(
      theater.toStringDeep(minLevel: DiagnosticLevel.info),
      equalsIgnoringHashCodes(
        '_RenderTheatre#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();
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(
          key: overlayKey,
          initialEntries: <OverlayEntry>[
            OverlayEntry(
              opaque: true,
              maintainState: true,
              builder: (BuildContext context) => Container(),
            ),
            OverlayEntry(
              opaque: true,
              maintainState: true,
              builder: (BuildContext context) => Container(),
            ),
            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(
        '_RenderTheatre#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',
      ),
    );
  });

  testWidgets('insert top', (WidgetTester tester) async {
    final GlobalKey overlayKey = GlobalKey();
    final List<String> buildOrder = <String>[];
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(
          key: overlayKey,
          initialEntries: <OverlayEntry>[
            OverlayEntry(
              builder: (BuildContext context) {
                buildOrder.add('Base');
                return Container();
              },
            ),
          ],
        ),
      ),
    );

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

    buildOrder.clear();
    final OverlayState overlay = overlayKey.currentState! as OverlayState;
    overlay.insert(
      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();
    OverlayEntry base;
    final List<String> buildOrder = <String>[];
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(
          key: overlayKey,
          initialEntries: <OverlayEntry>[
            base = OverlayEntry(
              builder: (BuildContext context) {
                buildOrder.add('Base');
                return Container();
              },
            ),
          ],
        ),
      ),
    );

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

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

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

  testWidgets('insert above', (WidgetTester tester) async {
    final GlobalKey overlayKey = GlobalKey();
    OverlayEntry base;
    final List<String> buildOrder = <String>[];
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(
          key: overlayKey,
          initialEntries: <OverlayEntry>[
            base = OverlayEntry(
              builder: (BuildContext context) {
                buildOrder.add('Base');
                return Container();
              },
            ),
            OverlayEntry(
              builder: (BuildContext context) {
                buildOrder.add('Top');
                return Container();
              },
            ),
          ],
        ),
      ),
    );

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

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

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

  testWidgets('insertAll top', (WidgetTester tester) async {
    final GlobalKey overlayKey = GlobalKey();
    final List<String> buildOrder = <String>[];
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(
          key: overlayKey,
          initialEntries: <OverlayEntry>[
            OverlayEntry(
              builder: (BuildContext context) {
                buildOrder.add('Base');
                return Container();
              },
            ),
          ],
        ),
      ),
    );

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

    final List<OverlayEntry> entries = <OverlayEntry>[
      OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add('New1');
          return Container();
        },
      ),
      OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add('New2');
          return Container();
        },
      ),
    ];

    buildOrder.clear();
    final OverlayState 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();
    OverlayEntry base;
    final List<String> buildOrder = <String>[];
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(
          key: overlayKey,
          initialEntries: <OverlayEntry>[
            base = OverlayEntry(
              builder: (BuildContext context) {
                buildOrder.add('Base');
                return Container();
              },
            ),
          ],
        ),
      ),
    );

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

    final List<OverlayEntry> entries = <OverlayEntry>[
      OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add('New1');
          return Container();
        },
      ),
      OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add('New2');
          return Container();
        },
      ),
    ];

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

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

  testWidgets('insertAll above', (WidgetTester tester) async {
    final GlobalKey overlayKey = GlobalKey();
    final List<String> buildOrder = <String>[];
    OverlayEntry base;
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(
          key: overlayKey,
          initialEntries: <OverlayEntry>[
            base = OverlayEntry(
              builder: (BuildContext context) {
                buildOrder.add('Base');
                return Container();
              },
            ),
            OverlayEntry(
              builder: (BuildContext context) {
                buildOrder.add('Top');
                return Container();
              },
            ),
          ],
        ),
      ),
    );

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

    final List<OverlayEntry> entries = <OverlayEntry>[
      OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add('New1');
          return Container();
        },
      ),
      OverlayEntry(
        builder: (BuildContext context) {
          buildOrder.add('New2');
          return Container();
        },
      ),
    ];

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

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

  testWidgets('rearrange', (WidgetTester tester) async {
    final GlobalKey overlayKey = GlobalKey();
    final List<int> buildOrder = <int>[];
    final List<OverlayEntry> 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();
        },
      ),
    ];

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

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

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

    buildOrder.clear();
    final OverlayState 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 List<int> buildOrder = <int>[];
    final List<OverlayEntry> 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();
        },
      ),
    ];

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

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

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

    buildOrder.clear();
    final OverlayState 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 List<int> buildOrder = <int>[];
    final List<OverlayEntry> 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();
        },
      ),
    ];

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

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

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

    buildOrder.clear();
    final OverlayState 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();
    OverlayEntry base;

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

    final OverlayState overlay = overlayKey.currentState! as OverlayState;

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

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

    try {
      overlay.insert(
        OverlayEntry(builder: (BuildContext context) {
          return Container();
        }),
        above: OverlayEntry(
          builder: (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: OverlayEntry(
        builder: (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() called without Overlay being 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 or Navigator widget in the 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 or Navigator widget in the 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('OverlayEntry.opaque can be changed when OverlayEntry is not part of an Overlay (yet)', (WidgetTester tester) async {
    final GlobalKey<OverlayState> overlayKey = GlobalKey<OverlayState>();
    final Key root = UniqueKey();
    final Key top = UniqueKey();
    final OverlayEntry rootEntry = OverlayEntry(
      builder: (BuildContext context) {
        return Container(key: root);
      },
    );

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

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

    final OverlayEntry newEntry = OverlayEntry(
      builder: (BuildContext context) {
        return Container(key: top);
      },
    );
    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 GlobalKey<OverlayState> 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 OverlayEntry bottomEntry = OverlayEntry(
      maintainState: true,
      builder: (BuildContext context) {
        return bottomWidget;
      },
    );
    final OverlayEntry middleEntry = OverlayEntry(
      maintainState: true,
      builder: (BuildContext context) {
        return middleWidget;
      },
    );
    final OverlayEntry topEntry = OverlayEntry(
      maintainState: true,
      builder: (BuildContext context) {
        return topWidget;
      },
    );

    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 GlobalKey<OverlayState> 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 OverlayEntry bottomEntry = OverlayEntry(
      maintainState: true,
      builder: (BuildContext context) {
        return bottomWidget;
      },
    );
    final OverlayEntry middleEntry = OverlayEntry(
      opaque: true,
      maintainState: true,
      builder: (BuildContext context) {
        return middleWidget;
      },
    );
    final OverlayEntry topEntry = OverlayEntry(
      maintainState: true,
      builder: (BuildContext context) {
        return topWidget;
      },
    );

    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 GlobalKey<OverlayState> overlayKey = GlobalKey<OverlayState>();
    int bottomTapCount = 0;
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(
          key: overlayKey,
          initialEntries: <OverlayEntry>[
            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);

    overlayKey.currentState!.insert(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);

    int topTapCount = 0;
    overlayKey.currentState!.insert(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 SemanticsTester semantics = SemanticsTester(tester);
    final GlobalKey<OverlayState> overlayKey = GlobalKey<OverlayState>();
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(
          key: overlayKey,
          initialEntries: <OverlayEntry>[
            OverlayEntry(
              maintainState: true,
              builder: (BuildContext context) {
                return const Text('bottom');
              },
            ),
            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 {
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Overlay(
          initialEntries: <OverlayEntry>[
            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>[
            OverlayEntry(
              builder: (BuildContext context) => Container(),
            ),
          ],
        ),
      ),
    );

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

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

class StatefulTestWidget extends StatefulWidget {
  const StatefulTestWidget({Key? key}) : super(key: key);

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

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

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