// 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/rendering.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 '../rendering/rendering_tester.dart' show TestCallbackPainter;

class TestPaintingContext implements PaintingContext {
  final List<Invocation> invocations = <Invocation>[];

  @override
  void noSuchMethod(Invocation invocation) {
    invocations.add(invocation);
  }
}

void main() {
  testWidgets('Can construct an empty Stack', (WidgetTester tester) async {
    await tester.pumpWidget(const Directionality(textDirection: TextDirection.ltr, child: Stack()));
  });

  testWidgets('Can construct an empty Centered Stack', (WidgetTester tester) async {
    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: Center(child: Stack()),
      ),
    );
  });

  testWidgets('Can change position data', (WidgetTester tester) async {
    const key = Key('container');

    await tester.pumpWidget(
      const Stack(
        alignment: Alignment.topLeft,
        children: <Widget>[
          Positioned(left: 10.0, child: SizedBox(key: key, width: 10.0, height: 10.0)),
        ],
      ),
    );

    Element container;
    StackParentData parentData;

    container = tester.element(find.byKey(key));
    parentData = container.renderObject!.parentData! as StackParentData;
    expect(parentData.top, isNull);
    expect(parentData.right, isNull);
    expect(parentData.bottom, isNull);
    expect(parentData.left, equals(10.0));
    expect(parentData.width, isNull);
    expect(parentData.height, isNull);

    await tester.pumpWidget(
      const Stack(
        alignment: Alignment.topLeft,
        children: <Widget>[
          Positioned(right: 10.0, child: SizedBox(key: key, width: 10.0, height: 10.0)),
        ],
      ),
    );

    container = tester.element(find.byKey(key));
    parentData = container.renderObject!.parentData! as StackParentData;
    expect(parentData.top, isNull);
    expect(parentData.right, equals(10.0));
    expect(parentData.bottom, isNull);
    expect(parentData.left, isNull);
    expect(parentData.width, isNull);
    expect(parentData.height, isNull);
  });

  testWidgets('Can remove parent data', (WidgetTester tester) async {
    const key = Key('container');
    const sizedBox = SizedBox(key: key, width: 10.0, height: 10.0);

    await tester.pumpWidget(
      const Stack(
        textDirection: TextDirection.ltr,
        children: <Widget>[Positioned(left: 10.0, child: sizedBox)],
      ),
    );
    Element containerElement = tester.element(find.byKey(key));

    StackParentData parentData;
    parentData = containerElement.renderObject!.parentData! as StackParentData;
    expect(parentData.top, isNull);
    expect(parentData.right, isNull);
    expect(parentData.bottom, isNull);
    expect(parentData.left, equals(10.0));
    expect(parentData.width, isNull);
    expect(parentData.height, isNull);

    await tester.pumpWidget(
      const Stack(textDirection: TextDirection.ltr, children: <Widget>[sizedBox]),
    );
    containerElement = tester.element(find.byKey(key));

    parentData = containerElement.renderObject!.parentData! as StackParentData;
    expect(parentData.top, isNull);
    expect(parentData.right, isNull);
    expect(parentData.bottom, isNull);
    expect(parentData.left, isNull);
    expect(parentData.width, isNull);
    expect(parentData.height, isNull);
  });

  testWidgets('Can align non-positioned children (LTR)', (WidgetTester tester) async {
    const child0Key = Key('child0');
    const child1Key = Key('child1');

    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: Center(
          child: Stack(
            alignment: Alignment.center,
            children: <Widget>[
              SizedBox(key: child0Key, width: 20.0, height: 20.0),
              SizedBox(key: child1Key, width: 10.0, height: 10.0),
            ],
          ),
        ),
      ),
    );

    final Element child0 = tester.element(find.byKey(child0Key));
    final child0RenderObjectParentData = child0.renderObject!.parentData! as StackParentData;
    expect(child0RenderObjectParentData.offset, equals(Offset.zero));

    final Element child1 = tester.element(find.byKey(child1Key));
    final child1RenderObjectParentData = child1.renderObject!.parentData! as StackParentData;
    expect(child1RenderObjectParentData.offset, equals(const Offset(5.0, 5.0)));

    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: Center(
          child: Stack(
            alignment: AlignmentDirectional.bottomEnd,
            children: <Widget>[
              SizedBox(key: child0Key, width: 20.0, height: 20.0),
              SizedBox(key: child1Key, width: 10.0, height: 10.0),
            ],
          ),
        ),
      ),
    );

    expect(child0RenderObjectParentData.offset, equals(Offset.zero));
    expect(child1RenderObjectParentData.offset, equals(const Offset(10.0, 10.0)));
  });

  testWidgets('Can align non-positioned children (RTL)', (WidgetTester tester) async {
    const child0Key = Key('child0');
    const child1Key = Key('child1');

    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.rtl,
        child: Center(
          child: Stack(
            alignment: Alignment.center,
            children: <Widget>[
              SizedBox(key: child0Key, width: 20.0, height: 20.0),
              SizedBox(key: child1Key, width: 10.0, height: 10.0),
            ],
          ),
        ),
      ),
    );

    final Element child0 = tester.element(find.byKey(child0Key));
    final child0RenderObjectParentData = child0.renderObject!.parentData! as StackParentData;
    expect(child0RenderObjectParentData.offset, equals(Offset.zero));

    final Element child1 = tester.element(find.byKey(child1Key));
    final child1RenderObjectParentData = child1.renderObject!.parentData! as StackParentData;
    expect(child1RenderObjectParentData.offset, equals(const Offset(5.0, 5.0)));

    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.rtl,
        child: Center(
          child: Stack(
            alignment: AlignmentDirectional.bottomEnd,
            children: <Widget>[
              SizedBox(key: child0Key, width: 20.0, height: 20.0),
              SizedBox(key: child1Key, width: 10.0, height: 10.0),
            ],
          ),
        ),
      ),
    );

    expect(child0RenderObjectParentData.offset, equals(Offset.zero));
    expect(child1RenderObjectParentData.offset, equals(const Offset(0.0, 10.0)));
  });

  testWidgets('Can construct an empty IndexedStack', (WidgetTester tester) async {
    await tester.pumpWidget(
      const Directionality(textDirection: TextDirection.ltr, child: IndexedStack()),
    );
  });

  testWidgets('Can construct an empty Centered IndexedStack', (WidgetTester tester) async {
    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: Center(child: IndexedStack()),
      ),
    );
  });

  testWidgets('Can construct an IndexedStack', (WidgetTester tester) async {
    const itemCount = 3;
    late List<int> itemsPainted;

    Widget buildFrame(int index) {
      itemsPainted = <int>[];
      final items = List<Widget>.generate(itemCount, (int i) {
        return CustomPaint(
          painter: TestCallbackPainter(
            onPaint: () {
              itemsPainted.add(i);
            },
          ),
          child: Text('$i', textDirection: TextDirection.ltr),
        );
      });
      return Center(
        child: IndexedStack(alignment: Alignment.topLeft, index: index, children: items),
      );
    }

    void expectFindsChild(int n) {
      for (var i = 0; i < 3; i++) {
        expect(find.text('$i', skipOffstage: false), findsOneWidget);

        if (i == n) {
          expect(find.text('$i'), findsOneWidget);
        } else {
          expect(find.text('$i'), findsNothing);
        }
      }
    }

    await tester.pumpWidget(buildFrame(0));
    expectFindsChild(0);
    expect(itemsPainted, equals(<int>[0]));

    await tester.pumpWidget(buildFrame(1));
    expectFindsChild(1);
    expect(itemsPainted, equals(<int>[1]));

    await tester.pumpWidget(buildFrame(2));
    expectFindsChild(2);
    expect(itemsPainted, equals(<int>[2]));
  });

  testWidgets('Can hit test an IndexedStack', (WidgetTester tester) async {
    const key = Key('indexedStack');
    const itemCount = 3;
    late List<int> itemsTapped;

    Widget buildFrame(int index) {
      itemsTapped = <int>[];
      final items = List<Widget>.generate(itemCount, (int i) {
        return GestureDetector(
          child: Text('$i', textDirection: TextDirection.ltr),
          onTap: () {
            itemsTapped.add(i);
          },
        );
      });
      return Center(
        child: IndexedStack(alignment: Alignment.topLeft, key: key, index: index, children: items),
      );
    }

    await tester.pumpWidget(buildFrame(0));
    expect(itemsTapped, isEmpty);
    await tester.tap(find.byKey(key));
    expect(itemsTapped, <int>[0]);

    await tester.pumpWidget(buildFrame(2));
    expect(itemsTapped, isEmpty);
    await tester.tap(find.byKey(key));
    expect(itemsTapped, <int>[2]);
  });

  testWidgets('IndexedStack sets non-selected indexes to visible=false', (
    WidgetTester tester,
  ) async {
    Widget buildStack({required int itemCount, required int? selectedIndex}) {
      final children = List<Widget>.generate(itemCount, (int i) {
        return _ShowVisibility(index: i);
      });
      return Directionality(
        textDirection: TextDirection.ltr,
        child: IndexedStack(index: selectedIndex, children: children),
      );
    }

    await tester.pumpWidget(buildStack(itemCount: 3, selectedIndex: null));
    expect(find.text('index 0 is visible ? false', skipOffstage: false), findsOneWidget);
    expect(find.text('index 1 is visible ? false', skipOffstage: false), findsOneWidget);
    expect(find.text('index 2 is visible ? false', skipOffstage: false), findsOneWidget);

    await tester.pumpWidget(buildStack(itemCount: 3, selectedIndex: 0));
    expect(find.text('index 0 is visible ? true', skipOffstage: false), findsOneWidget);
    expect(find.text('index 1 is visible ? false', skipOffstage: false), findsOneWidget);
    expect(find.text('index 2 is visible ? false', skipOffstage: false), findsOneWidget);

    await tester.pumpWidget(buildStack(itemCount: 3, selectedIndex: 1));
    expect(find.text('index 0 is visible ? false', skipOffstage: false), findsOneWidget);
    expect(find.text('index 1 is visible ? true', skipOffstage: false), findsOneWidget);
    expect(find.text('index 2 is visible ? false', skipOffstage: false), findsOneWidget);

    await tester.pumpWidget(buildStack(itemCount: 3, selectedIndex: 2));
    expect(find.text('index 0 is visible ? false', skipOffstage: false), findsOneWidget);
    expect(find.text('index 1 is visible ? false', skipOffstage: false), findsOneWidget);
    expect(find.text('index 2 is visible ? true', skipOffstage: false), findsOneWidget);
  });

  testWidgets('Can set width and height', (WidgetTester tester) async {
    const key = Key('container');

    const kBoxDecoration = BoxDecoration(color: Color(0xFF00FF00));

    await tester.pumpWidget(
      const Stack(
        textDirection: TextDirection.ltr,
        children: <Widget>[
          Positioned(
            left: 10.0,
            width: 11.0,
            height: 12.0,
            child: DecoratedBox(key: key, decoration: kBoxDecoration),
          ),
        ],
      ),
    );

    Element box;
    RenderBox renderBox;
    StackParentData parentData;

    box = tester.element(find.byKey(key));
    renderBox = box.renderObject! as RenderBox;
    parentData = renderBox.parentData! as StackParentData;
    expect(parentData.top, isNull);
    expect(parentData.right, isNull);
    expect(parentData.bottom, isNull);
    expect(parentData.left, equals(10.0));
    expect(parentData.width, equals(11.0));
    expect(parentData.height, equals(12.0));
    expect(parentData.offset.dx, equals(10.0));
    expect(parentData.offset.dy, equals(0.0));
    expect(renderBox.size.width, equals(11.0));
    expect(renderBox.size.height, equals(12.0));

    await tester.pumpWidget(
      const Stack(
        textDirection: TextDirection.ltr,
        children: <Widget>[
          Positioned(
            right: 10.0,
            width: 11.0,
            height: 12.0,
            child: DecoratedBox(key: key, decoration: kBoxDecoration),
          ),
        ],
      ),
    );

    box = tester.element(find.byKey(key));
    renderBox = box.renderObject! as RenderBox;
    parentData = renderBox.parentData! as StackParentData;
    expect(parentData.top, isNull);
    expect(parentData.right, equals(10.0));
    expect(parentData.bottom, isNull);
    expect(parentData.left, isNull);
    expect(parentData.width, equals(11.0));
    expect(parentData.height, equals(12.0));
    expect(parentData.offset.dx, equals(779.0));
    expect(parentData.offset.dy, equals(0.0));
    expect(renderBox.size.width, equals(11.0));
    expect(renderBox.size.height, equals(12.0));
  });

  testWidgets('Can set and update clipBehavior', (WidgetTester tester) async {
    await tester.pumpWidget(const Stack(textDirection: TextDirection.ltr));
    final RenderStack renderObject = tester.allRenderObjects.whereType<RenderStack>().first;
    expect(renderObject.clipBehavior, equals(Clip.hardEdge));

    await tester.pumpWidget(const Stack(textDirection: TextDirection.ltr));
    expect(renderObject.clipBehavior, equals(Clip.hardEdge));
  });

  testWidgets('Clip.none is respected by describeApproximateClip', (WidgetTester tester) async {
    await tester.pumpWidget(
      const Stack(
        textDirection: TextDirection.ltr,
        children: <Widget>[
          Positioned(left: 1000, right: 2000, child: SizedBox(width: 2000, height: 2000)),
        ],
      ),
    );
    final RenderStack renderObject = tester.allRenderObjects.whereType<RenderStack>().first;
    expect(renderObject.clipBehavior, equals(Clip.hardEdge));

    var visited = false;
    renderObject.visitChildren((RenderObject child) {
      visited = true;
      expect(
        renderObject.describeApproximatePaintClip(child),
        const Rect.fromLTRB(0.0, 0.0, 800.0, 600.0),
      );
    });
    expect(visited, true);
    visited = false;
    renderObject.clipBehavior = Clip.none;
    renderObject.visitChildren((RenderObject child) {
      visited = true;
      expect(renderObject.describeApproximatePaintClip(child), null);
    });
    expect(visited, true);
  });

  testWidgets('IndexedStack with null index', (WidgetTester tester) async {
    bool? tapped;

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Center(
          child: IndexedStack(
            index: null,
            children: <Widget>[
              GestureDetector(
                behavior: HitTestBehavior.opaque,
                onTap: () {
                  tapped = true;
                },
                child: const SizedBox(width: 200.0, height: 200.0),
              ),
            ],
          ),
        ),
      ),
    );

    await tester.tap(find.byType(IndexedStack), warnIfMissed: false);
    final RenderBox box = tester.renderObject(find.byType(IndexedStack));
    expect(box.size, equals(const Size(200.0, 200.0)));
    expect(tapped, isNull);
  });

  testWidgets('IndexedStack reports hidden children as offstage', (WidgetTester tester) async {
    final children = <Widget>[for (int i = 0; i < 5; i++) Text('child $i')];

    Future<void> pumpIndexedStack(int? activeIndex) async {
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: IndexedStack(index: activeIndex, children: children),
        ),
      );
    }

    final Finder finder = find.byType(Text);
    final Finder finderIncludingOffstage = find.byType(Text, skipOffstage: false);

    await pumpIndexedStack(null);
    expect(finder, findsNothing); // IndexedStack with null index shows nothing
    expect(finderIncludingOffstage, findsNWidgets(5));

    for (var i = 0; i < 5; i++) {
      await pumpIndexedStack(i);

      expect(finder, findsOneWidget);
      expect(finderIncludingOffstage, findsNWidgets(5));

      expect(find.text('child $i'), findsOneWidget);
    }
  });

  testWidgets('IndexedStack excludes focus for hidden children', (WidgetTester tester) async {
    const children = <Widget>[Focus(child: Text('child 0')), Focus(child: Text('child 1'))];

    Future<void> pumpIndexedStack(int? activeIndex) async {
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: IndexedStack(index: activeIndex, children: children),
        ),
      );
    }

    Future<void> requestFocusAndPump(FocusNode node) async {
      node.requestFocus();
      await tester.pump();
    }

    await pumpIndexedStack(0);

    final Element child0 = tester.element(find.text('child 0', skipOffstage: false));
    final Element child1 = tester.element(find.text('child 1', skipOffstage: false));
    final FocusNode child0FocusNode = Focus.of(child0);
    final FocusNode child1FocusNode = Focus.of(child1);

    await requestFocusAndPump(child0FocusNode);

    expect(child0FocusNode.hasFocus, true);
    expect(child1FocusNode.hasFocus, false);

    await requestFocusAndPump(child1FocusNode);

    expect(child0FocusNode.hasFocus, true);
    expect(child1FocusNode.hasFocus, false);

    await pumpIndexedStack(1);
    await requestFocusAndPump(child1FocusNode);

    expect(child0FocusNode.hasFocus, false);
    expect(child1FocusNode.hasFocus, true);

    await requestFocusAndPump(child0FocusNode);

    expect(child0FocusNode.hasFocus, false);
    expect(child1FocusNode.hasFocus, true);
  });

  testWidgets('IndexedStack: hidden children can not receive tap events', (
    WidgetTester tester,
  ) async {
    var tapped = false;
    final children = <Widget>[
      const Text('child'),
      GestureDetector(onTap: () => tapped = true, child: const Text('hiddenChild')),
    ];

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: IndexedStack(children: children),
      ),
    );

    await tester.tap(find.text('hiddenChild', skipOffstage: false), warnIfMissed: false);
    await tester.pump();

    expect(tapped, false);
  });

  testWidgets('Stack clip test', (WidgetTester tester) async {
    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: Center(
          child: Stack(
            children: <Widget>[
              SizedBox(width: 100.0, height: 100.0),
              Positioned(top: 0.0, left: 0.0, child: SizedBox(width: 200.0, height: 200.0)),
            ],
          ),
        ),
      ),
    );

    RenderBox box = tester.renderObject(find.byType(Stack));
    var context = TestPaintingContext();
    box.paint(context, Offset.zero);
    expect(context.invocations.first.memberName, equals(#pushClipRect));

    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: Center(
          child: Stack(
            clipBehavior: Clip.none,
            children: <Widget>[
              SizedBox(width: 100.0, height: 100.0),
              Positioned(top: 0.0, left: 0.0, child: SizedBox(width: 200.0, height: 200.0)),
            ],
          ),
        ),
      ),
    );

    box = tester.renderObject(find.byType(Stack));
    context = TestPaintingContext();
    box.paint(context, Offset.zero);
    expect(context.invocations.first.memberName, equals(#paintChild));
  });

  testWidgets('Stack sizing: default', (WidgetTester tester) async {
    final logs = <String>[];
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Center(
          child: ConstrainedBox(
            constraints: const BoxConstraints(
              minWidth: 2.0,
              maxWidth: 3.0,
              minHeight: 5.0,
              maxHeight: 7.0,
            ),
            child: Stack(
              children: <Widget>[
                LayoutBuilder(
                  builder: (BuildContext context, BoxConstraints constraints) {
                    logs.add(constraints.toString());
                    return const Placeholder();
                  },
                ),
              ],
            ),
          ),
        ),
      ),
    );
    expect(logs, <String>['BoxConstraints(0.0<=w<=3.0, 0.0<=h<=7.0)']);
  });

  testWidgets('Stack sizing: explicit', (WidgetTester tester) async {
    final logs = <String>[];
    Widget buildStack(StackFit sizing) {
      return Directionality(
        textDirection: TextDirection.ltr,
        child: Center(
          child: ConstrainedBox(
            constraints: const BoxConstraints(
              minWidth: 2.0,
              maxWidth: 3.0,
              minHeight: 5.0,
              maxHeight: 7.0,
            ),
            child: Stack(
              fit: sizing,
              children: <Widget>[
                LayoutBuilder(
                  builder: (BuildContext context, BoxConstraints constraints) {
                    logs.add(constraints.toString());
                    return const Placeholder();
                  },
                ),
              ],
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildStack(StackFit.loose));
    logs.add('=1=');
    await tester.pumpWidget(buildStack(StackFit.expand));
    logs.add('=2=');
    await tester.pumpWidget(buildStack(StackFit.passthrough));
    expect(logs, <String>[
      'BoxConstraints(0.0<=w<=3.0, 0.0<=h<=7.0)',
      '=1=',
      'BoxConstraints(w=3.0, h=7.0)',
      '=2=',
      'BoxConstraints(2.0<=w<=3.0, 5.0<=h<=7.0)',
    ]);
  });

  testWidgets('Positioned.directional control test', (WidgetTester tester) async {
    final Key key = UniqueKey();
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Stack(
          children: <Widget>[
            Positioned.directional(
              textDirection: TextDirection.rtl,
              start: 50.0,
              child: SizedBox(key: key, width: 75.0, height: 175.0),
            ),
          ],
        ),
      ),
    );

    expect(tester.getTopLeft(find.byKey(key)), const Offset(675.0, 0.0));

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Stack(
          children: <Widget>[
            Positioned.directional(
              textDirection: TextDirection.ltr,
              start: 50.0,
              child: SizedBox(key: key, width: 75.0, height: 175.0),
            ),
          ],
        ),
      ),
    );

    expect(tester.getTopLeft(find.byKey(key)), const Offset(50.0, 0.0));
  });

  testWidgets('PositionedDirectional control test', (WidgetTester tester) async {
    final Key key = UniqueKey();
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.rtl,
        child: Stack(
          children: <Widget>[
            PositionedDirectional(
              start: 50.0,
              child: SizedBox(key: key, width: 75.0, height: 175.0),
            ),
          ],
        ),
      ),
    );

    expect(tester.getTopLeft(find.byKey(key)), const Offset(675.0, 0.0));

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Stack(
          children: <Widget>[
            PositionedDirectional(
              start: 50.0,
              child: SizedBox(key: key, width: 75.0, height: 175.0),
            ),
          ],
        ),
      ),
    );

    expect(tester.getTopLeft(find.byKey(key)), const Offset(50.0, 0.0));
  });

  testWidgets('Can change the text direction of a Stack', (WidgetTester tester) async {
    await tester.pumpWidget(const Stack(alignment: Alignment.center));
    await tester.pumpWidget(const Stack(textDirection: TextDirection.rtl));
    await tester.pumpWidget(const Stack(alignment: Alignment.center));
  });

  testWidgets('Alignment with partially-positioned children', (WidgetTester tester) async {
    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.rtl,
        child: Stack(
          alignment: Alignment.center,
          children: <Widget>[
            SizedBox(width: 100.0, height: 100.0),
            Positioned(left: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
            Positioned(right: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
            Positioned(top: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
            Positioned(bottom: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
            PositionedDirectional(start: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
            PositionedDirectional(end: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
            PositionedDirectional(top: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
            PositionedDirectional(bottom: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
          ],
        ),
      ),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(0)),
      const Rect.fromLTWH(350.0, 250.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(1)),
      const Rect.fromLTWH(0.0, 250.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(2)),
      const Rect.fromLTWH(700.0, 250.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(3)),
      const Rect.fromLTWH(350.0, 0.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(4)),
      const Rect.fromLTWH(350.0, 500.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(5)),
      const Rect.fromLTWH(700.0, 250.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(6)),
      const Rect.fromLTWH(0.0, 250.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(7)),
      const Rect.fromLTWH(350.0, 0.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(8)),
      const Rect.fromLTWH(350.0, 500.0, 100.0, 100.0),
    );

    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: Stack(
          alignment: Alignment.center,
          children: <Widget>[
            SizedBox(width: 100.0, height: 100.0),
            Positioned(left: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
            Positioned(right: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
            Positioned(top: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
            Positioned(bottom: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
            PositionedDirectional(start: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
            PositionedDirectional(end: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
            PositionedDirectional(top: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
            PositionedDirectional(bottom: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
          ],
        ),
      ),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(0)),
      const Rect.fromLTWH(350.0, 250.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(1)),
      const Rect.fromLTWH(0.0, 250.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(2)),
      const Rect.fromLTWH(700.0, 250.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(3)),
      const Rect.fromLTWH(350.0, 0.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(4)),
      const Rect.fromLTWH(350.0, 500.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(5)),
      const Rect.fromLTWH(0.0, 250.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(6)),
      const Rect.fromLTWH(700.0, 250.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(7)),
      const Rect.fromLTWH(350.0, 0.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(8)),
      const Rect.fromLTWH(350.0, 500.0, 100.0, 100.0),
    );

    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: Stack(
          alignment: Alignment.bottomRight,
          children: <Widget>[
            SizedBox(width: 100.0, height: 100.0),
            Positioned(left: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
            Positioned(right: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
            Positioned(top: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
            Positioned(bottom: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
            PositionedDirectional(start: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
            PositionedDirectional(end: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
            PositionedDirectional(top: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
            PositionedDirectional(bottom: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
          ],
        ),
      ),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(0)),
      const Rect.fromLTWH(700.0, 500.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(1)),
      const Rect.fromLTWH(0.0, 500.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(2)),
      const Rect.fromLTWH(700.0, 500.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(3)),
      const Rect.fromLTWH(700.0, 0.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(4)),
      const Rect.fromLTWH(700.0, 500.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(5)),
      const Rect.fromLTWH(0.0, 500.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(6)),
      const Rect.fromLTWH(700.0, 500.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(7)),
      const Rect.fromLTWH(700.0, 0.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(8)),
      const Rect.fromLTWH(700.0, 500.0, 100.0, 100.0),
    );

    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: Stack(
          alignment: Alignment.topLeft,
          children: <Widget>[
            SizedBox(width: 100.0, height: 100.0),
            Positioned(left: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
            Positioned(right: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
            Positioned(top: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
            Positioned(bottom: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
            PositionedDirectional(start: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
            PositionedDirectional(end: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
            PositionedDirectional(top: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
            PositionedDirectional(bottom: 0.0, child: SizedBox(width: 100.0, height: 100.0)),
          ],
        ),
      ),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(0)),
      const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(1)),
      const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(2)),
      const Rect.fromLTWH(700.0, 0.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(3)),
      const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(4)),
      const Rect.fromLTWH(0.0, 500.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(5)),
      const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(6)),
      const Rect.fromLTWH(700.0, 0.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(7)),
      const Rect.fromLTWH(0.0, 0.0, 100.0, 100.0),
    );
    expect(
      tester.getRect(find.byType(SizedBox).at(8)),
      const Rect.fromLTWH(0.0, 500.0, 100.0, 100.0),
    );
  });

  testWidgets(
    'Stack error messages',
    experimentalLeakTesting: LeakTesting.settings
        .withIgnoredAll(), // leaking by design because of exception
    (WidgetTester tester) async {
      await tester.pumpWidget(const Stack());
      final exception = tester.takeException().toString();

      expect(
        exception,
        startsWith(
          'No Directionality widget found.\n'
          "Stack widgets require a Directionality widget ancestor to resolve the 'alignment' argument.\n"
          "The default value for 'alignment' is AlignmentDirectional.topStart, which requires a text direction.\n"
          'The specific widget that could not find a Directionality ancestor was:\n'
          '  Stack\n'
          'The ownership chain for the affected widget is: "Stack ← ', // Omitted full ownership chain because it is not relevant for the test.
        ),
      );
      expect(
        exception,
        endsWith(
          '_ViewScope ← ⋯"\n' // End of ownership chain.
          'Typically, the Directionality widget is introduced by the MaterialApp or WidgetsApp widget at the '
          'top of your application widget tree. It determines the ambient reading direction and is used, for '
          'example, to determine how to lay out text, how to interpret "start" and "end" values, and to resolve '
          'EdgeInsetsDirectional, AlignmentDirectional, and other *Directional objects.\n'
          'Instead of providing a Directionality widget, another solution would be passing a non-directional '
          "'alignment', or an explicit 'textDirection', to the Stack.",
        ),
      );
    },
  );

  testWidgets('Can update clipBehavior of IndexedStack', (WidgetTester tester) async {
    await tester.pumpWidget(const IndexedStack(textDirection: TextDirection.ltr));
    final RenderIndexedStack renderObject = tester.renderObject<RenderIndexedStack>(
      find.byType(IndexedStack),
    );
    expect(renderObject.clipBehavior, equals(Clip.hardEdge));

    // Update clipBehavior to Clip.antiAlias

    await tester.pumpWidget(
      const IndexedStack(textDirection: TextDirection.ltr, clipBehavior: Clip.antiAlias),
    );
    final RenderIndexedStack renderIndexedObject = tester.renderObject<RenderIndexedStack>(
      find.byType(IndexedStack),
    );
    expect(renderIndexedObject.clipBehavior, equals(Clip.antiAlias));
  });

  testWidgets('IndexedStack sizing: explicit', (WidgetTester tester) async {
    final logs = <String>[];
    Widget buildIndexedStack(StackFit sizing) {
      return Directionality(
        textDirection: TextDirection.ltr,
        child: Center(
          child: ConstrainedBox(
            constraints: const BoxConstraints(
              minWidth: 2.0,
              maxWidth: 3.0,
              minHeight: 5.0,
              maxHeight: 7.0,
            ),
            child: IndexedStack(
              sizing: sizing,
              children: <Widget>[
                LayoutBuilder(
                  builder: (BuildContext context, BoxConstraints constraints) {
                    logs.add(constraints.toString());
                    return const Placeholder();
                  },
                ),
              ],
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildIndexedStack(StackFit.loose));
    logs.add('=1=');
    await tester.pumpWidget(buildIndexedStack(StackFit.expand));
    logs.add('=2=');
    await tester.pumpWidget(buildIndexedStack(StackFit.passthrough));
    expect(logs, <String>[
      'BoxConstraints(0.0<=w<=3.0, 0.0<=h<=7.0)',
      '=1=',
      'BoxConstraints(w=3.0, h=7.0)',
      '=2=',
      'BoxConstraints(2.0<=w<=3.0, 5.0<=h<=7.0)',
    ]);
  });

  testWidgets('IndexedStack does not assert with the default parameters', (
    WidgetTester tester,
  ) async {
    await tester.pumpWidget(
      const Directionality(textDirection: TextDirection.ltr, child: IndexedStack()),
    );

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

  testWidgets('IndexedStack does not assert when index is null', (WidgetTester tester) async {
    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: IndexedStack(index: null, children: <Widget>[SizedBox.shrink(), SizedBox.shrink()]),
      ),
    );

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

  testWidgets('IndexedStack asserts when index is negative', (WidgetTester tester) async {
    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: IndexedStack(index: -1, children: <Widget>[SizedBox.shrink(), SizedBox.shrink()]),
      ),
    );

    expect(tester.takeException(), isA<AssertionError>());
  });

  testWidgets('IndexedStack asserts when index is not in children range', (
    WidgetTester tester,
  ) async {
    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: IndexedStack(index: 2, children: <Widget>[SizedBox.shrink(), SizedBox.shrink()]),
      ),
    );

    expect(tester.takeException(), isA<AssertionError>());
  });
}

class _ShowVisibility extends StatelessWidget {
  const _ShowVisibility({required this.index});

  final int index;

  @override
  Widget build(BuildContext context) {
    return Text('index $index is visible ? ${Visibility.of(context)}');
  }
}
