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

import 'two_dimensional_utils.dart';

void main() {
  group('TwoDimensionalChildDelegate', () {
    group('TwoDimensionalChildBuilderDelegate', () {
      testWidgets('repaintBoundaries', (WidgetTester tester) async {
        // Default - adds repaint boundaries
        late final TwoDimensionalChildBuilderDelegate delegate1;
        addTearDown(() => delegate1.dispose());
        await tester.pumpWidget(simpleBuilderTest(
          delegate: delegate1 = TwoDimensionalChildBuilderDelegate(
            // Only build 1 child
            maxXIndex: 0,
            maxYIndex: 0,
            builder: (BuildContext context, ChildVicinity vicinity) {
              return SizedBox(
                height: 200,
                width: 200,
                child: Center(child: Text('C${vicinity.xIndex}:R${vicinity.yIndex}')),
              );
            }
          )
        ));
        await tester.pumpAndSettle();

        switch (defaultTargetPlatform) {
          case TargetPlatform.android:
          case TargetPlatform.fuchsia:
            expect(find.byType(RepaintBoundary), findsNWidgets(7));
          case TargetPlatform.iOS:
          case TargetPlatform.linux:
          case TargetPlatform.macOS:
          case TargetPlatform.windows:
            expect(find.byType(RepaintBoundary), findsNWidgets(3));
        }

        // None
        late final TwoDimensionalChildBuilderDelegate delegate2;
        addTearDown(() => delegate2.dispose());
        await tester.pumpWidget(simpleBuilderTest(
          delegate: delegate2 = TwoDimensionalChildBuilderDelegate(
            // Only build 1 child
            maxXIndex: 0,
            maxYIndex: 0,
            addRepaintBoundaries: false,
            builder: (BuildContext context, ChildVicinity vicinity) {
              return SizedBox(
                height: 200,
                width: 200,
                child: Center(child: Text('C${vicinity.xIndex}:R${vicinity.yIndex}')),
              );
            }
          )
        ));
        await tester.pumpAndSettle();

        switch (defaultTargetPlatform) {
          case TargetPlatform.android:
          case TargetPlatform.fuchsia:
            expect(find.byType(RepaintBoundary), findsNWidgets(6));
          case TargetPlatform.iOS:
          case TargetPlatform.linux:
          case TargetPlatform.macOS:
          case TargetPlatform.windows:
            expect(find.byType(RepaintBoundary), findsNWidgets(2));
        }
      }, variant: TargetPlatformVariant.all());

      testWidgets('will return null from build for exceeding maxXIndex and maxYIndex', (WidgetTester tester) async {
        late BuildContext capturedContext;
        final TwoDimensionalChildBuilderDelegate delegate = TwoDimensionalChildBuilderDelegate(
          // Only build 1 child
          maxXIndex: 0,
          maxYIndex: 0,
          addRepaintBoundaries: false,
          builder: (BuildContext context, ChildVicinity vicinity) {
            capturedContext = context;
            return SizedBox(
              height: 200,
              width: 200,
              child: Center(child: Text('C${vicinity.xIndex}:R${vicinity.yIndex}')),
            );
          }
        );
        addTearDown(delegate.dispose);

        await tester.pumpWidget(simpleBuilderTest(
          delegate: delegate,
        ));
        await tester.pumpAndSettle();
        // maxXIndex
        expect(
          delegate.build(capturedContext, const ChildVicinity(xIndex: 1, yIndex: 0)),
          isNull,
        );

        // maxYIndex
        expect(
          delegate.build(capturedContext, const ChildVicinity(xIndex: 0, yIndex: 1)),
          isNull,
        );

        // Both
        expect(
          delegate.build(capturedContext, const ChildVicinity(xIndex: 1, yIndex: 1)),
          isNull,
        );
      }, variant: TargetPlatformVariant.all());

      test('maxXIndex and maxYIndex assertions', () {
        final TwoDimensionalChildBuilderDelegate delegate = TwoDimensionalChildBuilderDelegate(
          maxXIndex: 0,
          maxYIndex: 0,
          builder: (BuildContext context, ChildVicinity vicinity) {
            return const SizedBox.shrink();
          }
        );
        // Update
        delegate.maxXIndex = -1; // No exception.
        expect(
          () {
            delegate.maxXIndex = -2;
          },
          throwsA(
            isA<AssertionError>().having(
              (AssertionError error) => error.toString(),
              'description',
              contains('value == null || value >= -1'),
            ),
          ),
        );
        delegate.maxYIndex = -1; // No exception
        expect(
          () {
            delegate.maxYIndex = -2;
          },
          throwsA(
            isA<AssertionError>().having(
              (AssertionError error) => error.toString(),
              'description',
              contains('value == null || value >= -1'),
            ),
          ),
        );
        // Constructor
        expect(
          () {
            TwoDimensionalChildBuilderDelegate(
              maxXIndex: -2,
              maxYIndex: 0,
              builder: (BuildContext context, ChildVicinity vicinity) {
                return const SizedBox.shrink();
              }
            );
          },
          throwsA(
            isA<AssertionError>().having(
              (AssertionError error) => error.toString(),
              'description',
              contains('maxXIndex == null || maxXIndex >= -1'),
            ),
          ),
        );
        expect(
          () {
            TwoDimensionalChildBuilderDelegate(
              maxXIndex: 0,
              maxYIndex: -2,
              builder: (BuildContext context, ChildVicinity vicinity) {
                return const SizedBox.shrink();
              }
            );
          },
          throwsA(
            isA<AssertionError>().having(
              (AssertionError error) => error.toString(),
              'description',
              contains('maxYIndex == null || maxYIndex >= -1'),
            ),
          ),
        );
      });

      testWidgets('throws an error when builder throws', (WidgetTester tester) async {
        final List<Object> exceptions = <Object>[];
        final FlutterExceptionHandler? oldHandler = FlutterError.onError;
        FlutterError.onError = (FlutterErrorDetails details) {
          exceptions.add(details.exception);
        };
        final TwoDimensionalChildBuilderDelegate delegate = TwoDimensionalChildBuilderDelegate(
          // Only build 1 child
          maxXIndex: 0,
          maxYIndex: 0,
          addRepaintBoundaries: false,
          builder: (BuildContext context, ChildVicinity vicinity) {
            throw 'Builder error!';
          }
        );
        addTearDown(delegate.dispose);

        await tester.pumpWidget(simpleBuilderTest(
          delegate: delegate,
        ));
        await tester.pumpAndSettle();
        FlutterError.onError = oldHandler;

        expect(exceptions.isNotEmpty, isTrue);
        expect(exceptions.length, 1);
        expect(exceptions[0] as String, contains('Builder error!'));
      }, variant: TargetPlatformVariant.all());

      testWidgets('shouldRebuild', (WidgetTester tester) async {
        expect(builderDelegate.shouldRebuild(builderDelegate), isTrue);
      }, variant: TargetPlatformVariant.all());

      testWidgets('builder delegate supports automatic keep alive - default true', (WidgetTester tester) async {
        const ChildVicinity firstCell = ChildVicinity(xIndex: 0, yIndex: 0);
        final ScrollController verticalController = ScrollController();
        addTearDown(verticalController.dispose);
        final UniqueKey checkBoxKey = UniqueKey();
        final TwoDimensionalChildBuilderDelegate builderDelegate = TwoDimensionalChildBuilderDelegate(
          maxXIndex: 5,
          maxYIndex: 5,
          builder: (BuildContext context, ChildVicinity vicinity) {
            return SizedBox.square(
              dimension: 200,
              child: Center(child: vicinity == firstCell
                ? KeepAliveCheckBox(key: checkBoxKey)
                : Text('R${vicinity.xIndex}:C${vicinity.yIndex}')
              ),
            );
          }
        );
        addTearDown(builderDelegate.dispose);

        await tester.pumpWidget(simpleBuilderTest(
          delegate: builderDelegate,
          verticalDetails: ScrollableDetails.vertical(controller: verticalController),
        ));
        await tester.pumpAndSettle();

        expect(verticalController.hasClients, isTrue);
        expect(verticalController.position.pixels, 0.0);
        expect(find.byKey(checkBoxKey), findsOneWidget);
        expect(
          tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).checkValue,
          isFalse,
        );
        expect(
          tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).wantKeepAlive,
          isFalse,
        );
        // Scroll away, disposing of the checkbox.
        verticalController.jumpTo(verticalController.position.maxScrollExtent);
        await tester.pump();
        expect(verticalController.position.pixels, 600.0);
        expect(find.byKey(checkBoxKey), findsNothing);

        // Bring back into view, still unchecked, not kept alive.
        verticalController.jumpTo(0.0);
        await tester.pump();
        expect(verticalController.position.pixels, 0.0);
        expect(find.byKey(checkBoxKey), findsOneWidget);
        await tester.tap(find.byKey(checkBoxKey));
        await tester.pumpAndSettle();
        expect(
          tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).checkValue,
          isTrue,
        );
        expect(
          tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).wantKeepAlive,
          isTrue,
        );

        // Scroll away again, checkbox should be kept alive now.
        verticalController.jumpTo(verticalController.position.maxScrollExtent);
        await tester.pump();
        expect(verticalController.position.pixels, 600.0);
        expect(find.byKey(checkBoxKey), findsOneWidget);
        expect(
          tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).checkValue,
          isTrue,
        );
        expect(
          tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).wantKeepAlive,
          isTrue,
        );

        // Bring back into view, still checked, after being kept alive.
        verticalController.jumpTo(0.0);
        await tester.pump();
        expect(verticalController.position.pixels, 0.0);
        expect(find.byKey(checkBoxKey), findsOneWidget);
        expect(
          tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).checkValue,
          isTrue,
        );
        expect(
          tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).wantKeepAlive,
          isTrue,
        );
      });

      testWidgets('Keep alive works with additional parent data widgets', (WidgetTester tester) async {
        const ChildVicinity firstCell = ChildVicinity(xIndex: 0, yIndex: 0);
        final ScrollController verticalController = ScrollController();
        addTearDown(verticalController.dispose);
        final UniqueKey checkBoxKey = UniqueKey();
        final TwoDimensionalChildBuilderDelegate builderDelegate = TwoDimensionalChildBuilderDelegate(
          maxXIndex: 5,
          maxYIndex: 5,
          addRepaintBoundaries: false,
          builder: (BuildContext context, ChildVicinity vicinity) {
            // The delegate will add a KeepAlive ParentDataWidget, this add an
            // additional ParentDataWidget.
            return TestParentDataWidget(
              testValue: 20,
              child: SizedBox.square(
                dimension: 200,
                child: Center(child: vicinity == firstCell
                  ? KeepAliveCheckBox(key: checkBoxKey)
                  : Text('R${vicinity.xIndex}:C${vicinity.yIndex}')
                ),
              ),
            );
          }
        );
        addTearDown(builderDelegate.dispose);

        await tester.pumpWidget(simpleBuilderTest(
          delegate: builderDelegate,
          verticalDetails: ScrollableDetails.vertical(controller: verticalController),
        ));
        await tester.pumpAndSettle();

        expect(verticalController.hasClients, isTrue);
        expect(verticalController.position.pixels, 0.0);
        expect(find.byKey(checkBoxKey), findsOneWidget);
        expect(
          tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).checkValue,
          isFalse,
        );
        expect(
          tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).wantKeepAlive,
          isFalse,
        );
        RenderSimpleBuilderTableViewport viewport = getViewport(tester, checkBoxKey) as RenderSimpleBuilderTableViewport;
        TestExtendedParentData parentData = viewport.parentDataOf(viewport.testGetChildFor(firstCell)!);
        // Check parent data from both ParentDataWidgets
        expect(parentData.testValue, 20);
        expect(parentData.keepAlive, isFalse);

        // Scroll away, disposing of the checkbox.
        verticalController.jumpTo(verticalController.position.maxScrollExtent);
        await tester.pump();
        expect(verticalController.position.pixels, 600.0);
        expect(find.byKey(checkBoxKey), findsNothing);

        // Bring back into view, still unchecked, not kept alive.
        verticalController.jumpTo(0.0);
        await tester.pump();
        expect(verticalController.position.pixels, 0.0);
        expect(find.byKey(checkBoxKey), findsOneWidget);
        // Check the box to set keep alive to true.
        await tester.tap(find.byKey(checkBoxKey));
        await tester.pumpAndSettle();
        expect(
          tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).checkValue,
          isTrue,
        );
        expect(
          tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).wantKeepAlive,
          isTrue,
        );
        viewport = getViewport(tester, checkBoxKey) as RenderSimpleBuilderTableViewport;
        parentData = viewport.parentDataOf(viewport.testGetChildFor(firstCell)!);
        // Check parent data from both ParentDataWidgets
        expect(parentData.testValue, 20);
        expect(parentData.keepAlive, isTrue);

        // Scroll away again, checkbox should be kept alive now.
        verticalController.jumpTo(verticalController.position.maxScrollExtent);
        await tester.pump();
        expect(verticalController.position.pixels, 600.0);
        expect(find.byKey(checkBoxKey), findsOneWidget);
        expect(
          tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).checkValue,
          isTrue,
        );
        expect(
          tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).wantKeepAlive,
          isTrue,
        );
        viewport = getViewport(tester, checkBoxKey) as RenderSimpleBuilderTableViewport;
        parentData = viewport.parentDataOf(viewport.testGetChildFor(firstCell)!);
        // Check parent data from both ParentDataWidgets
        expect(parentData.testValue, 20);
        expect(parentData.keepAlive, isTrue);

        // Bring back into view, still checked, after being kept alive.
        verticalController.jumpTo(0.0);
        await tester.pump();
        expect(verticalController.position.pixels, 0.0);
        expect(find.byKey(checkBoxKey), findsOneWidget);
        expect(
          tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).checkValue,
          isTrue,
        );
        expect(
          tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).wantKeepAlive,
          isTrue,
        );
        viewport = getViewport(tester, checkBoxKey) as RenderSimpleBuilderTableViewport;
        parentData = viewport.parentDataOf(viewport.testGetChildFor(firstCell)!);
        // Check parent data from both ParentDataWidgets
        expect(parentData.testValue, 20);
        expect(parentData.keepAlive, isTrue);
      });

      testWidgets('builder delegate will not add automatic keep alives', (WidgetTester tester) async {
        const ChildVicinity firstCell = ChildVicinity(xIndex: 0, yIndex: 0);
        final ScrollController verticalController = ScrollController();
        addTearDown(verticalController.dispose);
        final UniqueKey checkBoxKey = UniqueKey();
        final TwoDimensionalChildBuilderDelegate builderDelegate = TwoDimensionalChildBuilderDelegate(
          maxXIndex: 5,
          maxYIndex: 5,
          addAutomaticKeepAlives: false, // No keeping alive this time
          builder: (BuildContext context, ChildVicinity vicinity) {
            return SizedBox.square(
              dimension: 200,
              child: Center(child: vicinity == firstCell
                ? KeepAliveCheckBox(key: checkBoxKey)
                : Text('R${vicinity.xIndex}:C${vicinity.yIndex}')
              ),
            );
          }
        );
        addTearDown(builderDelegate.dispose);

        await tester.pumpWidget(simpleBuilderTest(
          delegate: builderDelegate,
          verticalDetails: ScrollableDetails.vertical(controller: verticalController),
        ));
        await tester.pumpAndSettle();

        expect(verticalController.hasClients, isTrue);
        expect(verticalController.position.pixels, 0.0);
        expect(find.byKey(checkBoxKey), findsOneWidget);
        expect(
          tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).checkValue,
          isFalse,
        );
        expect(
          tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).wantKeepAlive,
          isFalse,
        );
        // Scroll away, disposing of the checkbox.
        verticalController.jumpTo(verticalController.position.maxScrollExtent);
        await tester.pump();
        expect(verticalController.position.pixels, 600.0);
        expect(find.byKey(checkBoxKey), findsNothing);

        // Bring back into view, still unchecked, not kept alive.
        verticalController.jumpTo(0.0);
        await tester.pump();
        expect(verticalController.position.pixels, 0.0);
        expect(find.byKey(checkBoxKey), findsOneWidget);
        await tester.tap(find.byKey(checkBoxKey));
        await tester.pumpAndSettle();
        expect(
          tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).checkValue,
          isTrue,
        );
        expect(
          tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).wantKeepAlive,
          isTrue,
        );

        // Scroll away again, checkbox should not be kept alive since the
        // delegate did not add automatic keep alive.
        verticalController.jumpTo(verticalController.position.maxScrollExtent);
        await tester.pump();
        expect(verticalController.position.pixels, 600.0);
        expect(find.byKey(checkBoxKey), findsNothing);

        // Bring back into view, not checked, having not been kept alive.
        verticalController.jumpTo(0.0);
        await tester.pump();
        expect(verticalController.position.pixels, 0.0);
        expect(find.byKey(checkBoxKey), findsOneWidget);
        expect(
          tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).checkValue,
          isFalse,
        );
        expect(
          tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).wantKeepAlive,
          isFalse,
        );
      });
    });

    group('TwoDimensionalChildListDelegate', () {
      testWidgets('repaintBoundaries', (WidgetTester tester) async {
        final List<List<Widget>> children = <List<Widget>>[];
        children.add(<Widget>[
          const SizedBox(
            height: 200,
            width: 200,
            child: Center(child: Text('R0:C0')),
          )
        ]);
        // Default - adds repaint boundaries
        late final TwoDimensionalChildListDelegate delegate1;
        addTearDown(() => delegate1.dispose());
        await tester.pumpWidget(simpleListTest(
          delegate: delegate1 = TwoDimensionalChildListDelegate(
            // Only builds 1 child
            children: children,
          )
        ));
        await tester.pumpAndSettle();

        // In the tests below the number of RepaintBoundary widgets depends on:
        // ModalRoute - builds 2
        // GlowingOverscrollIndicator - builds 2
        // TwoDimensionalChildListDelegate - builds 1 unless addRepaintBoundaries is false

        void expectModalRoute() {
          expect(ModalRoute.of(tester.element(find.byType(SimpleListTableViewport))), isA<MaterialPageRoute<void>>());
        }

        switch (defaultTargetPlatform) {
          case TargetPlatform.fuchsia:
            expectModalRoute();
            expect(find.byType(GlowingOverscrollIndicator), findsNWidgets(2));
            expect(find.byType(RepaintBoundary), findsNWidgets(7));

          case TargetPlatform.android:
          case TargetPlatform.iOS:
          case TargetPlatform.linux:
          case TargetPlatform.macOS:
          case TargetPlatform.windows:
            expectModalRoute();
            expect(find.byType(RepaintBoundary), findsNWidgets(3));
        }

        // None
        late final TwoDimensionalChildListDelegate delegate2;
        addTearDown(() => delegate2.dispose());
        await tester.pumpWidget(simpleListTest(
          delegate: delegate2 = TwoDimensionalChildListDelegate(
            // Different children triggers rebuild
            children: <List<Widget>>[<Widget>[Container()]],
            addRepaintBoundaries: false,
          )
        ));
        await tester.pumpAndSettle();

        switch (defaultTargetPlatform) {
          case TargetPlatform.fuchsia:
            expectModalRoute();
            expect(find.byType(GlowingOverscrollIndicator), findsNWidgets(2));
            expect(find.byType(RepaintBoundary), findsNWidgets(6));

          case TargetPlatform.android:
          case TargetPlatform.iOS:
          case TargetPlatform.linux:
          case TargetPlatform.macOS:
          case TargetPlatform.windows:
            expectModalRoute();
            expect(find.byType(RepaintBoundary), findsNWidgets(2));
        }
      }, variant: TargetPlatformVariant.all());

      testWidgets('will return null for a ChildVicinity outside of list bounds', (WidgetTester tester) async {
        final List<List<Widget>> children = <List<Widget>>[];
        children.add(<Widget>[
          const SizedBox(
            height: 200,
            width: 200,
            child: Center(child: Text('R0:C0')),
          )
        ]);
        final TwoDimensionalChildListDelegate delegate = TwoDimensionalChildListDelegate(
          // Only builds 1 child
          children: children,
        );
        addTearDown(delegate.dispose);

        // X index
        expect(
          delegate.build(_NullBuildContext(), const ChildVicinity(xIndex: 1, yIndex: 0)),
          isNull,
        );
        // Y index
        expect(
          delegate.build(_NullBuildContext(), const ChildVicinity(xIndex: 0, yIndex: 1)),
          isNull,
        );

        // Both
        expect(
          delegate.build(_NullBuildContext(), const ChildVicinity(xIndex: 1, yIndex: 1)),
          isNull,
        );
      }, variant: TargetPlatformVariant.all());

      testWidgets('shouldRebuild', (WidgetTester tester) async {
        final List<List<Widget>> children = <List<Widget>>[];
        children.add(<Widget>[
          const SizedBox(
            height: 200,
            width: 200,
            child: Center(child: Text('R0:C0')),
          )
        ]);
        final TwoDimensionalChildListDelegate delegate = TwoDimensionalChildListDelegate(
          // Only builds 1 child
          children: children,
        );
        addTearDown(delegate.dispose);
        expect(delegate.shouldRebuild(delegate), isFalse);

        final List<List<Widget>> newChildren = <List<Widget>>[];
        final TwoDimensionalChildListDelegate oldDelegate = TwoDimensionalChildListDelegate(
          children: newChildren,
        );
        addTearDown(oldDelegate.dispose);

        expect(delegate.shouldRebuild(oldDelegate), isTrue);
      }, variant: TargetPlatformVariant.all());
    });

    testWidgets('list delegate supports automatic keep alive - default true', (WidgetTester tester) async {
      final UniqueKey checkBoxKey = UniqueKey();
      final Widget originCell = SizedBox.square(
        dimension: 200,
        child: Center(child: KeepAliveCheckBox(key: checkBoxKey)
        ),
      );
      const Widget otherCell = SizedBox.square(dimension: 200);
      final ScrollController verticalController = ScrollController();
      addTearDown(verticalController.dispose);
      final TwoDimensionalChildListDelegate listDelegate = TwoDimensionalChildListDelegate(
        children: <List<Widget>>[
          <Widget>[originCell, otherCell, otherCell, otherCell, otherCell],
          <Widget>[otherCell, otherCell, otherCell, otherCell, otherCell],
          <Widget>[otherCell, otherCell, otherCell, otherCell, otherCell],
          <Widget>[otherCell, otherCell, otherCell, otherCell, otherCell],
          <Widget>[otherCell, otherCell, otherCell, otherCell, otherCell],
        ],
      );
      addTearDown(listDelegate.dispose);

      await tester.pumpWidget(simpleListTest(
        delegate: listDelegate,
        verticalDetails: ScrollableDetails.vertical(controller: verticalController),
      ));
      await tester.pumpAndSettle();

      expect(verticalController.hasClients, isTrue);
      expect(verticalController.position.pixels, 0.0);
      expect(find.byKey(checkBoxKey), findsOneWidget);
      expect(
        tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).checkValue,
        isFalse,
      );
      expect(
        tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).wantKeepAlive,
        isFalse,
      );
      // Scroll away, disposing of the checkbox.
      verticalController.jumpTo(verticalController.position.maxScrollExtent);
      await tester.pump();
      expect(verticalController.position.pixels, 400.0);
      expect(find.byKey(checkBoxKey), findsNothing);

      // Bring back into view, still unchecked, not kept alive.
      verticalController.jumpTo(0.0);
      await tester.pump();
      expect(verticalController.position.pixels, 0.0);
      expect(find.byKey(checkBoxKey), findsOneWidget);
      await tester.tap(find.byKey(checkBoxKey));
      await tester.pumpAndSettle();
      expect(
        tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).checkValue,
        isTrue,
      );
      expect(
        tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).wantKeepAlive,
        isTrue,
      );

      // Scroll away again, checkbox should be kept alive now.
      verticalController.jumpTo(verticalController.position.maxScrollExtent);
      await tester.pump();
      expect(verticalController.position.pixels, 400.0);
      expect(find.byKey(checkBoxKey), findsOneWidget);
      expect(
        tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).checkValue,
        isTrue,
      );
      expect(
        tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).wantKeepAlive,
        isTrue,
      );

      // Bring back into view, still checked, after being kept alive.
      verticalController.jumpTo(0.0);
      await tester.pump();
      expect(verticalController.position.pixels, 0.0);
      expect(find.byKey(checkBoxKey), findsOneWidget);
      expect(
        tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).checkValue,
        isTrue,
      );
      expect(
        tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).wantKeepAlive,
        isTrue,
      );
    });

    testWidgets('list delegate will not add automatic keep alives', (WidgetTester tester) async {
      final UniqueKey checkBoxKey = UniqueKey();
      final Widget originCell = SizedBox.square(
        dimension: 200,
        child: Center(child: KeepAliveCheckBox(key: checkBoxKey)
        ),
      );
      const Widget otherCell = SizedBox.square(dimension: 200);
      final ScrollController verticalController = ScrollController();
      addTearDown(verticalController.dispose);
      final TwoDimensionalChildListDelegate listDelegate = TwoDimensionalChildListDelegate(
        addAutomaticKeepAlives: false,
        children: <List<Widget>>[
          <Widget>[originCell, otherCell, otherCell, otherCell, otherCell],
          <Widget>[otherCell, otherCell, otherCell, otherCell, otherCell],
          <Widget>[otherCell, otherCell, otherCell, otherCell, otherCell],
          <Widget>[otherCell, otherCell, otherCell, otherCell, otherCell],
          <Widget>[otherCell, otherCell, otherCell, otherCell, otherCell],
        ],
      );
      addTearDown(listDelegate.dispose);

      await tester.pumpWidget(simpleListTest(
        delegate: listDelegate,
        verticalDetails: ScrollableDetails.vertical(controller: verticalController),
      ));
      await tester.pumpAndSettle();

      expect(verticalController.hasClients, isTrue);
      expect(verticalController.position.pixels, 0.0);
      expect(find.byKey(checkBoxKey), findsOneWidget);
      expect(
        tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).checkValue,
        isFalse,
      );
      expect(
        tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).wantKeepAlive,
        isFalse,
      );
      // Scroll away, disposing of the checkbox.
      verticalController.jumpTo(verticalController.position.maxScrollExtent);
      await tester.pump();
      expect(verticalController.position.pixels, 400.0);
      expect(find.byKey(checkBoxKey), findsNothing);

      // Bring back into view, still unchecked, not kept alive.
      verticalController.jumpTo(0.0);
      await tester.pump();
      expect(verticalController.position.pixels, 0.0);
      expect(find.byKey(checkBoxKey), findsOneWidget);
      await tester.tap(find.byKey(checkBoxKey));
      await tester.pumpAndSettle();
      expect(
        tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).checkValue,
        isTrue,
      );
      expect(
        tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).wantKeepAlive,
        isTrue,
      );

      // Scroll away again, checkbox should not be kept alive since the
      // delegate did not add automatic keep alive.
      verticalController.jumpTo(verticalController.position.maxScrollExtent);
      await tester.pump();
      expect(verticalController.position.pixels, 400.0);
      expect(find.byKey(checkBoxKey), findsNothing);

      // Bring back into view, not checked, having not been kept alive.
      verticalController.jumpTo(0.0);
      await tester.pump();
      expect(verticalController.position.pixels, 0.0);
      expect(find.byKey(checkBoxKey), findsOneWidget);
      expect(
        tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).checkValue,
        isFalse,
      );
      expect(
        tester.state<KeepAliveCheckBoxState>(find.byKey(checkBoxKey)).wantKeepAlive,
        isFalse,
      );
    });
  });

  group('TwoDimensionalScrollable', () {
    testWidgets('.of, .maybeOf', (WidgetTester tester) async {
      late BuildContext capturedContext;
      final TwoDimensionalChildBuilderDelegate delegate = TwoDimensionalChildBuilderDelegate(
        maxXIndex: 0,
        maxYIndex: 0,
        builder: (BuildContext context, ChildVicinity vicinity) {
          capturedContext = context;
          return const SizedBox.square(dimension: 200);
        }
      );
      addTearDown(delegate.dispose);

      await tester.pumpWidget(simpleBuilderTest(
        delegate: delegate,
      ));
      await tester.pumpAndSettle();

      expect(TwoDimensionalScrollable.of(capturedContext), isNotNull);
      expect(TwoDimensionalScrollable.maybeOf(capturedContext), isNotNull);

      await tester.pumpWidget(Builder(
        builder: (BuildContext context) {
          capturedContext = context;
          TwoDimensionalScrollable.of(context);
          return Container();
        }
      ));
      await tester.pumpAndSettle();
      final dynamic exception = tester.takeException();
      expect(exception, isFlutterError);
      final FlutterError error = exception as FlutterError;
      expect(error.toString(), contains(
        'TwoDimensionalScrollable.of() was called with a context that does '
        'not contain a TwoDimensionalScrollable widget.'
      ));

      expect(TwoDimensionalScrollable.maybeOf(capturedContext), isNull);
    }, variant: TargetPlatformVariant.all());

    testWidgets('horizontal and vertical getters', (WidgetTester tester) async {
      late BuildContext capturedContext;
      final TwoDimensionalChildBuilderDelegate delegate = TwoDimensionalChildBuilderDelegate(
        maxXIndex: 0,
        maxYIndex: 0,
        builder: (BuildContext context, ChildVicinity vicinity) {
          capturedContext = context;
          return const SizedBox.square(dimension: 200);
        }
      );
      addTearDown(delegate.dispose);

      await tester.pumpWidget(simpleBuilderTest(
        delegate: delegate,
      ));
      await tester.pumpAndSettle();

      final TwoDimensionalScrollableState scrollable = TwoDimensionalScrollable.of(capturedContext);
      expect(scrollable.verticalScrollable.position.pixels, 0.0);
      expect(scrollable.horizontalScrollable.position.pixels, 0.0);
    }, variant: TargetPlatformVariant.all());

    testWidgets('creates fallback ScrollControllers if not provided by ScrollableDetails', (WidgetTester tester) async {
      late BuildContext capturedContext;
      final TwoDimensionalChildBuilderDelegate delegate = TwoDimensionalChildBuilderDelegate(
        maxXIndex: 0,
        maxYIndex: 0,
        builder: (BuildContext context, ChildVicinity vicinity) {
          capturedContext = context;
          return const SizedBox.square(dimension: 200);
        }
      );
      addTearDown(delegate.dispose);

      await tester.pumpWidget(simpleBuilderTest(
        delegate: delegate,
      ));
      await tester.pumpAndSettle();

      // Vertical
      final ScrollableState vertical = Scrollable.of(capturedContext, axis: Axis.vertical);
      expect(vertical.widget.controller, isNotNull);
      // Horizontal
      final ScrollableState horizontal = Scrollable.of(capturedContext, axis: Axis.horizontal);
      expect(horizontal.widget.controller, isNotNull);
    }, variant: TargetPlatformVariant.all());

    testWidgets('asserts the axis directions do not conflict with one another', (WidgetTester tester) async {
      final List<Object> exceptions = <Object>[];
      final FlutterExceptionHandler? oldHandler = FlutterError.onError;
      FlutterError.onError = (FlutterErrorDetails details) {
        exceptions.add(details.exception);
      };
      // Horizontal mismatch
      await tester.pumpWidget(TwoDimensionalScrollable(
        horizontalDetails: const ScrollableDetails.horizontal(),
        verticalDetails: const ScrollableDetails.horizontal(),
        viewportBuilder: (BuildContext context, ViewportOffset verticalPosition, ViewportOffset horizontalPosition) {
          return Container();
        },
      ));

      // Vertical mismatch
      await tester.pumpWidget(TwoDimensionalScrollable(
        horizontalDetails: const ScrollableDetails.vertical(),
        verticalDetails: const ScrollableDetails.vertical(),
        viewportBuilder: (BuildContext context, ViewportOffset verticalPosition, ViewportOffset horizontalPosition) {
          return Container();
        },
      ));

      // Both
      await tester.pumpWidget(TwoDimensionalScrollable(
        horizontalDetails: const ScrollableDetails.vertical(),
        verticalDetails: const ScrollableDetails.horizontal(),
        viewportBuilder: (BuildContext context, ViewportOffset verticalPosition, ViewportOffset horizontalPosition) {
          return Container();
        },
      ));

      expect(exceptions.length, 3);
      for (final Object exception in exceptions) {
        expect(exception, isAssertionError);
        expect((exception as AssertionError).message, contains('are not Axis'));
      }
      FlutterError.onError = oldHandler;
    }, variant: TargetPlatformVariant.all());

    testWidgets('correctly sets restorationIds', (WidgetTester tester) async {
      late BuildContext capturedContext;
      // with restorationID set
      await tester.pumpWidget(WidgetsApp(
        color: const Color(0xFFFFFFFF),
        restorationScopeId: 'Test ID',
        builder: (BuildContext context, Widget? child) => TwoDimensionalScrollable(
          restorationId: 'Custom Restoration ID',
          horizontalDetails: const ScrollableDetails.horizontal(),
          verticalDetails: const ScrollableDetails.vertical(),
          viewportBuilder: (BuildContext context, ViewportOffset verticalPosition, ViewportOffset horizontalPosition) {
            return SizedBox.square(
              dimension: 200,
              child: Builder(
                builder: (BuildContext context) {
                  capturedContext = context;
                  return Container();
                },
              )
            );
          },
        ),
      ));
      await tester.pumpAndSettle();

      expect(
        RestorationScope.of(capturedContext).restorationId,
        'Custom Restoration ID',
      );
      expect(
        Scrollable.of(capturedContext, axis: Axis.vertical).widget.restorationId,
        'OuterVerticalTwoDimensionalScrollable',
      );
      expect(
        Scrollable.of(capturedContext, axis: Axis.horizontal).widget.restorationId,
        'InnerHorizontalTwoDimensionalScrollable',
      );

      // default restorationID
      await tester.pumpWidget(TwoDimensionalScrollable(
        horizontalDetails: const ScrollableDetails.horizontal(),
        verticalDetails: const ScrollableDetails.vertical(),
        viewportBuilder: (BuildContext context, ViewportOffset verticalPosition, ViewportOffset horizontalPosition) {
          return SizedBox.square(
            dimension: 200,
            child: Builder(
              builder: (BuildContext context) {
                capturedContext = context;
                return Container();
              },
            )
          );
        },
      ));
      await tester.pumpAndSettle();

      expect(
        RestorationScope.maybeOf(capturedContext),
        isNull,
      );
      expect(
        Scrollable.of(capturedContext, axis: Axis.vertical).widget.restorationId,
        'OuterVerticalTwoDimensionalScrollable',
      );
      expect(
        Scrollable.of(capturedContext, axis: Axis.horizontal).widget.restorationId,
        'InnerHorizontalTwoDimensionalScrollable',
      );
    }, variant: TargetPlatformVariant.all());

    testWidgets('Restoration works', (WidgetTester tester) async {
      await tester.pumpWidget(WidgetsApp(
        color: const Color(0xFFFFFFFF),
        restorationScopeId: 'Test ID',
        builder: (BuildContext context, Widget? child) => TwoDimensionalScrollable(
          restorationId: 'Custom Restoration ID',
          horizontalDetails: const ScrollableDetails.horizontal(),
          verticalDetails: const ScrollableDetails.vertical(),
          viewportBuilder: (BuildContext context, ViewportOffset verticalPosition, ViewportOffset horizontalPosition) {
            return SimpleBuilderTableViewport(
              verticalOffset: verticalPosition,
              verticalAxisDirection: AxisDirection.down,
              horizontalOffset: horizontalPosition,
              horizontalAxisDirection: AxisDirection.right,
              delegate: builderDelegate,
              mainAxis: Axis.vertical,
            );
          },
        ),
      ));
      await tester.pumpAndSettle();

      await restoreScrollAndVerify(tester);
    }, variant: TargetPlatformVariant.all());

    testWidgets('Inner Scrollables receive the correct details from TwoDimensionalScrollable', (WidgetTester tester) async {
      // Default
      late BuildContext capturedContext;
      await tester.pumpWidget(TwoDimensionalScrollable(
        horizontalDetails: const ScrollableDetails.horizontal(),
        verticalDetails: const ScrollableDetails.vertical(),
        viewportBuilder: (BuildContext context, ViewportOffset verticalPosition, ViewportOffset horizontalPosition) {
          return SizedBox.square(
            dimension: 200,
            child: Builder(
              builder: (BuildContext context) {
                capturedContext = context;
                return Container();
              },
            )
          );
        },
      ));
      await tester.pumpAndSettle();

      // Vertical
      ScrollableState vertical = Scrollable.of(capturedContext, axis: Axis.vertical);
      expect(vertical.widget.key, isNotNull);
      expect(vertical.widget.axisDirection, AxisDirection.down);
      expect(vertical.widget.controller, isNotNull);
      expect(vertical.widget.physics, isNull);
      expect(vertical.widget.clipBehavior, Clip.hardEdge);
      expect(vertical.widget.incrementCalculator, isNull);
      expect(vertical.widget.excludeFromSemantics, isFalse);
      expect(vertical.widget.restorationId, 'OuterVerticalTwoDimensionalScrollable');
      expect(vertical.widget.dragStartBehavior, DragStartBehavior.start);

      // Horizontal
      ScrollableState horizontal = Scrollable.of(capturedContext, axis: Axis.horizontal);
      expect(horizontal.widget.key, isNotNull);
      expect(horizontal.widget.axisDirection, AxisDirection.right);
      expect(horizontal.widget.controller, isNotNull);
      expect(horizontal.widget.physics, isNull);
      expect(horizontal.widget.clipBehavior, Clip.hardEdge);
      expect(horizontal.widget.incrementCalculator, isNull);
      expect(horizontal.widget.excludeFromSemantics, isFalse);
      expect(horizontal.widget.restorationId, 'InnerHorizontalTwoDimensionalScrollable');
      expect(horizontal.widget.dragStartBehavior, DragStartBehavior.start);

      // Customized
      final ScrollController horizontalController = ScrollController();
      addTearDown(horizontalController.dispose);
      final ScrollController verticalController = ScrollController();
      addTearDown(verticalController.dispose);
      double calculator(_) => 0.0;
      await tester.pumpWidget(TwoDimensionalScrollable(
        incrementCalculator: calculator,
        excludeFromSemantics: true,
        dragStartBehavior: DragStartBehavior.down,
        horizontalDetails: ScrollableDetails.horizontal(
          reverse: true,
          controller: horizontalController,
          physics: const ClampingScrollPhysics(),
          decorationClipBehavior: Clip.antiAlias,
        ),
        verticalDetails: ScrollableDetails.vertical(
          reverse: true,
          controller: verticalController,
          physics: const AlwaysScrollableScrollPhysics(),
          decorationClipBehavior: Clip.antiAliasWithSaveLayer,
        ),
        viewportBuilder: (BuildContext context, ViewportOffset verticalPosition, ViewportOffset horizontalPosition) {
          return SizedBox.square(
            dimension: 200,
            child: Builder(
              builder: (BuildContext context) {
                capturedContext = context;
                return Container();
              },
            )
          );
        },
      ));
      await tester.pumpAndSettle();

      // Vertical
      vertical = Scrollable.of(capturedContext, axis: Axis.vertical);
      expect(vertical.widget.key, isNotNull);
      expect(vertical.widget.axisDirection, AxisDirection.up);
      expect(vertical.widget.controller, verticalController);
      expect(vertical.widget.physics, const AlwaysScrollableScrollPhysics());
      expect(vertical.widget.clipBehavior, Clip.antiAliasWithSaveLayer);
      expect(
        vertical.widget.incrementCalculator!(ScrollIncrementDetails(
          type: ScrollIncrementType.line,
          metrics: verticalController.position,
        )),
        0.0,
      );
      expect(vertical.widget.excludeFromSemantics, isTrue);
      expect(vertical.widget.restorationId, 'OuterVerticalTwoDimensionalScrollable');
      expect(vertical.widget.dragStartBehavior, DragStartBehavior.down);

      // Horizontal
      horizontal = Scrollable.of(capturedContext, axis: Axis.horizontal);
      expect(horizontal.widget.key, isNotNull);
      expect(horizontal.widget.axisDirection, AxisDirection.left);
      expect(horizontal.widget.controller, horizontalController);
      expect(horizontal.widget.physics, const ClampingScrollPhysics());
      expect(horizontal.widget.clipBehavior, Clip.antiAlias);
      expect(
        horizontal.widget.incrementCalculator!(ScrollIncrementDetails(
          type: ScrollIncrementType.line,
          metrics: horizontalController.position,
        )),
        0.0,
      );
      expect(horizontal.widget.excludeFromSemantics, isTrue);
      expect(horizontal.widget.restorationId, 'InnerHorizontalTwoDimensionalScrollable');
      expect(horizontal.widget.dragStartBehavior, DragStartBehavior.down);
    }, variant: TargetPlatformVariant.all());

    group('DiagonalDragBehavior', () {
      testWidgets('none (default)', (WidgetTester tester) async {
        // Vertical and horizontal axes are locked.
        final ScrollController verticalController = ScrollController();
        addTearDown(verticalController.dispose);
        final ScrollController horizontalController = ScrollController();
        addTearDown(horizontalController.dispose);
        await tester.pumpWidget(Directionality(
          textDirection: TextDirection.ltr,
          child: simpleBuilderTest(
            verticalDetails: ScrollableDetails.vertical(controller: verticalController),
            horizontalDetails: ScrollableDetails.horizontal(controller: horizontalController),
          )
        ));
        await tester.pumpAndSettle();
        final Finder findScrollable = find.byElementPredicate((Element e) => e.widget is TwoDimensionalScrollable);

        expect(verticalController.position.pixels, 0.0);
        expect(horizontalController.position.pixels, 0.0);
        await tester.drag(findScrollable, const Offset(0.0, -100.0));
        await tester.pumpAndSettle();
        expect(verticalController.position.pixels, 80.0);
        expect(horizontalController.position.pixels, 0.0);
        await tester.drag(findScrollable, const Offset(-100.0, 0.0));
        await tester.pumpAndSettle();
        expect(verticalController.position.pixels, 80.0);
        expect(horizontalController.position.pixels, 80.0);
        // Drag with and x and y offset, only vertical will accept the gesture
        // since the x is < kTouchSlop
        await tester.drag(findScrollable, const Offset(-10.0, -50.0));
        await tester.pumpAndSettle();
        expect(verticalController.position.pixels, 110.0);
        expect(horizontalController.position.pixels, 80.0);
        // Drag with and x and y offset, only horizontal will accept the gesture
        // since the y is < kTouchSlop
        await tester.drag(findScrollable, const Offset(-50.0, -10.0));
        await tester.pumpAndSettle();
        expect(verticalController.position.pixels, 110.0);
        expect(horizontalController.position.pixels, 110.0);
        // Drag with and x and y offset, only vertical will accept the gesture
        //  x is > kTouchSlop, larger offset wins
        await tester.drag(findScrollable, const Offset(-20.0, -50.0));
        await tester.pumpAndSettle();
        expect(verticalController.position.pixels, 140.0);
        expect(horizontalController.position.pixels, 110.0);
        // Drag with and x and y offset, only horizontal will accept the gesture
        //  y is > kTouchSlop, larger offset wins
        await tester.drag(findScrollable, const Offset(-50.0, -20.0));
        await tester.pumpAndSettle();
        expect(verticalController.position.pixels, 140.0);
        expect(horizontalController.position.pixels, 140.0);
      }, variant: TargetPlatformVariant.all());

      testWidgets('weightedEvent', (WidgetTester tester) async {
        // For weighted event, the winning axis is locked for the duration of
        // the gesture.
        final ScrollController verticalController = ScrollController();
        addTearDown(verticalController.dispose);
        final ScrollController horizontalController = ScrollController();
        addTearDown(horizontalController.dispose);
        await tester.pumpWidget(Directionality(
          textDirection: TextDirection.ltr,
          child: simpleBuilderTest(
            diagonalDrag: DiagonalDragBehavior.weightedEvent,
            verticalDetails: ScrollableDetails.vertical(controller: verticalController),
            horizontalDetails: ScrollableDetails.horizontal(controller: horizontalController),
          )
        ));
        await tester.pumpAndSettle();
        final Finder findScrollable = find.byElementPredicate((Element e) => e.widget is TwoDimensionalScrollable);

        // Locks to vertical axis - simple.
        expect(verticalController.position.pixels, 0.0);
        expect(horizontalController.position.pixels, 0.0);
        TestGesture gesture = await tester.startGesture(tester.getCenter(findScrollable));
        // In this case, the vertical axis clearly wins.
        Offset secondLocation = tester.getCenter(findScrollable) + const Offset(0.0, -50.0);
        await gesture.moveTo(secondLocation);
        await tester.pumpAndSettle();
        expect(verticalController.position.pixels, 50.0);
        expect(horizontalController.position.pixels, 0.0);
        // Gesture has not ended yet, move with horizontal diff
        Offset thirdLocation = secondLocation + const Offset(-30, -15);
        await gesture.moveTo(thirdLocation);
        await tester.pumpAndSettle();
        // Only vertical diff applied
        expect(verticalController.position.pixels, 65.0);
        expect(horizontalController.position.pixels, 0.0);
        await gesture.up();
        await tester.pumpAndSettle();

        // Lock to vertical axis - scrolls diagonally until certain
        verticalController.jumpTo(0.0);
        horizontalController.jumpTo(0.0);
        await tester.pump();
        expect(verticalController.position.pixels, 0.0);
        expect(horizontalController.position.pixels, 0.0);
        gesture = await tester.startGesture(tester.getCenter(findScrollable));
        // In this case, the no one clearly wins, so it moves diagonally.
        secondLocation = tester.getCenter(findScrollable) + const Offset(-50.0, -50.0);
        await gesture.moveTo(secondLocation);
        await tester.pumpAndSettle();
        expect(verticalController.position.pixels, 50.0);
        expect(horizontalController.position.pixels, 50.0);
        // Gesture has not ended yet, move clearly indicating vertical
        thirdLocation = secondLocation + const Offset(-20, -50);
        await gesture.moveTo(thirdLocation);
        await tester.pumpAndSettle();
        // Only vertical diff applied
        expect(verticalController.position.pixels, 100.0);
        expect(horizontalController.position.pixels, 50.0);
        // Gesture has not ended yet, and vertical axis has won for the gesture
        // continue only vertical scrolling.
        Offset fourthLocation = thirdLocation + const Offset(-30, -30);
        await gesture.moveTo(fourthLocation);
        await tester.pumpAndSettle();
        // Only vertical diff applied
        expect(verticalController.position.pixels, 130.0);
        expect(horizontalController.position.pixels, 50.0);
        await gesture.up();
        await tester.pumpAndSettle();

        // Locks to horizontal axis - simple.
        verticalController.jumpTo(0.0);
        horizontalController.jumpTo(0.0);
        await tester.pump();
        expect(verticalController.position.pixels, 0.0);
        expect(horizontalController.position.pixels, 0.0);
        gesture = await tester.startGesture(tester.getCenter(findScrollable));
        // In this case, the horizontal axis clearly wins.
        secondLocation = tester.getCenter(findScrollable) + const Offset(-50.0, 0.0);
        await gesture.moveTo(secondLocation);
        await tester.pumpAndSettle();
        expect(verticalController.position.pixels, 0.0);
        expect(horizontalController.position.pixels, 50.0);
        // Gesture has not ended yet, move with vertical diff
        thirdLocation = secondLocation + const Offset(-15, -30);
        await gesture.moveTo(thirdLocation);
        await tester.pumpAndSettle();
        // Only vertical diff applied
        expect(verticalController.position.pixels, 0.0);
        expect(horizontalController.position.pixels, 65.0);
        await gesture.up();
        await tester.pumpAndSettle();

        // Lock to horizontal axis - scrolls diagonally until certain
        verticalController.jumpTo(0.0);
        horizontalController.jumpTo(0.0);
        await tester.pump();
        expect(verticalController.position.pixels, 0.0);
        expect(horizontalController.position.pixels, 0.0);
        gesture = await tester.startGesture(tester.getCenter(findScrollable));
        // In this case, the no one clearly wins, so it moves diagonally.
        secondLocation = tester.getCenter(findScrollable) + const Offset(-50.0, -50.0);
        await gesture.moveTo(secondLocation);
        await tester.pumpAndSettle();
        expect(verticalController.position.pixels, 50.0);
        expect(horizontalController.position.pixels, 50.0);
        // Gesture has not ended yet, move clearly indicating horizontal
        thirdLocation = secondLocation + const Offset(-50, -20);
        await gesture.moveTo(thirdLocation);
        await tester.pumpAndSettle();
        // Only horizontal diff applied
        expect(verticalController.position.pixels, 50.0);
        expect(horizontalController.position.pixels, 100.0);
        // Gesture has not ended yet, and horizontal axis has won for the gesture
        // continue only horizontal scrolling.
        fourthLocation = thirdLocation + const Offset(-30, -30);
        await gesture.moveTo(fourthLocation);
        await tester.pumpAndSettle();
        // Only horizontal diff applied
        expect(verticalController.position.pixels, 50.0);
        expect(horizontalController.position.pixels, 130.0);
        await gesture.up();
        await tester.pumpAndSettle();
      }, variant: TargetPlatformVariant.all());

      testWidgets('weightedContinuous', (WidgetTester tester) async {
        // For weighted continuous, the winning axis can change if the axis
        // differential for the gesture exceeds kTouchSlop. So it can lock, and
        // remain locked, if the user maintains a generally straight gesture,
        // otherwise it will unlock and re-evaluate.
        final ScrollController verticalController = ScrollController();
        addTearDown(verticalController.dispose);
        final ScrollController horizontalController = ScrollController();
        addTearDown(horizontalController.dispose);
        await tester.pumpWidget(Directionality(
          textDirection: TextDirection.ltr,
          child: simpleBuilderTest(
            diagonalDrag: DiagonalDragBehavior.weightedContinuous,
            verticalDetails: ScrollableDetails.vertical(controller: verticalController),
            horizontalDetails: ScrollableDetails.horizontal(controller: horizontalController),
          )
        ));
        await tester.pumpAndSettle();
        final Finder findScrollable = find.byElementPredicate((Element e) => e.widget is TwoDimensionalScrollable);

        // Locks to vertical, and then unlocks, resets to horizontal, then
        // unlocks and scrolls diagonally.
        expect(verticalController.position.pixels, 0.0);
        expect(horizontalController.position.pixels, 0.0);
        final TestGesture gesture = await tester.startGesture(tester.getCenter(findScrollable));
        // In this case, the vertical axis clearly wins.
        final Offset secondLocation = tester.getCenter(findScrollable) + const Offset(0.0, -50.0);
        await gesture.moveTo(secondLocation);
        await tester.pumpAndSettle();
        expect(verticalController.position.pixels, 50.0);
        expect(horizontalController.position.pixels, 0.0);
        // Gesture has not ended yet, move with horizontal diff, but still
        // dominant vertical
        final Offset thirdLocation = secondLocation + const Offset(-15, -50);
        await gesture.moveTo(thirdLocation);
        await tester.pumpAndSettle();
        // Only vertical diff applied since kTouchSlop was not exceeded in the
        // horizontal axis from one drag event to the next.
        expect(verticalController.position.pixels, 100.0);
        expect(horizontalController.position.pixels, 0.0);
        // Gesture has not ended yet, move with unlocking horizontal diff
        final Offset fourthLocation = thirdLocation + const Offset(-50, -15);
        await gesture.moveTo(fourthLocation);
        await tester.pumpAndSettle();
        // Only horizontal diff applied
        expect(verticalController.position.pixels, 100.0);
        expect(horizontalController.position.pixels, 50.0);
        // Gesture has not ended yet, move with unlocking diff that results in
        // diagonal move since neither wins.
        final Offset fifthLocation = fourthLocation + const Offset(-50, -50);
        await gesture.moveTo(fifthLocation);
        await tester.pumpAndSettle();
        // Only horizontal diff applied
        expect(verticalController.position.pixels, 150.0);
        expect(horizontalController.position.pixels, 100.0);
        await gesture.up();
        await tester.pumpAndSettle();
      }, variant: TargetPlatformVariant.all());

      testWidgets('free', (WidgetTester tester) async {
        // For free, anything goes.
        final ScrollController verticalController = ScrollController();
        addTearDown(verticalController.dispose);
        final ScrollController horizontalController = ScrollController();
        addTearDown(horizontalController.dispose);
        await tester.pumpWidget(Directionality(
          textDirection: TextDirection.ltr,
          child: simpleBuilderTest(
            diagonalDrag: DiagonalDragBehavior.free,
            verticalDetails: ScrollableDetails.vertical(controller: verticalController),
            horizontalDetails: ScrollableDetails.horizontal(controller: horizontalController),
          )
        ));
        await tester.pumpAndSettle();
        final Finder findScrollable = find.byElementPredicate((Element e) => e.widget is TwoDimensionalScrollable);

        // Nothing locks.
        expect(verticalController.position.pixels, 0.0);
        expect(horizontalController.position.pixels, 0.0);
        final TestGesture gesture = await tester.startGesture(tester.getCenter(findScrollable));
        final Offset secondLocation = tester.getCenter(findScrollable) + const Offset(0.0, -50.0);
        await gesture.moveTo(secondLocation);
        await tester.pumpAndSettle();
        expect(verticalController.position.pixels, 50.0);
        expect(horizontalController.position.pixels, 0.0);
        final Offset thirdLocation = secondLocation + const Offset(-15, -50);
        await gesture.moveTo(thirdLocation);
        await tester.pumpAndSettle();
        expect(verticalController.position.pixels, 100.0);
        expect(horizontalController.position.pixels, 15.0);
        final Offset fourthLocation = thirdLocation + const Offset(-50, -15);
        await gesture.moveTo(fourthLocation);
        await tester.pumpAndSettle();
        expect(verticalController.position.pixels, 115.0);
        expect(horizontalController.position.pixels, 65.0);
        final Offset fifthLocation = fourthLocation + const Offset(-50, -50);
        await gesture.moveTo(fifthLocation);
        await tester.pumpAndSettle();
        expect(verticalController.position.pixels, 165.0);
        expect(horizontalController.position.pixels, 115.0);
        await gesture.up();
        await tester.pumpAndSettle();
      });
    });
  });

  testWidgets('TwoDimensionalViewport asserts against axes mismatch', (WidgetTester tester) async {
    // Horizontal mismatch
    expect(
      () {
        final ViewportOffset verticalOffset = ViewportOffset.fixed(0.0);
        addTearDown(verticalOffset.dispose);
        final ViewportOffset horizontalOffset = ViewportOffset.fixed(0.0);
        addTearDown(horizontalOffset.dispose);

        SimpleBuilderTableViewport(
          verticalOffset: verticalOffset,
          verticalAxisDirection: AxisDirection.left,
          horizontalOffset: horizontalOffset,
          horizontalAxisDirection: AxisDirection.right,
          delegate: builderDelegate,
          mainAxis: Axis.vertical,
        );
      },
      throwsA(
        isA<AssertionError>().having(
          (AssertionError error) => error.toString(),
          'description',
          contains('AxisDirection is not Axis.'),
        ),
      ),
    );

    // Vertical mismatch
    expect(
      () {
        final ViewportOffset verticalOffset = ViewportOffset.fixed(0.0);
        addTearDown(verticalOffset.dispose);
        final ViewportOffset horizontalOffset = ViewportOffset.fixed(0.0);
        addTearDown(horizontalOffset.dispose);

        SimpleBuilderTableViewport(
          verticalOffset: verticalOffset,
          verticalAxisDirection: AxisDirection.up,
          horizontalOffset: horizontalOffset,
          horizontalAxisDirection: AxisDirection.down,
          delegate: builderDelegate,
          mainAxis: Axis.vertical,
        );
      },
      throwsA(
        isA<AssertionError>().having(
          (AssertionError error) => error.toString(),
          'description',
          contains('AxisDirection is not Axis.'),
        ),
      ),
    );

    // Both
    expect(
      () {
        final ViewportOffset verticalOffset = ViewportOffset.fixed(0.0);
        addTearDown(verticalOffset.dispose);
        final ViewportOffset horizontalOffset = ViewportOffset.fixed(0.0);
        addTearDown(horizontalOffset.dispose);

        SimpleBuilderTableViewport(
          verticalOffset: verticalOffset,
          verticalAxisDirection: AxisDirection.left,
          horizontalOffset: horizontalOffset,
          horizontalAxisDirection: AxisDirection.down,
          delegate: builderDelegate,
          mainAxis: Axis.vertical,
        );
      },
      throwsA(
        isA<AssertionError>().having(
          (AssertionError error) => error.toString(),
          'description',
          contains('AxisDirection is not Axis.'),
        ),
      ),
    );
  });

  test('TwoDimensionalViewportParentData', () {
    // Default vicinity is invalid
    final TwoDimensionalViewportParentData parentData = TwoDimensionalViewportParentData();
    expect(parentData.vicinity, ChildVicinity.invalid);

    // toString
    parentData
      ..vicinity = const ChildVicinity(xIndex: 10, yIndex: 10)
      ..paintOffset = const Offset(20.0, 20.0)
      ..layoutOffset = const Offset(20.0, 20.0);
    expect(
      parentData.toString(),
      'vicinity=(xIndex: 10, yIndex: 10); layoutOffset=Offset(20.0, 20.0); '
      'paintOffset=Offset(20.0, 20.0); not visible; ',
    );
  });

  test('ChildVicinity comparable', () {
    const ChildVicinity baseVicinity = ChildVicinity(xIndex: 0, yIndex: 0);
    const ChildVicinity sameXVicinity = ChildVicinity(xIndex: 0, yIndex: 2);
    const ChildVicinity sameYVicinity = ChildVicinity(xIndex: 3, yIndex: 0);
    const ChildVicinity sameNothingVicinity = ChildVicinity(xIndex: 20, yIndex: 30);
    // ==
    expect(baseVicinity == baseVicinity, isTrue);
    expect(baseVicinity == sameXVicinity, isFalse);
    expect(baseVicinity == sameYVicinity, isFalse);
    expect(baseVicinity == sameNothingVicinity, isFalse);

    // compareTo
    expect(baseVicinity.compareTo(baseVicinity), 0);
    expect(baseVicinity.compareTo(sameXVicinity), -2);
    expect(baseVicinity.compareTo(sameYVicinity), -3);
    expect(baseVicinity.compareTo(sameNothingVicinity), -20);

    // toString
    expect(baseVicinity.toString(), '(xIndex: 0, yIndex: 0)');
    expect(sameXVicinity.toString(), '(xIndex: 0, yIndex: 2)');
    expect(sameYVicinity.toString(), '(xIndex: 3, yIndex: 0)');
    expect(sameNothingVicinity.toString(), '(xIndex: 20, yIndex: 30)');
  });

  group('RenderTwoDimensionalViewport', () {
    testWidgets('asserts against axes mismatch', (WidgetTester tester) async {
      // Horizontal mismatch
      expect(
        () {
          final ViewportOffset verticalOffset = ViewportOffset.fixed(0.0);
          addTearDown(verticalOffset.dispose);
          final ViewportOffset horizontalOffset = ViewportOffset.fixed(0.0);
          addTearDown(horizontalOffset.dispose);

          RenderSimpleBuilderTableViewport(
            verticalOffset: verticalOffset,
            verticalAxisDirection: AxisDirection.left,
            horizontalOffset: horizontalOffset,
            horizontalAxisDirection: AxisDirection.right,
            delegate: builderDelegate,
            mainAxis: Axis.vertical,
            childManager: _NullBuildContext(),
          );
        },
        throwsA(
          isA<AssertionError>().having(
            (AssertionError error) => error.toString(),
            'description',
            contains('AxisDirection is not Axis.'),
          ),
        ),
      );

      // Vertical mismatch
      expect(
        () {
          final ViewportOffset verticalOffset = ViewportOffset.fixed(0.0);
          addTearDown(verticalOffset.dispose);
          final ViewportOffset horizontalOffset = ViewportOffset.fixed(0.0);
          addTearDown(horizontalOffset.dispose);

          RenderSimpleBuilderTableViewport(
            verticalOffset: verticalOffset,
            verticalAxisDirection: AxisDirection.up,
            horizontalOffset: horizontalOffset,
            horizontalAxisDirection: AxisDirection.down,
            delegate: builderDelegate,
            mainAxis: Axis.vertical,
            childManager: _NullBuildContext(),
          );
        },
        throwsA(
          isA<AssertionError>().having(
            (AssertionError error) => error.toString(),
            'description',
            contains('AxisDirection is not Axis.'),
          ),
        ),
      );

      // Both
      expect(
        () {
          final ViewportOffset verticalOffset = ViewportOffset.fixed(0.0);
          addTearDown(verticalOffset.dispose);
          final ViewportOffset horizontalOffset = ViewportOffset.fixed(0.0);
          addTearDown(horizontalOffset.dispose);

          RenderSimpleBuilderTableViewport(
            verticalOffset: verticalOffset,
            verticalAxisDirection: AxisDirection.left,
            horizontalOffset: horizontalOffset,
            horizontalAxisDirection: AxisDirection.down,
            delegate: builderDelegate,
            mainAxis: Axis.vertical,
            childManager: _NullBuildContext(),
          );
        },
        throwsA(
          isA<AssertionError>().having(
            (AssertionError error) => error.toString(),
            'description',
            contains('AxisDirection is not Axis.'),
          ),
        ),
      );
    });

    testWidgets('getters', (WidgetTester tester) async {
      final UniqueKey childKey = UniqueKey();
      final TwoDimensionalChildBuilderDelegate delegate = TwoDimensionalChildBuilderDelegate(
        maxXIndex: 0,
        maxYIndex: 0,
        builder: (BuildContext context, ChildVicinity vicinity) {
          return SizedBox.square(key: childKey, dimension: 200);
        }
      );
      addTearDown(delegate.dispose);
      final ViewportOffset verticalOffset = ViewportOffset.fixed(10.0);
      addTearDown(verticalOffset.dispose);
      final ViewportOffset horizontalOffset = ViewportOffset.fixed(20.0);
      addTearDown(horizontalOffset.dispose);

      final RenderSimpleBuilderTableViewport renderViewport = RenderSimpleBuilderTableViewport(
        verticalOffset: verticalOffset,
        verticalAxisDirection: AxisDirection.down,
        horizontalOffset: horizontalOffset,
        horizontalAxisDirection: AxisDirection.right,
        delegate: delegate,
        mainAxis: Axis.vertical,
        childManager: _NullBuildContext(),
      );
      addTearDown(renderViewport.dispose);

      expect(renderViewport.clipBehavior, Clip.hardEdge);
      expect(renderViewport.cacheExtent, RenderAbstractViewport.defaultCacheExtent);
      expect(renderViewport.isRepaintBoundary, isTrue);
      expect(renderViewport.sizedByParent, isTrue);
      // No size yet, should assert.
      expect(
        () {
          renderViewport.viewportDimension;
        },
        throwsA(
          isA<AssertionError>().having(
            (AssertionError error) => error.toString(),
            'description',
            contains('hasSize'),
          ),
        ),
      );
      expect(renderViewport.horizontalOffset.pixels, 20.0);
      expect(renderViewport.horizontalAxisDirection, AxisDirection.right);
      expect(renderViewport.verticalOffset.pixels, 10.0);
      expect(renderViewport.verticalAxisDirection, AxisDirection.down);
      expect(renderViewport.delegate, delegate);
      expect(renderViewport.mainAxis, Axis.vertical);

      // viewportDimension when hasSize
      await tester.pumpWidget(simpleBuilderTest(
        delegate: delegate,
      ));
      await tester.pumpAndSettle();
      final RenderTwoDimensionalViewport viewport = getViewport(tester, childKey);
      expect(viewport.viewportDimension, const Size(800.0, 600.0));
    }, variant: TargetPlatformVariant.all());

    testWidgets('Children are organized according to mainAxis', (WidgetTester tester) async {
      final Map<ChildVicinity, UniqueKey> childKeys = <ChildVicinity, UniqueKey>{};
      final TwoDimensionalChildBuilderDelegate delegate = TwoDimensionalChildBuilderDelegate(
        maxXIndex: 5,
        maxYIndex: 5,
        builder: (BuildContext context, ChildVicinity vicinity) {
          childKeys[vicinity] = childKeys[vicinity] ?? UniqueKey();
          return SizedBox.square(key: childKeys[vicinity], dimension: 200);
        }
      );
      addTearDown(delegate.dispose);
      TwoDimensionalViewportParentData parentDataOf(RenderBox child) {
        return child.parentData! as TwoDimensionalViewportParentData;
      }
      // mainAxis is vertical (default)
      await tester.pumpWidget(simpleBuilderTest(
        delegate: delegate,
      ));
      await tester.pumpAndSettle();
      RenderTwoDimensionalViewport viewport = getViewport(
        tester,
        childKeys.values.first,
      );
      expect(viewport.mainAxis, Axis.vertical);
      // first child
      expect(
        parentDataOf(viewport.firstChild!).vicinity,
        const ChildVicinity(xIndex: 0, yIndex: 0),
      );
      expect(
        parentDataOf(viewport.childAfter(viewport.firstChild!)!).vicinity,
        const ChildVicinity(xIndex: 1, yIndex: 0),
      );
      expect(
        viewport.childBefore(viewport.firstChild!),
        isNull,
      );
      // last child
      expect(
        parentDataOf(viewport.lastChild!).vicinity,
        const ChildVicinity(xIndex: 4, yIndex: 3),
      );
      expect(
        viewport.childAfter(viewport.lastChild!),
        isNull,
      );
      expect(
        parentDataOf(viewport.childBefore(viewport.lastChild!)!).vicinity,
        const ChildVicinity(xIndex: 3, yIndex: 3),
      );

      // mainAxis is horizontal
      await tester.pumpWidget(simpleBuilderTest(
        delegate: delegate,
        mainAxis: Axis.horizontal,
      ));
      await tester.pumpAndSettle();
      viewport = getViewport(tester, childKeys.values.first);
      expect(viewport.mainAxis, Axis.horizontal);
      // first child
      expect(
        parentDataOf(viewport.firstChild!).vicinity,
        const ChildVicinity(xIndex: 0, yIndex: 0),
      );
      expect(
        parentDataOf(viewport.childAfter(viewport.firstChild!)!).vicinity,
        const ChildVicinity(xIndex: 0, yIndex: 1),
      );
      expect(
        viewport.childBefore(viewport.firstChild!),
        isNull,
      );
      // last child
      expect(
        parentDataOf(viewport.lastChild!).vicinity,
        const ChildVicinity(xIndex: 4, yIndex: 3),
      );
      expect(
        viewport.childAfter(viewport.lastChild!),
        isNull,
      );
      expect(
        parentDataOf(viewport.childBefore(viewport.lastChild!)!).vicinity,
        const ChildVicinity(xIndex: 4, yIndex: 2),
      );
    }, variant: TargetPlatformVariant.all());

    testWidgets('sets up parent data', (WidgetTester tester) async {
      // Also tests computeAbsolutePaintOffsetFor & computeChildPaintExtent
      // Regression test for https://github.com/flutter/flutter/issues/128723
      final Map<ChildVicinity, UniqueKey> childKeys = <ChildVicinity, UniqueKey>{};
      final TwoDimensionalChildBuilderDelegate delegate = TwoDimensionalChildBuilderDelegate(
        maxXIndex: 5,
        maxYIndex: 5,
        builder: (BuildContext context, ChildVicinity vicinity) {
          childKeys[vicinity] = childKeys[vicinity] ?? UniqueKey();
          return SizedBox.square(key: childKeys[vicinity], dimension: 200);
        }
      );
      addTearDown(delegate.dispose);

      // parent data is TwoDimensionalViewportParentData
      TwoDimensionalViewportParentData parentDataOf(RenderBox child) {
        return child.parentData! as TwoDimensionalViewportParentData;
      }

      await tester.pumpWidget(simpleBuilderTest(
        delegate: delegate,
        useCacheExtent: true,
      ));
      await tester.pumpAndSettle();

      RenderTwoDimensionalViewport viewport = getViewport(
        tester,
        childKeys.values.first,
      );

      // first child
      // parentData is computed correctly - normal axes
      // - layoutOffset, paintOffset, isVisible, ChildVicinity
      TwoDimensionalViewportParentData childParentData = parentDataOf(viewport.firstChild!);
      expect(childParentData.vicinity, const ChildVicinity(xIndex: 0, yIndex: 0));
      expect(childParentData.isVisible, isTrue);
      expect(childParentData.paintOffset, Offset.zero);
      expect(childParentData.layoutOffset, Offset.zero);
      // The last child is in the cache extent, and should not be visible.
      childParentData = parentDataOf(viewport.lastChild!);
      expect(childParentData.vicinity, const ChildVicinity(xIndex: 5, yIndex: 5));
      expect(childParentData.isVisible, isFalse);
      expect(childParentData.paintOffset, const Offset(1000.0, 1000.0));
      expect(childParentData.layoutOffset, const Offset(1000.0, 1000.0));

      // parentData is computed correctly - reverse axes
      // - vertical reverse
      await tester.pumpWidget(simpleBuilderTest(
        delegate: delegate,
        verticalDetails: const ScrollableDetails.vertical(reverse: true),
      ));
      await tester.pumpAndSettle();

      viewport = getViewport(tester, childKeys.values.first);

      childParentData = parentDataOf(viewport.firstChild!);
      expect(childParentData.vicinity, const ChildVicinity(xIndex: 0, yIndex: 0));
      expect(childParentData.isVisible, isTrue);
      expect(childParentData.paintOffset, const Offset(0.0, 400.0));
      expect(childParentData.layoutOffset, Offset.zero);
      // The last child is in the cache extent, and should not be visible.
      childParentData = parentDataOf(viewport.lastChild!);
      expect(childParentData.vicinity, const ChildVicinity(xIndex: 5, yIndex: 5));
      expect(childParentData.isVisible, isFalse);
      expect(childParentData.paintOffset, const Offset(1000.0, -600.0));
      expect(childParentData.layoutOffset, const Offset(1000.0, 1000.0));

      // - horizontal reverse
      await tester.pumpWidget(simpleBuilderTest(
        delegate: delegate,
        horizontalDetails: const ScrollableDetails.horizontal(reverse: true),
      ));
      await tester.pumpAndSettle();

      viewport = getViewport(tester, childKeys.values.first);

      childParentData = parentDataOf(viewport.firstChild!);
      expect(childParentData.vicinity, const ChildVicinity(xIndex: 0, yIndex: 0));
      expect(childParentData.isVisible, isTrue);
      expect(childParentData.paintOffset, const Offset(600.0, 0.0));
      expect(childParentData.layoutOffset, Offset.zero);
      // The last child is in the cache extent, and should not be visible.
      childParentData = parentDataOf(viewport.lastChild!);
      expect(childParentData.vicinity, const ChildVicinity(xIndex: 5, yIndex: 5));
      expect(childParentData.isVisible, isFalse);
      expect(childParentData.paintOffset, const Offset(-400.0, 1000.0));
      expect(childParentData.layoutOffset, const Offset(1000.0, 1000.0));

      // - both reverse
      await tester.pumpWidget(simpleBuilderTest(
        delegate: delegate,
        horizontalDetails: const ScrollableDetails.horizontal(reverse: true),
        verticalDetails: const ScrollableDetails.vertical(reverse: true),
      ));
      await tester.pumpAndSettle();

      viewport = getViewport(tester, childKeys.values.first);

      childParentData = parentDataOf(viewport.firstChild!);
      expect(childParentData.vicinity, const ChildVicinity(xIndex: 0, yIndex: 0));
      expect(childParentData.isVisible, isTrue);
      expect(childParentData.paintOffset, const Offset(600.0, 400.0));
      expect(childParentData.layoutOffset, Offset.zero);
      // The last child is in the cache extent, and should not be visible.
      childParentData = parentDataOf(viewport.lastChild!);
      expect(childParentData.vicinity, const ChildVicinity(xIndex: 5, yIndex: 5));
      expect(childParentData.isVisible, isFalse);
      expect(childParentData.paintOffset, const Offset(-400.0, -600.0));
      expect(childParentData.layoutOffset, const Offset(1000.0, 1000.0));

      // Change the scroll positions to test partially visible.
      final ScrollController verticalController = ScrollController();
      addTearDown(verticalController.dispose);
      final ScrollController horizontalController = ScrollController();
      addTearDown(horizontalController.dispose);
      await tester.pumpWidget(simpleBuilderTest(
        delegate: delegate,
        horizontalDetails: ScrollableDetails.horizontal(controller: horizontalController),
        verticalDetails: ScrollableDetails.vertical(controller: verticalController),
      ));
      await tester.pumpAndSettle();
      verticalController.jumpTo(50.0);
      horizontalController.jumpTo(50.0);
      await tester.pump();

      viewport = getViewport(tester, childKeys.values.first);

      childParentData = parentDataOf(viewport.firstChild!);
      expect(childParentData.vicinity, const ChildVicinity(xIndex: 0, yIndex: 0));
      expect(childParentData.isVisible, isTrue);
      expect(childParentData.paintOffset, const Offset(-50.0, -50.0));
      expect(childParentData.layoutOffset, const Offset(-50.0, -50.0));
    }, variant: TargetPlatformVariant.all());

    testWidgets('debugDescribeChildren', (WidgetTester tester) async {
      final Map<ChildVicinity, UniqueKey> childKeys = <ChildVicinity, UniqueKey>{};
      final TwoDimensionalChildBuilderDelegate delegate = TwoDimensionalChildBuilderDelegate(
        maxXIndex: 5,
        maxYIndex: 5,
        builder: (BuildContext context, ChildVicinity vicinity) {
          childKeys[vicinity] = childKeys[vicinity] ?? UniqueKey();
          return SizedBox.square(key: childKeys[vicinity], dimension: 200);
        }
      );
      addTearDown(delegate.dispose);

      await tester.pumpWidget(simpleBuilderTest(
        delegate: delegate,
      ));
      await tester.pumpAndSettle();

      final RenderTwoDimensionalViewport viewport = getViewport(
        tester,
        childKeys.values.first,
      );
      final List<DiagnosticsNode> result = viewport.debugDescribeChildren();
      expect(result.length, 20);
      expect(
        result.first.toString(),
        equalsIgnoringHashCodes('(xIndex: 0, yIndex: 0): RenderRepaintBoundary#00000'),
      );
      expect(
        result.last.toString(),
        equalsIgnoringHashCodes('(xIndex: 4, yIndex: 3): RenderRepaintBoundary#00000 NEEDS-PAINT'),
      );
    }, variant: TargetPlatformVariant.all());

    testWidgets('asserts that both axes are bounded', (WidgetTester tester) async {
      final List<Object> exceptions = <Object>[];
      final FlutterExceptionHandler? oldHandler = FlutterError.onError;
      FlutterError.onError = (FlutterErrorDetails details) {
        exceptions.add(details.exception);
      };
      // Compose unbounded - vertical axis
      await tester.pumpWidget(WidgetsApp(
        color: const Color(0xFFFFFFFF),
        builder: (BuildContext context, Widget? child) => Column(
          children: <Widget>[
            SimpleBuilderTableView(delegate: builderDelegate)
          ]
        ),
      ));
      await tester.pumpAndSettle();
      FlutterError.onError = oldHandler;
      expect(exceptions.isNotEmpty, isTrue);
      expect((exceptions[0] as FlutterError).message, contains('unbounded'));

      exceptions.clear();
      FlutterError.onError = (FlutterErrorDetails details) {
        exceptions.add(details.exception);
      };
      // Compose unbounded - horizontal axis
      await tester.pumpWidget(WidgetsApp(
        color: const Color(0xFFFFFFFF),
        builder: (BuildContext context, Widget? child) => Row(
          children: <Widget>[
            SimpleBuilderTableView(delegate: builderDelegate)
          ]
        ),
      ));
      await tester.pumpAndSettle();
      FlutterError.onError = oldHandler;
      expect(exceptions.isNotEmpty, isTrue);
      expect((exceptions[0] as FlutterError).message, contains('unbounded'));
    }, variant: TargetPlatformVariant.all());

    testWidgets('computeDryLayout asserts axes are bounded', (WidgetTester tester) async {
      final UniqueKey childKey = UniqueKey();
      final TwoDimensionalChildBuilderDelegate delegate = TwoDimensionalChildBuilderDelegate(
        maxXIndex: 0,
        maxYIndex: 0,
        builder: (BuildContext context, ChildVicinity vicinity) {
          return SizedBox.square(key: childKey, dimension: 200);
        }
      );
      addTearDown(delegate.dispose);

      // Call computeDryLayout with unbounded constraints
      await tester.pumpWidget(simpleBuilderTest(delegate: delegate));
      final RenderTwoDimensionalViewport viewport = getViewport(
        tester,
        childKey,
      );
      expect(
        () {
          viewport.computeDryLayout(const BoxConstraints());
        },
        throwsA(
          isA<FlutterError>().having(
            (FlutterError error) => error.message,
            'error.message',
            contains('unbounded'),
          ),
        ),
      );
    }, variant: TargetPlatformVariant.all());

    testWidgets('correctly resizes dimensions', (WidgetTester tester) async {
      final UniqueKey childKey = UniqueKey();
      final TwoDimensionalChildBuilderDelegate delegate = TwoDimensionalChildBuilderDelegate(
        maxXIndex: 0,
        maxYIndex: 0,
        builder: (BuildContext context, ChildVicinity vicinity) {
          return SizedBox.square(key: childKey, dimension: 200);
        }
      );
      addTearDown(delegate.dispose);

      await tester.pumpWidget(simpleBuilderTest(
        delegate: delegate,
      ));
      await tester.pumpAndSettle();
      RenderTwoDimensionalViewport viewport = getViewport(
        tester,
        childKey,
      );
      expect(viewport.viewportDimension, const Size(800.0, 600.0));
      tester.view.physicalSize = const Size(300.0, 300.0);
      tester.view.devicePixelRatio = 1;
      await tester.pumpWidget(simpleBuilderTest(
        delegate: delegate,
      ));
      await tester.pumpAndSettle();
      viewport = getViewport(tester, childKey);
      expect(viewport.viewportDimension, const Size(300.0, 300.0));
      tester.view.resetPhysicalSize();
      tester.view.resetDevicePixelRatio();
    }, variant: TargetPlatformVariant.all());

    testWidgets('Rebuilds when delegate changes', (WidgetTester tester) async {
      final UniqueKey firstChildKey = UniqueKey();
      final TwoDimensionalChildBuilderDelegate delegate = TwoDimensionalChildBuilderDelegate(
        maxXIndex: 0,
        maxYIndex: 0,
        addRepaintBoundaries: false,
        builder: (BuildContext context, ChildVicinity vicinity) {
          return SizedBox.square(key: firstChildKey, dimension: 200);
        }
      );
      addTearDown(delegate.dispose);

      await tester.pumpWidget(simpleBuilderTest(
        delegate: delegate,
      ));
      RenderTwoDimensionalViewport viewport = getViewport(tester, firstChildKey);
      expect(viewport.firstChild, tester.renderObject<RenderBox>(find.byKey(firstChildKey)));
      // New delegate
      final UniqueKey newChildKey = UniqueKey();
      final TwoDimensionalChildBuilderDelegate newDelegate = TwoDimensionalChildBuilderDelegate(
        maxXIndex: 0,
        maxYIndex: 0,
        addRepaintBoundaries: false,
        builder: (BuildContext context, ChildVicinity vicinity) {
          return Container(key: newChildKey, height: 300, width: 300, color: const Color(0xFFFFFFFF));
        }
      );
      addTearDown(() => newDelegate.dispose());

      await tester.pumpWidget(simpleBuilderTest(
        delegate: newDelegate,
      ));
      viewport = getViewport(tester, newChildKey);
      expect(firstChildKey, isNot(newChildKey));
      expect(find.byKey(firstChildKey), findsNothing);
      expect(find.byKey(newChildKey), findsOneWidget);
      expect(viewport.firstChild, tester.renderObject<RenderBox>(find.byKey(newChildKey)));
    }, variant: TargetPlatformVariant.all());

    testWidgets('hitTestChildren', (WidgetTester tester) async {
      final List<ChildVicinity> taps = <ChildVicinity>[];
      final Map<ChildVicinity, UniqueKey> childKeys = <ChildVicinity, UniqueKey>{};
      final TwoDimensionalChildBuilderDelegate delegate = TwoDimensionalChildBuilderDelegate(
        maxXIndex: 19,
        maxYIndex: 19,
        builder: (BuildContext context, ChildVicinity vicinity) {
          childKeys[vicinity] = childKeys[vicinity] ?? UniqueKey();
          return SizedBox.square(
            dimension: 200,
            child: Center(
              child: FloatingActionButton(
                key: childKeys[vicinity],
                onPressed: () {
                  taps.add(vicinity);
                },
              ),
            ),
          );
        }
      );
      addTearDown(delegate.dispose);

      await tester.pumpWidget(simpleBuilderTest(
        delegate: delegate,
        useCacheExtent: true, // Untappable children are rendered in the cache extent
      ));
      await tester.pumpAndSettle();
      // Regular orientation
      // Offset at center of first child
      await tester.tapAt(const Offset(100.0, 100.0));
      await tester.pump();
      expect(taps.contains(const ChildVicinity(xIndex: 0, yIndex: 0)), isTrue);
      // Offset by child location
      await tester.tap(find.byKey(childKeys[const ChildVicinity(xIndex: 2, yIndex: 2)]!));
      await tester.pump();
      expect(taps.contains(const ChildVicinity(xIndex: 2, yIndex: 2)), isTrue);
      // Offset out of bounds
      await tester.tap(
        find.byKey(childKeys[const ChildVicinity(xIndex: 5, yIndex: 5)]!),
        warnIfMissed: false,
      );
      await tester.pump();
      expect(taps.contains(const ChildVicinity(xIndex: 5, yIndex: 5)), isFalse);

      // Reversed
      await tester.pumpWidget(simpleBuilderTest(
        delegate: delegate,
        verticalDetails: const ScrollableDetails.vertical(reverse: true),
        horizontalDetails: const ScrollableDetails.horizontal(reverse: true),
        useCacheExtent: true, // Untappable children are rendered in the cache extent
      ));
      await tester.pumpAndSettle();
      // Offset at center of first child
      await tester.tapAt(const Offset(700.0, 500.0));
      await tester.pump();
      expect(taps.contains(const ChildVicinity(xIndex: 0, yIndex: 0)), isTrue);
      // Offset by child location
      await tester.tap(find.byKey(childKeys[const ChildVicinity(xIndex: 2, yIndex: 2)]!));
      await tester.pump();
      expect(taps.contains(const ChildVicinity(xIndex: 2, yIndex: 2)), isTrue);
      // Offset out of bounds
      await tester.tap(
        find.byKey(childKeys[const ChildVicinity(xIndex: 5, yIndex: 5)]!),
        warnIfMissed: false,
      );
      await tester.pump();
      expect(taps.contains(const ChildVicinity(xIndex: 5, yIndex: 5)), isFalse);
    }, variant: TargetPlatformVariant.all());

    testWidgets('getChildFor', (WidgetTester tester) async {
      final Map<ChildVicinity, UniqueKey> childKeys = <ChildVicinity, UniqueKey>{};
      final TwoDimensionalChildBuilderDelegate delegate = TwoDimensionalChildBuilderDelegate(
        maxXIndex: 5,
        maxYIndex: 5,
        builder: (BuildContext context, ChildVicinity vicinity) {
          childKeys[vicinity] = childKeys[vicinity] ?? UniqueKey();
          return SizedBox.square(key: childKeys[vicinity], dimension: 200);
        }
      );
      addTearDown(delegate.dispose);

      await tester.pumpWidget(simpleBuilderTest(
        delegate: delegate,
      ));
      await tester.pumpAndSettle();

      final RenderSimpleBuilderTableViewport viewport = getViewport(
        tester, childKeys.values.first,
      ) as RenderSimpleBuilderTableViewport;
      // returns child
      expect(
        viewport.testGetChildFor(const ChildVicinity(xIndex: 0, yIndex: 0)),
        isNotNull,
      );
      expect(
        viewport.testGetChildFor(const ChildVicinity(xIndex: 0, yIndex: 0)),
        viewport.firstChild,
      );

      // returns null
      expect(
        viewport.testGetChildFor(const ChildVicinity(xIndex: 10, yIndex: 10)),
        isNull,
      );
    }, variant: TargetPlatformVariant.all());

    testWidgets('asserts vicinity is valid when children are asked to build', (WidgetTester tester) async {
      final Map<ChildVicinity, UniqueKey> childKeys = <ChildVicinity, UniqueKey>{};
      final TwoDimensionalChildBuilderDelegate delegate = TwoDimensionalChildBuilderDelegate(
        maxXIndex: 5,
        maxYIndex: 5,
        builder: (BuildContext context, ChildVicinity vicinity) {
          childKeys[vicinity] = childKeys[vicinity] ?? UniqueKey();
          return SizedBox.square(key: childKeys[vicinity], dimension: 200);
        }
      );
      addTearDown(delegate.dispose);

      await tester.pumpWidget(simpleBuilderTest(
        delegate: delegate,
      ));
      await tester.pumpAndSettle();

      final RenderTwoDimensionalViewport viewport = getViewport(
        tester,
        childKeys.values.first,
      );
      expect(
        () {
          viewport.buildOrObtainChildFor(ChildVicinity.invalid);
        },
        throwsA(
          isA<AssertionError>().having(
            (AssertionError error) => error.toString(),
            'description',
            contains('ChildVicinity.invalid'),
          ),
        ),
      );
    }, variant: TargetPlatformVariant.all());

    testWidgets('asserts that content dimensions have been applied', (WidgetTester tester) async {
      final TwoDimensionalChildBuilderDelegate delegate = TwoDimensionalChildBuilderDelegate(
        maxXIndex: 5,
        maxYIndex: 5,
        builder: (BuildContext context, ChildVicinity vicinity) {
          return const SizedBox.square(dimension: 200);
        }
      );
      addTearDown(delegate.dispose);

      await tester.pumpWidget(simpleBuilderTest(
        delegate: delegate,
        // Will cause the test implementation to not set dimensions
        applyDimensions: false,
      ));
      final FlutterError error = tester.takeException() as FlutterError;
      expect(error.message, contains('was not given content dimensions'));
    }, variant: TargetPlatformVariant.all());

    testWidgets('will not rebuild a child if it can be reused', (WidgetTester tester) async {
      final List<ChildVicinity> builtChildren = <ChildVicinity>[];
      final ScrollController controller = ScrollController();
      addTearDown(controller.dispose);
      final TwoDimensionalChildBuilderDelegate delegate = TwoDimensionalChildBuilderDelegate(
        maxXIndex: 5,
        maxYIndex: 5,
        builder: (BuildContext context, ChildVicinity vicinity) {
          builtChildren.add(vicinity);
          return const SizedBox.square(dimension: 200);
        }
      );
      addTearDown(delegate.dispose);

      await tester.pumpWidget(simpleBuilderTest(
        delegate: delegate,
        verticalDetails: ScrollableDetails.vertical(controller: controller),
      ));
      expect(controller.position.pixels, 0.0);
      expect(builtChildren.length, 20);
      expect(builtChildren[0], const ChildVicinity(xIndex: 0, yIndex: 0));
      builtChildren.clear();
      controller.jumpTo(1.0); // Move slightly to trigger another layout
      await tester.pump();
      expect(controller.position.pixels, 1.0);
      expect(builtChildren.length, 5); // Next row of children was built
      // Children from the first layout pass were re-used, not rebuilt.
      expect(
        builtChildren.contains(const ChildVicinity(xIndex: 0, yIndex: 0)),
        isFalse,
      );
    }, variant: TargetPlatformVariant.all());

    testWidgets('asserts the layoutOffset has been set by the subclass', (WidgetTester tester) async {
      final TwoDimensionalChildBuilderDelegate delegate = TwoDimensionalChildBuilderDelegate(
        maxXIndex: 5,
        maxYIndex: 5,
        builder: (BuildContext context, ChildVicinity vicinity) {
          return const SizedBox.square(dimension: 200);
        }
      );
      addTearDown(delegate.dispose);

      await tester.pumpWidget(simpleBuilderTest(
        delegate: delegate,
        // Will cause the test implementation to not set the layoutOffset of
        // the parent data
        setLayoutOffset: false,
      ));
      final AssertionError error = tester.takeException() as AssertionError;
      expect(error.message, contains('was not provided a layoutOffset'));
    }, variant: TargetPlatformVariant.all());

    testWidgets('asserts the children have a size after layoutChildSequence', (WidgetTester tester) async {
      final TwoDimensionalChildBuilderDelegate delegate = TwoDimensionalChildBuilderDelegate(
        maxXIndex: 5,
        maxYIndex: 5,
        builder: (BuildContext context, ChildVicinity vicinity) {
          return const SizedBox.square(dimension: 200);
        }
      );
      addTearDown(delegate.dispose);

      await tester.pumpWidget(simpleBuilderTest(
        delegate: delegate,
        // Will cause the test implementation to not actually layout the
        // children it asked for.
        forgetToLayoutChild: true,
      ));
      final AssertionError error = tester.takeException() as AssertionError;
      expect(error.toString(), contains('child.hasSize'));
    }, variant: TargetPlatformVariant.all());

    testWidgets('does not support intrinsics', (WidgetTester tester) async {
      final Map<ChildVicinity, UniqueKey> childKeys = <ChildVicinity, UniqueKey>{};
      final TwoDimensionalChildBuilderDelegate delegate = TwoDimensionalChildBuilderDelegate(
        maxXIndex: 5,
        maxYIndex: 5,
        builder: (BuildContext context, ChildVicinity vicinity) {
          childKeys[vicinity] = childKeys[vicinity] ?? UniqueKey();
          return SizedBox.square(key: childKeys[vicinity], dimension: 200);
        }
      );
      addTearDown(delegate.dispose);

      await tester.pumpWidget(simpleBuilderTest(
        delegate: delegate,
      ));
      await tester.pumpAndSettle();

      final RenderTwoDimensionalViewport viewport = getViewport(
        tester,
        childKeys.values.first,
      );
      expect(
        () {
          viewport.computeMinIntrinsicWidth(100);
        },
        throwsA(
          isA<AssertionError>().having(
            (AssertionError error) => error.toString(),
            'description',
            contains('does not support returning intrinsic dimensions'),
          ),
        ),
      );
      expect(
        () {
          viewport.computeMaxIntrinsicWidth(100);
        },
        throwsA(
          isA<AssertionError>().having(
            (AssertionError error) => error.toString(),
            'description',
            contains('does not support returning intrinsic dimensions'),
          ),
        ),
      );
      expect(
        () {
          viewport.computeMinIntrinsicHeight(100);
        },
        throwsA(
          isA<AssertionError>().having(
            (AssertionError error) => error.toString(),
            'description',
            contains('does not support returning intrinsic dimensions'),
          ),
        ),
      );
      expect(
        () {
          viewport.computeMaxIntrinsicHeight(100);
        },
        throwsA(
          isA<AssertionError>().having(
            (AssertionError error) => error.toString(),
            'description',
            contains('does not support returning intrinsic dimensions'),
          ),
        ),
      );
    }, variant: TargetPlatformVariant.all());

    group('showOnScreen & showInViewport', () {
      Finder findKey(ChildVicinity vicinity) {
        return find.byKey(ValueKey<ChildVicinity>(vicinity));
      }

      testWidgets('getOffsetToReveal', (WidgetTester tester) async {
        await tester.pumpWidget(simpleBuilderTest(useCacheExtent: true));

        RenderAbstractViewport viewport = tester.allRenderObjects.whereType<RenderAbstractViewport>().first;
        final RevealedOffset verticalOffset = viewport.getOffsetToReveal(
          tester.renderObject(findKey(const ChildVicinity(xIndex: 5, yIndex: 5))),
          1.0,
          axis: Axis.vertical,
        );
        final RevealedOffset horizontalOffset = viewport.getOffsetToReveal(
          tester.renderObject(findKey(const ChildVicinity(xIndex: 5, yIndex: 5))),
          1.0,
          axis: Axis.horizontal,
        );
        expect(verticalOffset.offset, 600.0);
        expect(verticalOffset.rect, const Rect.fromLTRB(1000.0, 400.0, 1200.0, 600.0));
        expect(horizontalOffset.offset, 400.0);
        expect(horizontalOffset.rect, const Rect.fromLTRB(600.0, 1000.0, 800.0, 1200.0));

        // default is to use mainAxis when axis is not provided, mainAxis
        // defaults to Axis.vertical.
        RevealedOffset defaultOffset = viewport.getOffsetToReveal(
          tester.renderObject(findKey(const ChildVicinity(xIndex: 5, yIndex: 5))),
          1.0,
        );
        expect(defaultOffset.offset, verticalOffset.offset);
        expect(defaultOffset.rect, verticalOffset.rect);

        // mainAxis as Axis.horizontal
        await tester.pumpWidget(simpleBuilderTest(
          useCacheExtent: true,
          mainAxis: Axis.horizontal,
        ));
        viewport = tester.allRenderObjects.whereType<RenderAbstractViewport>().first;
        defaultOffset = viewport.getOffsetToReveal(
          tester.renderObject(findKey(const ChildVicinity(xIndex: 5, yIndex: 5))),
          1.0,
        );
        expect(defaultOffset.offset, horizontalOffset.offset);
        expect(defaultOffset.rect, horizontalOffset.rect);
      });

      testWidgets('Axis.vertical', (WidgetTester tester) async {
        await tester.pumpWidget(simpleBuilderTest(useCacheExtent: true));
        // Child visible at origin
        expect(
          tester.getTopLeft(findKey(const ChildVicinity(xIndex: 0, yIndex: 0))).dy,
          equals(0.0),
        );
        tester.renderObject(find.byKey(
          const ValueKey<ChildVicinity>(ChildVicinity(xIndex: 0, yIndex: 0)),
          skipOffstage: false,
        )).showOnScreen();
        await tester.pump();
        expect(
          tester.getTopLeft(findKey(const ChildVicinity(xIndex: 0, yIndex: 0))).dy,
          equals(0.0),
        );
        // (0, 3) is in the cache extent, and will be brought into view next
        expect(
          tester.getTopLeft(findKey(const ChildVicinity(xIndex: 0, yIndex: 3))).dy,
          equals(600.0),
        );
        tester.renderObject(find.byKey(
          const ValueKey<ChildVicinity>(ChildVicinity(xIndex: 0, yIndex: 3)),
          skipOffstage: false,
        )).showOnScreen();
        await tester.pump();
        // Now in view
        expect(
          tester.getTopLeft(findKey(const ChildVicinity(xIndex: 0, yIndex: 3))).dy,
          equals(400.0),
        );

        // If already visible, no change
        tester.renderObject(find.byKey(
          const ValueKey<ChildVicinity>(ChildVicinity(xIndex: 0, yIndex: 3)),
          skipOffstage: false,
        )).showOnScreen();
        await tester.pump();
        expect(
          tester.getTopLeft(findKey(const ChildVicinity(xIndex: 0, yIndex: 3))).dy,
          equals(400.0),
        );
      });

      testWidgets('Axis.horizontal', (WidgetTester tester) async {
        await tester.pumpWidget(simpleBuilderTest(useCacheExtent: true));

        tester.renderObject(find.byKey(
          const ValueKey<ChildVicinity>(ChildVicinity(xIndex: 1, yIndex: 0)),
          skipOffstage: false,
        )).showOnScreen();
        await tester.pump();
        expect(
          tester.getTopLeft(findKey(const ChildVicinity(xIndex: 1, yIndex: 0))).dx,
          equals(200.0), // No change since already fully visible
        );
        // (5, 0) is now in the cache extent, and will be brought into view next
        expect(
          tester.getTopLeft(findKey(const ChildVicinity(xIndex: 5, yIndex: 0))).dx,
          equals(1000.0),
        );
        tester.renderObject(find.byKey(
          const ValueKey<ChildVicinity>(ChildVicinity(xIndex: 5, yIndex: 0)),
          skipOffstage: false,
        )).showOnScreen();
        await tester.pump();
        // Now in view
        expect(
          tester.getTopLeft(findKey(const ChildVicinity(xIndex: 5, yIndex: 0))).dx,
          equals(600.0),
        );

        // If already in position, no change
        tester.renderObject(find.byKey(
          const ValueKey<ChildVicinity>(ChildVicinity(xIndex: 5, yIndex: 0)),
          skipOffstage: false,
        )).showOnScreen();
        await tester.pump();
        expect(
          tester.getTopLeft(findKey(const ChildVicinity(xIndex: 5, yIndex: 0))).dx,
          equals(600.0),
        );
      });

      testWidgets('both axes', (WidgetTester tester) async {
        await tester.pumpWidget(simpleBuilderTest(useCacheExtent: true));

        tester.renderObject(find.byKey(
          const ValueKey<ChildVicinity>(ChildVicinity(xIndex: 1, yIndex: 1)),
          skipOffstage: false,
        )).showOnScreen();
        await tester.pump();
        expect(
          tester.getRect(findKey(const ChildVicinity(xIndex: 1, yIndex: 1))),
          const Rect.fromLTRB(200.0, 200.0, 400.0, 400.0),
        );
        // (5, 4) is in the cache extent, and will be brought into view next
        expect(
          tester.getRect(findKey(const ChildVicinity(xIndex: 5, yIndex: 4))),
          const Rect.fromLTRB(1000.0, 800.0, 1200.0, 1000.0),
        );
        tester.renderObject(find.byKey(
          const ValueKey<ChildVicinity>(ChildVicinity(xIndex: 5, yIndex: 4)),
          skipOffstage: false,
        )).showOnScreen();
        await tester.pump();
        // Now in view
        expect(
          tester.getRect(findKey(const ChildVicinity(xIndex: 5, yIndex: 4))),
          const Rect.fromLTRB(600.0, 200.0, 800.0, 400.0),
        );

        // If already visible, no change
        tester.renderObject(find.byKey(
          const ValueKey<ChildVicinity>(ChildVicinity(xIndex: 5, yIndex: 4)),
          skipOffstage: false,
        )).showOnScreen();
        await tester.pump();
        expect(
          tester.getRect(findKey(const ChildVicinity(xIndex: 5, yIndex: 4))),
          const Rect.fromLTRB(600.0, 200.0, 800.0, 400.0),
        );
      });

      testWidgets('Axis.vertical reverse', (WidgetTester tester) async {
        await tester.pumpWidget(simpleBuilderTest(
          verticalDetails: const ScrollableDetails.vertical(reverse: true),
          useCacheExtent: true,
        ));

        expect(
          tester.getTopLeft(findKey(const ChildVicinity(xIndex: 0, yIndex: 0))).dy,
          equals(400.0),
        );
        tester.renderObject(find.byKey(
          const ValueKey<ChildVicinity>(ChildVicinity(xIndex: 0, yIndex: 0)),
          skipOffstage: false,
        )).showOnScreen();
        await tester.pump();
        // Already visible so no change.
        expect(
          tester.getTopLeft(findKey(const ChildVicinity(xIndex: 0, yIndex: 0))).dy,
          equals(400.0),
        );
        // (0, 3) is in the cache extent, and will be brought into view next
        expect(
          tester.getTopLeft(findKey(const ChildVicinity(xIndex: 0, yIndex: 3))).dy,
          equals(-200.0),
        );
        tester.renderObject(find.byKey(
          const ValueKey<ChildVicinity>(ChildVicinity(xIndex: 0, yIndex: 3)),
          skipOffstage: false,
        )).showOnScreen();
        await tester.pump();
        // Now in view
        expect(
          tester.getTopLeft(findKey(const ChildVicinity(xIndex: 0, yIndex: 3))).dy,
          equals(0.0),
        );

        // If already visible, no change
        tester.renderObject(find.byKey(
          const ValueKey<ChildVicinity>(ChildVicinity(xIndex: 0, yIndex: 3)),
          skipOffstage: false,
        )).showOnScreen();
        await tester.pump();
        expect(
          tester.getTopLeft(findKey(const ChildVicinity(xIndex: 0, yIndex: 3))).dy,
          equals(0.0),
        );
      });

      testWidgets('Axis.horizontal reverse', (WidgetTester tester) async {
        await tester.pumpWidget(simpleBuilderTest(
          horizontalDetails: const ScrollableDetails.horizontal(reverse: true),
          useCacheExtent: true,
        ));

        expect(
          tester.getTopLeft(findKey(const ChildVicinity(xIndex: 0, yIndex: 0))).dx,
          equals(600.0),
        );
        tester.renderObject(find.byKey(
          const ValueKey<ChildVicinity>(ChildVicinity(xIndex: 0, yIndex: 0)),
          skipOffstage: false,
        )).showOnScreen();
        await tester.pump();
        // Already visible so no change.
        expect(
          tester.getTopLeft(findKey(const ChildVicinity(xIndex: 0, yIndex: 0))).dx,
          equals(600.0),
        );
        // (4, 0) is in the cache extent, and will be brought into view next
        expect(
          tester.getTopLeft(findKey(const ChildVicinity(xIndex: 4, yIndex: 0))).dx,
          equals(-200.0),
        );
        tester.renderObject(find.byKey(
          const ValueKey<ChildVicinity>(ChildVicinity(xIndex: 4, yIndex: 0)),
          skipOffstage: false,
        )).showOnScreen();
        await tester.pump();
        expect(
          tester.getTopLeft(findKey(const ChildVicinity(xIndex: 4, yIndex: 0))).dx,
          equals(0.0),
        );

        // If already visible, no change
        tester.renderObject(find.byKey(
          const ValueKey<ChildVicinity>(ChildVicinity(xIndex: 4, yIndex: 0)),
          skipOffstage: false,
        )).showOnScreen();
        await tester.pump();
        expect(
          tester.getTopLeft(findKey(const ChildVicinity(xIndex: 4, yIndex: 0))).dx,
          equals(0.0),
        );
      });

      testWidgets('both axes reverse', (WidgetTester tester) async {
        await tester.pumpWidget(simpleBuilderTest(
          verticalDetails: const ScrollableDetails.vertical(reverse: true),
          horizontalDetails: const ScrollableDetails.horizontal(reverse: true),
          useCacheExtent: true,
        ));

        tester.renderObject(find.byKey(
          const ValueKey<ChildVicinity>(ChildVicinity(xIndex: 1, yIndex: 1)),
          skipOffstage: false,
        )).showOnScreen();
        await tester.pump();
        expect(
          tester.getRect(findKey(const ChildVicinity(xIndex: 1, yIndex: 1))),
          const Rect.fromLTRB(400.0, 200.0, 600.0, 400.0),
        );
        // (5, 4) is in the cache extent, and will be brought into view next
        expect(
          tester.getRect(findKey(const ChildVicinity(xIndex: 5, yIndex: 4))),
          const Rect.fromLTRB(-400.0, -400.0, -200.0, -200.0),
        );
        tester.renderObject(find.byKey(
          const ValueKey<ChildVicinity>(ChildVicinity(xIndex: 5, yIndex: 4)),
          skipOffstage: false,
        )).showOnScreen();
        await tester.pump();
        // Now in view
        expect(
          tester.getRect(findKey(const ChildVicinity(xIndex: 5, yIndex: 4))),
          const Rect.fromLTRB(0.0, 200.0, 200.0, 400.0),
        );

        // If already visible, no change
        tester.renderObject(find.byKey(
          const ValueKey<ChildVicinity>(ChildVicinity(xIndex: 5, yIndex: 4)),
          skipOffstage: false,
        )).showOnScreen();
        await tester.pump();
        expect(
          tester.getRect(findKey(const ChildVicinity(xIndex: 5, yIndex: 4))),
          const Rect.fromLTRB(0.0, 200.0, 200.0, 400.0),
        );
      });
    });

    testWidgets('Does not throw when no child is laid out',
        (WidgetTester tester) async {
      final TwoDimensionalChildBuilderDelegate delegate =
          TwoDimensionalChildBuilderDelegate(
        maxXIndex: 50,
        maxYIndex: 50,
        addAutomaticKeepAlives: false,
        addRepaintBoundaries: false,
        builder: (BuildContext context, ChildVicinity vicinity) {
          if (vicinity.xIndex > 10) {
            return const SizedBox.square(dimension: 200);
          }
          return null;
        },
      );
      addTearDown(delegate.dispose);

      await tester.pumpWidget(simpleBuilderTest(delegate: delegate));
      expect(tester.takeException(), isNull);
    });

    testWidgets('correctly reorders children and wont throw assertion failure',
        (WidgetTester tester) async {
      final TwoDimensionalChildBuilderDelegate delegate1 =
          TwoDimensionalChildBuilderDelegate(
              maxXIndex: 5,
              maxYIndex: 5,
              addAutomaticKeepAlives: false,
              addRepaintBoundaries: false,
              builder: (BuildContext context, ChildVicinity vicinity) {
                final ValueKey<int>? key = switch (vicinity) {
                  ChildVicinity(xIndex: 1, yIndex: 1) => const ValueKey<int>(1),
                  ChildVicinity(xIndex: 1, yIndex: 2) => const ValueKey<int>(2),
                  _ => null,
                };
                return SizedBox.square(key: key, dimension: 200);
              });
      final TwoDimensionalChildBuilderDelegate delegate2 =
          TwoDimensionalChildBuilderDelegate(
              maxXIndex: 5,
              maxYIndex: 5,
              addAutomaticKeepAlives: false,
              addRepaintBoundaries: false,
              builder: (BuildContext context, ChildVicinity vicinity) {
                ValueKey<int>? key;
                if (vicinity == const ChildVicinity(xIndex: 0, yIndex: 0)) {
                  key = const ValueKey<int>(1);
                } else if (vicinity ==
                    const ChildVicinity(xIndex: 1, yIndex: 1)) {
                  key = const ValueKey<int>(2);
                }
                return SizedBox.square(key: key, dimension: 200);
              });
      addTearDown(delegate1.dispose);
      addTearDown(delegate2.dispose);

      await tester.pumpWidget(simpleBuilderTest(delegate: delegate1));
      expect(tester.getRect(find.byKey(const ValueKey<int>(1))),
          const Rect.fromLTWH(200.0, 200.0, 200.0, 200.0));
      await tester.pumpWidget(simpleBuilderTest(delegate: delegate2));
      expect(tester.getRect(find.byKey(const ValueKey<int>(1))),
          const Rect.fromLTWH(0.0, 0.0, 200.0, 200.0));
      await tester.pumpWidget(simpleBuilderTest(delegate: delegate1));
      expect(tester.getRect(find.byKey(const ValueKey<int>(1))),
          const Rect.fromLTWH(200.0, 200.0, 200.0, 200.0));
    }, variant: TargetPlatformVariant.all());

    testWidgets('state is preserved after reordering',
        (WidgetTester tester) async {
      final TwoDimensionalChildBuilderDelegate delegate1 =
          TwoDimensionalChildBuilderDelegate(
              maxXIndex: 5,
              maxYIndex: 5,
              addAutomaticKeepAlives: false,
              addRepaintBoundaries: false,
              builder: (BuildContext context, ChildVicinity vicinity) {
                final ValueKey<int>? key = switch (vicinity) {
                  ChildVicinity(xIndex: 0, yIndex: 0) => const ValueKey<int>(1),
                  ChildVicinity(xIndex: 1, yIndex: 1) => const ValueKey<int>(2),
                  _ => null,
                };
                return Checkbox(key: key, value: false, onChanged: (_) {});
              });
      final TwoDimensionalChildBuilderDelegate delegate2 =
          TwoDimensionalChildBuilderDelegate(
              maxXIndex: 5,
              maxYIndex: 5,
              addAutomaticKeepAlives: false,
              addRepaintBoundaries: false,
              builder: (BuildContext context, ChildVicinity vicinity) {
                ValueKey<int>? key;
                if (vicinity == const ChildVicinity(xIndex: 0, yIndex: 0)) {
                  key = const ValueKey<int>(1);
                } else if (vicinity ==
                    const ChildVicinity(xIndex: 1, yIndex: 1)) {
                  key = const ValueKey<int>(2);
                }
                return Checkbox(key: key, value: false, onChanged: (_) {});
              });
      addTearDown(delegate1.dispose);
      addTearDown(delegate2.dispose);

      await tester.pumpWidget(simpleBuilderTest(delegate: delegate1));
      final State stateBeforeReordering =
          tester.state(find.byKey(const ValueKey<int>(2)));

      await tester.pumpWidget(simpleBuilderTest(delegate: delegate2));
      expect(tester.state(find.byKey(const ValueKey<int>(2))),
          stateBeforeReordering);

      await tester.pumpWidget(simpleBuilderTest(delegate: delegate1));
      expect(tester.state(find.byKey(const ValueKey<int>(2))),
          stateBeforeReordering);
    }, variant: TargetPlatformVariant.all());
  });
}

class _TestVicinity extends ChildVicinity {
  const _TestVicinity({required super.xIndex, required super.yIndex});
}

class _TestBaseDelegate extends TwoDimensionalChildDelegate { //ignore: unused_element
  // Would fail analysis without covariant
  @override
  Widget? build(BuildContext context, _TestVicinity vicinity) => null;

  @override
  bool shouldRebuild(covariant TwoDimensionalChildDelegate oldDelegate) => false;

}

class _TestBuilderDelegate extends TwoDimensionalChildBuilderDelegate { //ignore: unused_element
  _TestBuilderDelegate({required super.builder});
  // Would fail analysis without covariant
  @override
  Widget? build(BuildContext context, _TestVicinity vicinity) {
    return super.build(context, vicinity);
  }
}

class _TestListDelegate extends TwoDimensionalChildListDelegate { //ignore: unused_element
  _TestListDelegate({required super.children});
  // Would fail analysis without covariant
  @override
  Widget? build(BuildContext context, _TestVicinity vicinity) {
    return super.build(context, vicinity);
  }
}

RenderTwoDimensionalViewport getViewport(WidgetTester tester, Key childKey) {
  return RenderAbstractViewport.of(
    tester.renderObject(find.byKey(childKey))
  ) as RenderSimpleBuilderTableViewport;
}

class _NullBuildContext implements BuildContext, TwoDimensionalChildManager {
  @override
  dynamic noSuchMethod(Invocation invocation) => throw UnimplementedError();
}

Future<void> restoreScrollAndVerify(WidgetTester tester) async {
  final Finder findScrollable = find.byElementPredicate((Element e) => e.widget is TwoDimensionalScrollable);

  tester.state<TwoDimensionalScrollableState>(findScrollable).horizontalScrollable.position.jumpTo(100);
  tester.state<TwoDimensionalScrollableState>(findScrollable).verticalScrollable.position.jumpTo(100);
  await tester.pump();
  await tester.restartAndRestore();

  expect(
    tester.state<TwoDimensionalScrollableState>(findScrollable).horizontalScrollable.position.pixels,
    100.0,
  );
  expect(
    tester.state<TwoDimensionalScrollableState>(findScrollable).verticalScrollable.position.pixels,
    100.0,
  );

  final TestRestorationData data = await tester.getRestorationData();
  tester.state<TwoDimensionalScrollableState>(findScrollable).horizontalScrollable.position.jumpTo(0);
  tester.state<TwoDimensionalScrollableState>(findScrollable).verticalScrollable.position.jumpTo(0);
  await tester.pump();
  await tester.restoreFrom(data);

  expect(
    tester.state<TwoDimensionalScrollableState>(findScrollable).horizontalScrollable.position.pixels,
    100.0,
  );
  expect(
    tester.state<TwoDimensionalScrollableState>(findScrollable).verticalScrollable.position.pixels,
    100.0,
  );
}

// Validates covariant through analysis.
mixin _SomeDelegateMixin on TwoDimensionalChildDelegate {}

class _SomeRenderTwoDimensionalViewport extends RenderTwoDimensionalViewport { // ignore: unused_element
  _SomeRenderTwoDimensionalViewport({
    required super.horizontalOffset,
    required super.horizontalAxisDirection,
    required super.verticalOffset,
    required super.verticalAxisDirection,
    required _SomeDelegateMixin super.delegate,
    required super.mainAxis,
    required super.childManager,
  });

  @override
  _SomeDelegateMixin get delegate => super.delegate as _SomeDelegateMixin;
  @override
  set delegate(_SomeDelegateMixin value) { // Analysis would fail without covariant
    super.delegate = value;
  }

  @override
  RenderBox? getChildFor(_TestVicinity vicinity) { // Analysis would fail without covariant
    return super.getChildFor(vicinity);
  }

  @override
  void layoutChildSequence() {}
}
