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

void main() {
  group('LookupBoundary.dependOnInheritedWidgetOfExactType', () {
    testWidgets('respects boundary', (WidgetTester tester) async {
      InheritedWidget? containerThroughBoundary;
      InheritedWidget? containerStoppedAtBoundary;

      final Key inheritedKey = UniqueKey();

      await tester.pumpWidget(MyInheritedWidget(
        value: 2,
        key: inheritedKey,
        child: LookupBoundary(
          child: Builder(
            builder: (BuildContext context) {
              containerThroughBoundary = context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>();
              containerStoppedAtBoundary = LookupBoundary.dependOnInheritedWidgetOfExactType<MyInheritedWidget>(context);
              return const SizedBox.expand();
            },
          ),
        ),
      ));

      expect(containerThroughBoundary, equals(tester.widget(find.byKey(inheritedKey))));
      expect(containerStoppedAtBoundary, isNull);
    });

    testWidgets('ignores ancestor boundary', (WidgetTester tester) async {
      InheritedWidget? inheritedWidget;

      final Key inheritedKey = UniqueKey();

      await tester.pumpWidget(LookupBoundary(
        child: MyInheritedWidget(
          value: 2,
          key: inheritedKey,
          child: Builder(
            builder: (BuildContext context) {
              inheritedWidget = LookupBoundary.dependOnInheritedWidgetOfExactType<MyInheritedWidget>(context);
              return const SizedBox.expand();
            },
          ),
        ),
      ));

      expect(inheritedWidget, equals(tester.widget(find.byKey(inheritedKey))));
    });

    testWidgets('finds widget before boundary', (WidgetTester tester) async {
      InheritedWidget? containerThroughBoundary;
      InheritedWidget? containerStoppedAtBoundary;

      final Key inheritedKey = UniqueKey();

      await tester.pumpWidget(MyInheritedWidget(
        value: 2,
        child: LookupBoundary(
          child: MyInheritedWidget(
            key: inheritedKey,
            value: 1,
            child: Builder(
              builder: (BuildContext context) {
                containerThroughBoundary = context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>();
                containerStoppedAtBoundary = LookupBoundary.dependOnInheritedWidgetOfExactType<MyInheritedWidget>(context);
                return const SizedBox.expand();
              },
            ),
          ),
        ),
      ));

      expect(containerThroughBoundary, equals(tester.widget(find.byKey(inheritedKey))));
      expect(containerStoppedAtBoundary, equals(tester.widget(find.byKey(inheritedKey))));
    });

    testWidgets('creates dependency', (WidgetTester tester) async {
      MyInheritedWidget? inheritedWidget;

      final Widget widgetTree = DidChangeDependencySpy(
        onDidChangeDependencies: (BuildContext context) {
          inheritedWidget = LookupBoundary.dependOnInheritedWidgetOfExactType<MyInheritedWidget>(context);
        },
      );

      await tester.pumpWidget(
        MyInheritedWidget(
          value: 1,
          child: widgetTree,
        ),
      );
      expect(inheritedWidget!.value, 1);
      expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);

      await tester.pumpWidget(
        MyInheritedWidget(
          value: 2,
          child: widgetTree,
        ),
      );
      expect(inheritedWidget!.value, 2);
      expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 2);
    });

    testWidgets('causes didChangeDependencies to be called on move even if dependency was not fulfilled due to boundary', (WidgetTester tester) async {
      MyInheritedWidget? inheritedWidget;
      final Key globalKey = GlobalKey();

      final Widget widgetTree = DidChangeDependencySpy(
        key: globalKey,
        onDidChangeDependencies: (BuildContext context) {
          inheritedWidget = LookupBoundary.dependOnInheritedWidgetOfExactType<MyInheritedWidget>(context);
        },
      );

      await tester.pumpWidget(
        MyInheritedWidget(
          value: 1,
          child: LookupBoundary(
            child: widgetTree,
          ),
        ),
      );
      expect(inheritedWidget, isNull);
      expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);

      // Value of inherited widget changes, but there should be no dependency due to boundary.
      await tester.pumpWidget(
        MyInheritedWidget(
          value: 2,
          child: LookupBoundary(
            child: widgetTree,
          ),
        ),
      );
      expect(inheritedWidget, isNull);
      expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);

      // Widget is moved, didChangeDependencies is called, but dependency is still not found due to boundary.
      await tester.pumpWidget(
        SizedBox(
          child: MyInheritedWidget(
            value: 2,
            child: LookupBoundary(
              child: widgetTree,
            ),
          ),
        ),
      );
      expect(inheritedWidget, isNull);
      expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 2);

      await tester.pumpWidget(
        SizedBox(
          child: MyInheritedWidget(
            value: 2,
            child: LookupBoundary(
              child: MyInheritedWidget(
                value: 4,
                child: widgetTree,
              ),
            ),
          ),
        ),
      );
      expect(inheritedWidget!.value, 4);
      expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 3);
    });

    testWidgets('causes didChangeDependencies to be called on move even if dependency was non-existent', (WidgetTester tester) async {
      MyInheritedWidget? inheritedWidget;
      final Key globalKey = GlobalKey();

      final Widget widgetTree = DidChangeDependencySpy(
        key: globalKey,
        onDidChangeDependencies: (BuildContext context) {
          inheritedWidget = LookupBoundary.dependOnInheritedWidgetOfExactType<MyInheritedWidget>(context);
        },
      );

      await tester.pumpWidget(widgetTree);
      expect(inheritedWidget, isNull);
      expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);

      // Widget moved, didChangeDependencies must be called.
      await tester.pumpWidget(
        SizedBox(
          child: widgetTree,
        ),
      );
      expect(inheritedWidget, isNull);
      expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 2);

      // Widget moved, didChangeDependencies must be called.
      await tester.pumpWidget(
        MyInheritedWidget(
          value: 6,
          child: SizedBox(
            child: widgetTree,
          ),
        ),
      );
      expect(inheritedWidget!.value, 6);
      expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 3);
    });
  });

  group('LookupBoundary.getElementForInheritedWidgetOfExactType', () {
    testWidgets('respects boundary', (WidgetTester tester) async {
      InheritedElement? containerThroughBoundary;
      InheritedElement? containerStoppedAtBoundary;

      final Key inheritedKey = UniqueKey();

      await tester.pumpWidget(MyInheritedWidget(
        value: 2,
        key: inheritedKey,
        child: LookupBoundary(
          child: Builder(
            builder: (BuildContext context) {
              containerThroughBoundary = context.getElementForInheritedWidgetOfExactType<MyInheritedWidget>();
              containerStoppedAtBoundary = LookupBoundary.getElementForInheritedWidgetOfExactType<MyInheritedWidget>(context);
              return const SizedBox.expand();
            },
          ),
        ),
      ));

      expect(containerThroughBoundary, equals(tester.element(find.byKey(inheritedKey))));
      expect(containerStoppedAtBoundary, isNull);
    });

    testWidgets('ignores ancestor boundary', (WidgetTester tester) async {
      InheritedElement? inheritedWidget;

      final Key inheritedKey = UniqueKey();

      await tester.pumpWidget(LookupBoundary(
        child: MyInheritedWidget(
          value: 2,
          key: inheritedKey,
          child: Builder(
            builder: (BuildContext context) {
              inheritedWidget = LookupBoundary.getElementForInheritedWidgetOfExactType<MyInheritedWidget>(context);
              return const SizedBox.expand();
            },
          ),
        ),
      ));

      expect(inheritedWidget, equals(tester.element(find.byKey(inheritedKey))));
    });

    testWidgets('finds widget before boundary', (WidgetTester tester) async {
      InheritedElement? containerThroughBoundary;
      InheritedElement? containerStoppedAtBoundary;

      final Key inheritedKey = UniqueKey();

      await tester.pumpWidget(MyInheritedWidget(
        value: 2,
        child: LookupBoundary(
          child: MyInheritedWidget(
            key: inheritedKey,
            value: 1,
            child: Builder(
              builder: (BuildContext context) {
                containerThroughBoundary = context.getElementForInheritedWidgetOfExactType<MyInheritedWidget>();
                containerStoppedAtBoundary = LookupBoundary.getElementForInheritedWidgetOfExactType<MyInheritedWidget>(context);
                return const SizedBox.expand();
              },
            ),
          ),
        ),
      ));

      expect(containerThroughBoundary, equals(tester.element(find.byKey(inheritedKey))));
      expect(containerStoppedAtBoundary, equals(tester.element(find.byKey(inheritedKey))));
    });

    testWidgets('does not creates dependency', (WidgetTester tester) async {

      final Widget widgetTree = DidChangeDependencySpy(
        onDidChangeDependencies: (BuildContext context) {
          LookupBoundary.getElementForInheritedWidgetOfExactType<MyInheritedWidget>(context);
        },
      );

      await tester.pumpWidget(
        MyInheritedWidget(
          value: 1,
          child: widgetTree,
        ),
      );
      expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);

      await tester.pumpWidget(
        MyInheritedWidget(
          value: 2,
          child: widgetTree,
        ),
      );
      expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);
    });

    testWidgets('does not cause didChangeDependencies to be called on move when found', (WidgetTester tester) async {
      final Key globalKey = GlobalKey();

      final Widget widgetTree = DidChangeDependencySpy(
        key: globalKey,
        onDidChangeDependencies: (BuildContext context) {
          LookupBoundary.getElementForInheritedWidgetOfExactType<MyInheritedWidget>(context);
        },
      );

      await tester.pumpWidget(
        MyInheritedWidget(
          value: 1,
          child: LookupBoundary(
            child: widgetTree,
          ),
        ),
      );
      expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);

      // Value of inherited widget changes, but there should be no dependency due to boundary.
      await tester.pumpWidget(
        MyInheritedWidget(
          value: 2,
          child: LookupBoundary(
            child: widgetTree,
          ),
        ),
      );
      expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);

      // Widget is moved, didChangeDependencies is called, but dependency is still not found due to boundary.
      await tester.pumpWidget(
        SizedBox(
          child: MyInheritedWidget(
            value: 2,
            child: LookupBoundary(
              child: widgetTree,
            ),
          ),
        ),
      );
      expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);

      await tester.pumpWidget(
        SizedBox(
          child: MyInheritedWidget(
            value: 2,
            child: LookupBoundary(
              child: MyInheritedWidget(
                value: 4,
                child: widgetTree,
              ),
            ),
          ),
        ),
      );
      expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);
    });

    testWidgets('does not cause didChangeDependencies to be called on move when nothing was found', (WidgetTester tester) async {
      final Key globalKey = GlobalKey();

      final Widget widgetTree = DidChangeDependencySpy(
        key: globalKey,
        onDidChangeDependencies: (BuildContext context) {
          LookupBoundary.getElementForInheritedWidgetOfExactType<MyInheritedWidget>(context);
        },
      );

      await tester.pumpWidget(widgetTree);
      expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);

      // Widget moved, didChangeDependencies must be called.
      await tester.pumpWidget(
        SizedBox(
          child: widgetTree,
        ),
      );
      expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);

      // Widget moved, didChangeDependencies must be called.
      await tester.pumpWidget(
        MyInheritedWidget(
          value: 6,
          child: SizedBox(
            child: widgetTree,
          ),
        ),
      );
      expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);
    });
  });

  group('LookupBoundary.findAncestorWidgetOfExactType', () {
    testWidgets('respects boundary', (WidgetTester tester) async {
      Widget? containerThroughBoundary;
      Widget? containerStoppedAtBoundary;
      Widget? boundaryThroughBoundary;
      Widget? boundaryStoppedAtBoundary;

      final Key containerKey = UniqueKey();
      final Key boundaryKey = UniqueKey();

      await tester.pumpWidget(Container(
        key: containerKey,
        child: LookupBoundary(
          key: boundaryKey,
          child: Builder(
            builder: (BuildContext context) {
              containerThroughBoundary = context.findAncestorWidgetOfExactType<Container>();
              containerStoppedAtBoundary = LookupBoundary.findAncestorWidgetOfExactType<Container>(context);
              boundaryThroughBoundary = context.findAncestorWidgetOfExactType<LookupBoundary>();
              boundaryStoppedAtBoundary = LookupBoundary.findAncestorWidgetOfExactType<LookupBoundary>(context);
              return const SizedBox.expand();
            },
          ),
        ),
      ));

      expect(containerThroughBoundary, equals(tester.widget(find.byKey(containerKey))));
      expect(containerStoppedAtBoundary, isNull);
      expect(boundaryThroughBoundary, equals(tester.widget(find.byKey(boundaryKey))));
      expect(boundaryStoppedAtBoundary, equals(tester.widget(find.byKey(boundaryKey))));
    });

    testWidgets('finds right widget before boundary', (WidgetTester tester) async {
      Widget? containerThroughBoundary;
      Widget? containerStoppedAtBoundary;

      final Key outerContainerKey = UniqueKey();
      final Key innerContainerKey = UniqueKey();

      await tester.pumpWidget(Container(
        key: outerContainerKey,
        child: LookupBoundary(
          child: Container(
            padding: const EdgeInsets.all(10),
            color: Colors.blue,
            child: Container(
              key: innerContainerKey,
              child: Builder(
                builder: (BuildContext context) {
                  containerThroughBoundary = context.findAncestorWidgetOfExactType<Container>();
                  containerStoppedAtBoundary = LookupBoundary.findAncestorWidgetOfExactType<Container>(context);
                  return const SizedBox.expand();
                },
              ),
            ),
          ),
        ),
      ));

      expect(containerThroughBoundary, equals(tester.widget(find.byKey(innerContainerKey))));
      expect(containerStoppedAtBoundary, equals(tester.widget(find.byKey(innerContainerKey))));
    });

    testWidgets('works if nothing is found', (WidgetTester tester) async {
      Widget? containerStoppedAtBoundary;

      await tester.pumpWidget(Builder(
        builder: (BuildContext context) {
          containerStoppedAtBoundary = LookupBoundary.findAncestorWidgetOfExactType<Container>(context);
          return const SizedBox.expand();
        },
      ));

      expect(containerStoppedAtBoundary, isNull);
    });

    testWidgets('does not establish a dependency', (WidgetTester tester) async {
      Widget? containerThroughBoundary;
      Widget? containerStoppedAtBoundary;
      Widget? containerStoppedAtBoundaryUnfulfilled;

      final Key innerContainerKey = UniqueKey();
      final Key globalKey = GlobalKey();

      final Widget widgetTree = LookupBoundary(
        child: Container(
          key: innerContainerKey,
          child: DidChangeDependencySpy(
            key: globalKey,
            onDidChangeDependencies: (BuildContext context) {
              containerThroughBoundary = context.findAncestorWidgetOfExactType<Container>();
              containerStoppedAtBoundary = LookupBoundary.findAncestorWidgetOfExactType<Container>(context);
              containerStoppedAtBoundaryUnfulfilled = LookupBoundary.findAncestorWidgetOfExactType<Material>(context);
            },
          ),
        ),
      );

      await tester.pumpWidget(widgetTree);

      expect(containerThroughBoundary, equals(tester.widget(find.byKey(innerContainerKey))));
      expect(containerStoppedAtBoundary, equals(tester.widget(find.byKey(innerContainerKey))));
      expect(containerStoppedAtBoundaryUnfulfilled, isNull);
      expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);

      await tester.pumpWidget(
        SizedBox( // Changes tree structure, triggers global key move of DidChangeDependencySpy.
          child: widgetTree,
        ),
      );

      // Tree restructuring above would have called didChangeDependencies if dependency had been established.
      expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);
    });
  });

  group('LookupBoundary.findAncestorStateOfType', () {
    testWidgets('respects boundary', (WidgetTester tester) async {
      State? containerThroughBoundary;
      State? containerStoppedAtBoundary;

      final Key containerKey = UniqueKey();

      await tester.pumpWidget(MyStatefulContainer(
        key: containerKey,
        child: LookupBoundary(
          child: Builder(
            builder: (BuildContext context) {
              containerThroughBoundary = context.findAncestorStateOfType<MyStatefulContainerState>();
              containerStoppedAtBoundary = LookupBoundary.findAncestorStateOfType<MyStatefulContainerState>(context);
              return const SizedBox.expand();
            },
          ),
        ),
      ));

      expect(containerThroughBoundary, equals(tester.state(find.byKey(containerKey))));
      expect(containerStoppedAtBoundary, isNull);
    });

    testWidgets('finds right widget before boundary', (WidgetTester tester) async {
      State? containerThroughBoundary;
      State? containerStoppedAtBoundary;

      final Key outerContainerKey = UniqueKey();
      final Key innerContainerKey = UniqueKey();

      await tester.pumpWidget(MyStatefulContainer(
        key: outerContainerKey,
        child: LookupBoundary(
          child: MyStatefulContainer(
            child: MyStatefulContainer(
              key: innerContainerKey,
              child: Builder(
                builder: (BuildContext context) {
                  containerThroughBoundary = context.findAncestorStateOfType<MyStatefulContainerState>();
                  containerStoppedAtBoundary = LookupBoundary.findAncestorStateOfType<MyStatefulContainerState>(context);
                  return const SizedBox.expand();
                },
              ),
            ),
          ),
        ),
      ));

      expect(containerThroughBoundary, equals(tester.state(find.byKey(innerContainerKey))));
      expect(containerStoppedAtBoundary, equals(tester.state(find.byKey(innerContainerKey))));
    });

    testWidgets('works if nothing is found', (WidgetTester tester) async {
      State? containerStoppedAtBoundary;

      await tester.pumpWidget(Builder(
        builder: (BuildContext context) {
          containerStoppedAtBoundary = LookupBoundary.findAncestorStateOfType<MyStatefulContainerState>(context);
          return const SizedBox.expand();
        },
      ));

      expect(containerStoppedAtBoundary, isNull);
    });

    testWidgets('does not establish a dependency', (WidgetTester tester) async {
      State? containerThroughBoundary;
      State? containerStoppedAtBoundary;
      State? containerStoppedAtBoundaryUnfulfilled;

      final Key innerContainerKey = UniqueKey();
      final Key globalKey = GlobalKey();

      final Widget widgetTree = LookupBoundary(
        child: MyStatefulContainer(
          key: innerContainerKey,
          child: DidChangeDependencySpy(
            key: globalKey,
            onDidChangeDependencies: (BuildContext context) {
              containerThroughBoundary = context.findAncestorStateOfType<MyStatefulContainerState>();
              containerStoppedAtBoundary = LookupBoundary.findAncestorStateOfType<MyStatefulContainerState>(context);
              containerStoppedAtBoundaryUnfulfilled = LookupBoundary.findAncestorStateOfType<MyOtherStatefulContainerState>(context);
            },
          ),
        ),
      );

      await tester.pumpWidget(widgetTree);

      expect(containerThroughBoundary, equals(tester.state(find.byKey(innerContainerKey))));
      expect(containerStoppedAtBoundary, equals(tester.state(find.byKey(innerContainerKey))));
      expect(containerStoppedAtBoundaryUnfulfilled, isNull);
      expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);

      await tester.pumpWidget(
        SizedBox( // Changes tree structure, triggers global key move of DidChangeDependencySpy.
          child: widgetTree,
        ),
      );

      // Tree restructuring above would have called didChangeDependencies if dependency had been established.
      expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);
    });
  });

  group('LookupBoundary.findRootAncestorStateOfType', () {
    testWidgets('respects boundary', (WidgetTester tester) async {
      State? containerThroughBoundary;
      State? containerStoppedAtBoundary;

      final Key containerKey = UniqueKey();

      await tester.pumpWidget(MyStatefulContainer(
        key: containerKey,
        child: LookupBoundary(
          child: Builder(
            builder: (BuildContext context) {
              containerThroughBoundary = context.findRootAncestorStateOfType<MyStatefulContainerState>();
              containerStoppedAtBoundary = LookupBoundary.findRootAncestorStateOfType<MyStatefulContainerState>(context);
              return const SizedBox.expand();
            },
          ),
        ),
      ));

      expect(containerThroughBoundary, equals(tester.state(find.byKey(containerKey))));
      expect(containerStoppedAtBoundary, isNull);
    });

    testWidgets('finds right widget before boundary', (WidgetTester tester) async {
      State? containerThroughBoundary;
      State? containerStoppedAtBoundary;

      final Key outerContainerKey = UniqueKey();
      final Key innerContainerKey = UniqueKey();

      await tester.pumpWidget(MyStatefulContainer(
        key: outerContainerKey,
        child: LookupBoundary(
          child: MyStatefulContainer(
            key: innerContainerKey,
            child: MyStatefulContainer(
              child: Builder(
                builder: (BuildContext context) {
                  containerThroughBoundary = context.findRootAncestorStateOfType<MyStatefulContainerState>();
                  containerStoppedAtBoundary = LookupBoundary.findRootAncestorStateOfType<MyStatefulContainerState>(context);
                  return const SizedBox.expand();
                },
              ),
            ),
          ),
        ),
      ));

      expect(containerThroughBoundary, equals(tester.state(find.byKey(outerContainerKey))));
      expect(containerStoppedAtBoundary, equals(tester.state(find.byKey(innerContainerKey))));
    });

    testWidgets('works if nothing is found', (WidgetTester tester) async {
      State? containerStoppedAtBoundary;

      await tester.pumpWidget(Builder(
        builder: (BuildContext context) {
          containerStoppedAtBoundary = LookupBoundary.findRootAncestorStateOfType<MyStatefulContainerState>(context);
          return const SizedBox.expand();
        },
      ));

      expect(containerStoppedAtBoundary, isNull);
    });

    testWidgets('does not establish a dependency', (WidgetTester tester) async {
      State? containerThroughBoundary;
      State? containerStoppedAtBoundary;
      State? containerStoppedAtBoundaryUnfulfilled;

      final Key innerContainerKey = UniqueKey();
      final Key globalKey = GlobalKey();

      final Widget widgetTree = LookupBoundary(
        child: MyStatefulContainer(
          key: innerContainerKey,
          child: DidChangeDependencySpy(
            key: globalKey,
            onDidChangeDependencies: (BuildContext context) {
              containerThroughBoundary = context.findRootAncestorStateOfType<MyStatefulContainerState>();
              containerStoppedAtBoundary = LookupBoundary.findRootAncestorStateOfType<MyStatefulContainerState>(context);
              containerStoppedAtBoundaryUnfulfilled = LookupBoundary.findRootAncestorStateOfType<MyOtherStatefulContainerState>(context);
            },
          ),
        ),
      );

      await tester.pumpWidget(widgetTree);

      expect(containerThroughBoundary, equals(tester.state(find.byKey(innerContainerKey))));
      expect(containerStoppedAtBoundary, equals(tester.state(find.byKey(innerContainerKey))));
      expect(containerStoppedAtBoundaryUnfulfilled, isNull);
      expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);

      await tester.pumpWidget(
        SizedBox( // Changes tree structure, triggers global key move of DidChangeDependencySpy.
          child: widgetTree,
        ),
      );

      // Tree restructuring above would have called didChangeDependencies if dependency had been established.
      expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);
    });
  });

  group('LookupBoundary.findAncestorRenderObjectOfType', () {
    testWidgets('respects boundary', (WidgetTester tester) async {
      RenderPadding? paddingThroughBoundary;
      RenderPadding? passingStoppedAtBoundary;

      final Key paddingKey = UniqueKey();

      await tester.pumpWidget(Padding(
        padding: EdgeInsets.zero,
        key: paddingKey,
        child: LookupBoundary(
          child: Builder(
            builder: (BuildContext context) {
              paddingThroughBoundary = context.findAncestorRenderObjectOfType<RenderPadding>();
              passingStoppedAtBoundary = LookupBoundary.findAncestorRenderObjectOfType<RenderPadding>(context);
              return const SizedBox.expand();
            },
          ),
        ),
      ));

      expect(paddingThroughBoundary, equals(tester.renderObject(find.byKey(paddingKey))));
      expect(passingStoppedAtBoundary, isNull);
    });

    testWidgets('finds right widget before boundary', (WidgetTester tester) async {
      RenderPadding? paddingThroughBoundary;
      RenderPadding? paddingStoppedAtBoundary;

      final Key outerPaddingKey = UniqueKey();
      final Key innerPaddingKey = UniqueKey();

      await tester.pumpWidget(Padding(
        padding: EdgeInsets.zero,
        key: outerPaddingKey,
        child: LookupBoundary(
          child: Padding(
            padding: EdgeInsets.zero,
            child: Padding(
              padding: EdgeInsets.zero,
              key: innerPaddingKey,
              child: Builder(
                builder: (BuildContext context) {
                  paddingThroughBoundary = context.findAncestorRenderObjectOfType<RenderPadding>();
                  paddingStoppedAtBoundary = LookupBoundary.findAncestorRenderObjectOfType<RenderPadding>(context);
                  return const SizedBox.expand();
                },
              ),
            ),
          ),
        ),
      ));

      expect(paddingThroughBoundary, equals(tester.renderObject(find.byKey(innerPaddingKey))));
      expect(paddingStoppedAtBoundary, equals(tester.renderObject(find.byKey(innerPaddingKey))));
    });

    testWidgets('works if nothing is found', (WidgetTester tester) async {
      RenderPadding? paddingStoppedAtBoundary;

      await tester.pumpWidget(Builder(
        builder: (BuildContext context) {
          paddingStoppedAtBoundary = LookupBoundary.findAncestorRenderObjectOfType<RenderPadding>(context);
          return const SizedBox.expand();
        },
      ));

      expect(paddingStoppedAtBoundary, isNull);
    });

    testWidgets('does not establish a dependency', (WidgetTester tester) async {
      RenderPadding? paddingThroughBoundary;
      RenderPadding? paddingStoppedAtBoundary;
      RenderWrap? wrapStoppedAtBoundaryUnfulfilled;

      final Key innerPaddingKey = UniqueKey();
      final Key globalKey = GlobalKey();

      final Widget widgetTree = LookupBoundary(
        child: Padding(
          padding: EdgeInsets.zero,
          key: innerPaddingKey,
          child: DidChangeDependencySpy(
            key: globalKey,
            onDidChangeDependencies: (BuildContext context) {
              paddingThroughBoundary = context.findAncestorRenderObjectOfType<RenderPadding>();
              paddingStoppedAtBoundary = LookupBoundary.findAncestorRenderObjectOfType<RenderPadding>(context);
              wrapStoppedAtBoundaryUnfulfilled = LookupBoundary.findAncestorRenderObjectOfType<RenderWrap>(context);
            },
          ),
        ),
      );

      await tester.pumpWidget(widgetTree);

      expect(paddingThroughBoundary, equals(tester.renderObject(find.byKey(innerPaddingKey))));
      expect(paddingStoppedAtBoundary, equals(tester.renderObject(find.byKey(innerPaddingKey))));
      expect(wrapStoppedAtBoundaryUnfulfilled, isNull);
      expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);

      await tester.pumpWidget(
        SizedBox( // Changes tree structure, triggers global key move of DidChangeDependencySpy.
          child: widgetTree,
        ),
      );

      // Tree restructuring above would have called didChangeDependencies if dependency had been established.
      expect(tester.state<_DidChangeDependencySpyState>(find.byType(DidChangeDependencySpy)).didChangeDependenciesCount, 1);
    });
  });

  group('LookupBoundary.visitAncestorElements', () {
    testWidgets('respects boundary', (WidgetTester tester) async {
      final List<Element> throughBoundary = <Element>[];
      final List<Element> stoppedAtBoundary = <Element>[];
      final List<Element> stoppedAtBoundaryTerminatedEarly = <Element>[];

      final Key level0 = UniqueKey();
      final Key level1 = UniqueKey();
      final Key level2 = UniqueKey();
      final Key level3 = UniqueKey();
      final Key level4 = UniqueKey();

      await tester.pumpWidget(Container(
        key: level0,
        child: Container(
          key: level1,
          child: LookupBoundary(
            key: level2,
            child: Container(
              key: level3,
              child: Container(
                key: level4,
                child: Builder(
                  builder: (BuildContext context) {
                    context.visitAncestorElements((Element element) {
                      throughBoundary.add(element);
                      return element.widget.key != level0;
                    });
                    LookupBoundary.visitAncestorElements(context, (Element element) {
                      stoppedAtBoundary.add(element);
                      return element.widget.key != level0;
                    });
                    LookupBoundary.visitAncestorElements(context, (Element element) {
                      stoppedAtBoundaryTerminatedEarly.add(element);
                      return element.widget.key != level3;
                    });
                    return const SizedBox();
                  }
                )
              )
            )
          )
        ),
      ));

      expect(throughBoundary, <Element>[
        tester.element(find.byKey(level4)),
        tester.element(find.byKey(level3)),
        tester.element(find.byKey(level2)),
        tester.element(find.byKey(level1)),
        tester.element(find.byKey(level0)),
      ]);

      expect(stoppedAtBoundary, <Element>[
        tester.element(find.byKey(level4)),
        tester.element(find.byKey(level3)),
        tester.element(find.byKey(level2)),
      ]);

      expect(stoppedAtBoundaryTerminatedEarly, <Element>[
        tester.element(find.byKey(level4)),
        tester.element(find.byKey(level3)),
      ]);
    });
  });

  group('LookupBoundary.visitChildElements', () {
    testWidgets('respects boundary', (WidgetTester tester) async {
      final Key root = UniqueKey();
      final Key child1 = UniqueKey();
      final Key child2 = UniqueKey();
      final Key child3 = UniqueKey();

      await tester.pumpWidget(Column(
        key: root,
        children: <Widget>[
          LookupBoundary(
            key: child1,
            child: Container(),
          ),
          Container(
            key: child2,
            child: LookupBoundary(
              child: Container(),
            ),
          ),
          Container(
            key: child3,
          ),
        ],
      ));

      final List<Element> throughBoundary = <Element>[];
      final List<Element> stoppedAtBoundary = <Element>[];

      final BuildContext context = tester.element(find.byKey(root));

      context.visitChildElements((Element element) {
        throughBoundary.add(element);
      });
      LookupBoundary.visitChildElements(context, (Element element) {
        stoppedAtBoundary.add(element);
      });

      expect(throughBoundary, <Element>[
        tester.element(find.byKey(child1)),
        tester.element(find.byKey(child2)),
        tester.element(find.byKey(child3)),
      ]);

      expect(stoppedAtBoundary, <Element>[
        tester.element(find.byKey(child2)),
        tester.element(find.byKey(child3)),
      ]);

    });
  });

  group('LookupBoundary.debugIsHidingAncestorWidgetOfExactType', () {
    testWidgets('is hiding', (WidgetTester tester) async {
      bool? isHidden;
      await tester.pumpWidget(Container(
        padding: const EdgeInsets.all(10),
        color: Colors.blue,
        child: LookupBoundary(
          child: Builder(
            builder: (BuildContext context) {
              isHidden = LookupBoundary.debugIsHidingAncestorWidgetOfExactType<Container>(context);
              return Container();
            },
          ),
        ),
      ));
      expect(isHidden, isTrue);
    });

    testWidgets('is not hiding entity within boundary', (WidgetTester tester) async {
      bool? isHidden;
      await tester.pumpWidget(Container(
        padding: const EdgeInsets.all(10),
        color: Colors.blue,
        child: LookupBoundary(
          child: Container(
            padding: const EdgeInsets.all(10),
            color: Colors.red,
            child: Builder(
              builder: (BuildContext context) {
                isHidden = LookupBoundary.debugIsHidingAncestorWidgetOfExactType<Container>(context);
                return Container();
              },
            ),
          ),
        ),
      ));
      expect(isHidden, isFalse);
    });

    testWidgets('is not hiding if no boundary exists', (WidgetTester tester) async {
      bool? isHidden;
      await tester.pumpWidget(Container(
        padding: const EdgeInsets.all(10),
        color: Colors.blue,
        child: Builder(
          builder: (BuildContext context) {
            isHidden = LookupBoundary.debugIsHidingAncestorWidgetOfExactType<Container>(context);
            return Container();
          },
        ),
      ));
      expect(isHidden, isFalse);
    });

    testWidgets('is not hiding if no boundary and no entity exists', (WidgetTester tester) async {
      bool? isHidden;
      await tester.pumpWidget(Builder(
        builder: (BuildContext context) {
          isHidden = LookupBoundary.debugIsHidingAncestorWidgetOfExactType<Container>(context);
          return Container();
        },
      ));
      expect(isHidden, isFalse);
    });
  });

  group('LookupBoundary.debugIsHidingAncestorStateOfType', () {
    testWidgets('is hiding', (WidgetTester tester) async {
      bool? isHidden;
      await tester.pumpWidget(MyStatefulContainer(
        child: LookupBoundary(
          child: Builder(
            builder: (BuildContext context) {
              isHidden = LookupBoundary.debugIsHidingAncestorStateOfType<MyStatefulContainerState>(context);
              return Container();
            },
          ),
        ),
      ));
      expect(isHidden, isTrue);
    });

    testWidgets('is not hiding entity within boundary', (WidgetTester tester) async {
      bool? isHidden;
      await tester.pumpWidget(MyStatefulContainer(
        child: LookupBoundary(
          child: MyStatefulContainer(
            child: Builder(
              builder: (BuildContext context) {
                isHidden = LookupBoundary.debugIsHidingAncestorStateOfType<MyStatefulContainerState>(context);
                return Container();
              },
            ),
          ),
        ),
      ));
      expect(isHidden, isFalse);
    });

    testWidgets('is not hiding if no boundary exists', (WidgetTester tester) async {
      bool? isHidden;
      await tester.pumpWidget(MyStatefulContainer(
        child: Builder(
          builder: (BuildContext context) {
            isHidden = LookupBoundary.debugIsHidingAncestorStateOfType<MyStatefulContainerState>(context);
            return Container();
          },
        ),
      ));
      expect(isHidden, isFalse);
    });

    testWidgets('is not hiding if no boundary and no entity exists', (WidgetTester tester) async {
      bool? isHidden;
      await tester.pumpWidget(Builder(
        builder: (BuildContext context) {
          isHidden = LookupBoundary.debugIsHidingAncestorStateOfType<MyStatefulContainerState>(context);
          return Container();
        },
      ));
      expect(isHidden, isFalse);
    });
  });

  group('LookupBoundary.debugIsHidingAncestorRenderObjectOfType', () {
    testWidgets('is hiding', (WidgetTester tester) async {
      bool? isHidden;
      await tester.pumpWidget(Padding(
        padding: EdgeInsets.zero,
        child: LookupBoundary(
          child: Builder(
            builder: (BuildContext context) {
              isHidden = LookupBoundary.debugIsHidingAncestorRenderObjectOfType<RenderPadding>(context);
              return Container();
            },
          ),
        ),
      ));
      expect(isHidden, isTrue);
    });

    testWidgets('is not hiding entity within boundary', (WidgetTester tester) async {
      bool? isHidden;
      await tester.pumpWidget(Padding(
        padding: EdgeInsets.zero,
        child: LookupBoundary(
          child: Padding(
            padding: EdgeInsets.zero,
            child: Builder(
              builder: (BuildContext context) {
                isHidden = LookupBoundary.debugIsHidingAncestorRenderObjectOfType<RenderPadding>(context);
                return Container();
              },
            ),
          ),
        ),
      ));
      expect(isHidden, isFalse);
    });

    testWidgets('is not hiding if no boundary exists', (WidgetTester tester) async {
      bool? isHidden;
      await tester.pumpWidget(Padding(
        padding: EdgeInsets.zero,
        child: Builder(
          builder: (BuildContext context) {
            isHidden = LookupBoundary.debugIsHidingAncestorRenderObjectOfType<RenderPadding>(context);
            return Container();
          },
        ),
      ));
      expect(isHidden, isFalse);
    });

    testWidgets('is not hiding if no boundary and no entity exists', (WidgetTester tester) async {
      bool? isHidden;
      await tester.pumpWidget(Builder(
        builder: (BuildContext context) {
          isHidden = LookupBoundary.debugIsHidingAncestorRenderObjectOfType<RenderPadding>(context);
          return Container();
        },
      ));
      expect(isHidden, isFalse);
    });
  });
}

class MyStatefulContainer extends StatefulWidget {
  const MyStatefulContainer({super.key, required this.child});

  final Widget child;

  @override
  State<MyStatefulContainer> createState() => MyStatefulContainerState();
}

class MyStatefulContainerState extends State<MyStatefulContainer> {
  @override
  Widget build(BuildContext context) {
    return widget.child;
  }
}

class MyOtherStatefulContainerState extends State<MyStatefulContainer> {
  @override
  Widget build(BuildContext context) {
    return widget.child;
  }
}

class MyInheritedWidget extends InheritedWidget {
  const MyInheritedWidget({super.key, required this.value, required super.child});

  final int value;

  @override
  bool updateShouldNotify(MyInheritedWidget oldWidget) => oldWidget.value != value;
}

class DidChangeDependencySpy extends StatefulWidget {
  const DidChangeDependencySpy({super.key, required this.onDidChangeDependencies});

  final OnDidChangeDependencies onDidChangeDependencies;

  @override
  State<DidChangeDependencySpy> createState() => _DidChangeDependencySpyState();
}

class _DidChangeDependencySpyState extends State<DidChangeDependencySpy> {
  int didChangeDependenciesCount = 0;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    didChangeDependenciesCount += 1;
    widget.onDidChangeDependencies(context);
  }

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

typedef OnDidChangeDependencies = void Function(BuildContext context);
