// 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.

// This file is run as part of a reduced test set in CI on Mac and Windows
// machines.
@Tags(<String>['reduced-test-set'])
library;

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  group('$ReorderableListView', () {
    const double itemHeight = 48.0;
    const List<String> originalListItems = <String>['Item 1', 'Item 2', 'Item 3', 'Item 4'];
    late List<String> listItems;

    void onReorder(int oldIndex, int newIndex) {
      if (oldIndex < newIndex) {
        newIndex -= 1;
      }
      final String element = listItems.removeAt(oldIndex);
      listItems.insert(newIndex, element);
    }

    Widget listItemToWidget(String listItem) {
      return SizedBox(
        key: Key(listItem),
        height: itemHeight,
        width: itemHeight,
        child: Text(listItem),
      );
    }

    Widget build({
      Widget? header,
      Widget? footer,
      Axis scrollDirection = Axis.vertical,
      bool reverse = false,
      EdgeInsets padding = EdgeInsets.zero,
      TextDirection textDirection = TextDirection.ltr,
      TargetPlatform? platform,
    }) {
      return MaterialApp(
        theme: ThemeData(platform: platform),
        home: Directionality(
          textDirection: textDirection,
          child: SizedBox(
            height: itemHeight * 10,
            width: itemHeight * 10,
            child: ReorderableListView(
              header: header,
              footer: footer,
              scrollDirection: scrollDirection,
              onReorder: onReorder,
              reverse: reverse,
              padding: padding,
              children: listItems.map<Widget>(listItemToWidget).toList(),
            ),
          ),
        ),
      );
    }

    setUp(() {
      // Copy the original list into listItems.
      listItems = originalListItems.toList();
    });

    group('in vertical mode', () {
      testWidgets('reorder is not triggered when children length is less or equals to 1', (WidgetTester tester) async {
        bool onReorderWasCalled = false;
        final List<String> currentListItems = listItems.take(1).toList();
        final ReorderableListView reorderableListView = ReorderableListView(
          header: const Text('Header'),
          onReorder: (_, __) => onReorderWasCalled = true,
          children: currentListItems.map<Widget>(listItemToWidget).toList(),
        );
        final List<String> currentOriginalListItems = originalListItems.take(1).toList();
        await tester.pumpWidget(MaterialApp(
          home: SizedBox(
            height: itemHeight * 10,
            child: reorderableListView,
          ),
        ));
        expect(currentListItems, orderedEquals(currentOriginalListItems));
        final TestGesture drag = await tester.startGesture(tester.getCenter(find.text('Item 1')));
        await tester.pump(kLongPressTimeout + kPressTimeout);
        expect(currentListItems, orderedEquals(currentOriginalListItems));
        await drag.moveTo(tester.getBottomLeft(find.text('Item 1')) * 2);
        expect(currentListItems, orderedEquals(currentOriginalListItems));
        await drag.up();
        expect(onReorderWasCalled, false);
        expect(currentListItems, orderedEquals(<String>['Item 1']));
      });

      testWidgets('reorders its contents only when a drag finishes', (WidgetTester tester) async {
        await tester.pumpWidget(build());
        expect(listItems, orderedEquals(originalListItems));
        final TestGesture drag = await tester.startGesture(tester.getCenter(find.text('Item 1')));
        await tester.pump(kLongPressTimeout + kPressTimeout);
        expect(listItems, orderedEquals(originalListItems));
        await drag.moveTo(tester.getCenter(find.text('Item 4')));
        expect(listItems, orderedEquals(originalListItems));
        await drag.up();
        await tester.pumpAndSettle();
        expect(listItems, orderedEquals(<String>['Item 2', 'Item 3', 'Item 1', 'Item 4']));
      });

      testWidgets('allows reordering from the very top to the very bottom', (WidgetTester tester) async {
        await tester.pumpWidget(build());
        expect(listItems, orderedEquals(originalListItems));
        await longPressDrag(
          tester,
          tester.getCenter(find.text('Item 1')),
          tester.getCenter(find.text('Item 4')) + const Offset(0.0, itemHeight * 2),
        );
        await tester.pumpAndSettle();
        expect(listItems, orderedEquals(<String>['Item 2', 'Item 3', 'Item 4', 'Item 1']));
      });

      testWidgets('allows reordering from the very bottom to the very top', (WidgetTester tester) async {
        await tester.pumpWidget(build());
        expect(listItems, orderedEquals(originalListItems));
        await longPressDrag(
          tester,
          tester.getCenter(find.text('Item 4')),
          tester.getCenter(find.text('Item 1')),
        );
        await tester.pumpAndSettle();
        expect(listItems, orderedEquals(<String>['Item 4', 'Item 1', 'Item 2', 'Item 3']));
      });

      testWidgets('allows reordering inside the middle of the widget', (WidgetTester tester) async {
        await tester.pumpWidget(build());
        expect(listItems, orderedEquals(originalListItems));
        await longPressDrag(
          tester,
          tester.getCenter(find.text('Item 3')),
          tester.getCenter(find.text('Item 2')),
        );
        await tester.pumpAndSettle();
        expect(listItems, orderedEquals(<String>['Item 1', 'Item 3', 'Item 2', 'Item 4']));
      });

      testWidgets('properly reorders with a header', (WidgetTester tester) async {
        await tester.pumpWidget(build(header: const Text('Header Text')));
        expect(find.text('Header Text'), findsOneWidget);
        expect(listItems, orderedEquals(originalListItems));
        await longPressDrag(
          tester,
          tester.getCenter(find.text('Item 1')),
          tester.getCenter(find.text('Item 4')) + const Offset(0.0, itemHeight * 2),
        );
        await tester.pumpAndSettle();
        expect(find.text('Header Text'), findsOneWidget);
        expect(listItems, orderedEquals(<String>['Item 2', 'Item 3', 'Item 4', 'Item 1']));
      });

      testWidgets('properly reorders with a footer', (WidgetTester tester) async {
        await tester.pumpWidget(build(footer: const Text('Footer Text')));
        expect(find.text('Footer Text'), findsOneWidget);
        expect(listItems, orderedEquals(originalListItems));
        await longPressDrag(
          tester,
          tester.getCenter(find.text('Item 1')),
          tester.getCenter(find.text('Item 4')) + const Offset(0.0, itemHeight * 2),
        );
        await tester.pumpAndSettle();
        expect(find.text('Footer Text'), findsOneWidget);
        expect(listItems, orderedEquals(<String>['Item 2', 'Item 3', 'Item 4', 'Item 1']));
      });

      testWidgets('properly determines the vertical drop area extents', (WidgetTester tester) async {
        final Widget reorderableListView = ReorderableListView(
          onReorder: (int oldIndex, int newIndex) { },
          children: const <Widget>[
            SizedBox(
              key: Key('Normal item'),
              height: itemHeight,
              child: Text('Normal item'),
            ),
            SizedBox(
              key: Key('Tall item'),
              height: itemHeight * 2,
              child: Text('Tall item'),
            ),
            SizedBox(
              key: Key('Last item'),
              height: itemHeight,
              child: Text('Last item'),
            ),
          ],
        );
        await tester.pumpWidget(MaterialApp(
          home: SizedBox(
            height: itemHeight * 10,
            child: reorderableListView,
          ),
        ));

        double getListHeight() {
          final RenderSliverList listScrollView = tester.renderObject(find.byType(SliverList));
          return listScrollView.geometry!.maxPaintExtent;
        }

        const double kDraggingListHeight = 4 * itemHeight;
        // Drag a normal text item
        expect(getListHeight(), kDraggingListHeight);
        TestGesture drag = await tester.startGesture(tester.getCenter(find.text('Normal item')));
        await tester.pump(kLongPressTimeout + kPressTimeout);
        await tester.pumpAndSettle();
        expect(getListHeight(), kDraggingListHeight);

        // Move it
        await drag.moveTo(tester.getCenter(find.text('Last item')));
        await tester.pumpAndSettle();
        expect(getListHeight(), kDraggingListHeight);

        // Drop it
        await drag.up();
        await tester.pumpAndSettle();
        expect(getListHeight(), kDraggingListHeight);

        // Drag a tall item
        drag = await tester.startGesture(tester.getCenter(find.text('Tall item')));
        await tester.pump(kLongPressTimeout + kPressTimeout);
        await tester.pumpAndSettle();
        expect(getListHeight(), kDraggingListHeight);
        // Move it
        await drag.moveTo(tester.getCenter(find.text('Last item')));
        await tester.pumpAndSettle();
        expect(getListHeight(), kDraggingListHeight);

        // Drop it
        await drag.up();
        await tester.pumpAndSettle();
        expect(getListHeight(), kDraggingListHeight);
      });

      testWidgets('Vertical drag in progress golden image', (WidgetTester tester) async {
        debugDisableShadows = false;
        final Widget reorderableListView = ReorderableListView(
          children: <Widget>[
            Container(
              key: const Key('pink'),
              width: double.infinity,
              height: itemHeight,
              color: Colors.pink,
            ),
            Container(
              key: const Key('blue'),
              width: double.infinity,
              height: itemHeight,
              color: Colors.blue,
            ),
            Container(
              key: const Key('green'),
              width: double.infinity,
              height: itemHeight,
              color: Colors.green,
            ),
          ],
          onReorder: (int oldIndex, int newIndex) { },
        );

        late final OverlayEntry entry;
        addTearDown(() => entry..remove()..dispose());

        await tester.pumpWidget(MaterialApp(
          home: Container(
            color: Colors.white,
            height: itemHeight * 3,
            // Wrap in an overlay so that the golden image includes the dragged item.
            child: Overlay(
              initialEntries: <OverlayEntry>[
                entry = OverlayEntry(builder: (BuildContext context) {
                  // Wrap the list in padding to test that the positioning
                  // is correct when the origin of the overlay is different
                  // from the list.
                  return Padding(
                    padding: const EdgeInsets.all(24),
                    child: reorderableListView,
                  );
                }),
              ],
            ),
          ),
        ));

        // Start dragging the second item.
        final TestGesture drag = await tester.startGesture(tester.getCenter(find.byKey(const Key('blue'))));
        await tester.pump(kLongPressTimeout + kPressTimeout);

        // Drag it up to be partially over the top item.
        await drag.moveBy(const Offset(0, -itemHeight / 3));
        await tester.pumpAndSettle();

        // Should be an image of the second item overlapping the bottom of the
        // first with a gap between the first and third and a drop shadow on
        // the dragged item.
        await expectLater(
          find.byType(Overlay).last,
          matchesGoldenFile('reorderable_list_test.vertical.drop_area.png'),
        );
        debugDisableShadows = true;
      });

      testWidgets('Preserves children states when the list parent changes the order', (WidgetTester tester) async {
        _StatefulState findState(Key key) {
          return find.byElementPredicate((Element element) => element.findAncestorWidgetOfExactType<_Stateful>()?.key == key)
              .evaluate()
              .first
              .findAncestorStateOfType<_StatefulState>()!;
        }
        await tester.pumpWidget(MaterialApp(
          home: ReorderableListView(
            children: <Widget>[
              _Stateful(key: const Key('A')),
              _Stateful(key: const Key('B')),
              _Stateful(key: const Key('C')),
            ],
            onReorder: (int oldIndex, int newIndex) { },
          ),
        ));
        await tester.tap(find.byKey(const Key('A')));
        await tester.pumpAndSettle();
        // Only the 'A' widget should be checked.
        expect(findState(const Key('A')).checked, true);
        expect(findState(const Key('B')).checked, false);
        expect(findState(const Key('C')).checked, false);

        await tester.pumpWidget(MaterialApp(
          home: ReorderableListView(
            children: <Widget>[
              _Stateful(key: const Key('B')),
              _Stateful(key: const Key('C')),
              _Stateful(key: const Key('A')),
            ],
            onReorder: (int oldIndex, int newIndex) { },
          ),
        ));
        // Only the 'A' widget should be checked.
        expect(findState(const Key('B')).checked, false);
        expect(findState(const Key('C')).checked, false);
        expect(findState(const Key('A')).checked, true);
      });

      testWidgets('Preserves children states when rebuilt', (WidgetTester tester) async {
        const Key firstBox = Key('key');
        Widget build() {
          return MaterialApp(
            home: Directionality(
              textDirection: TextDirection.ltr,
              child: SizedBox(
                width: 100,
                height: 100,
                child: ReorderableListView(
                  children: const <Widget>[
                    SizedBox(key: firstBox, width: 10, height: 10),
                  ],
                  onReorder: (_, __) {},
                ),
              ),
            ),
          );
        }

        // When the widget is rebuilt, the state of child should be consistent.
        await tester.pumpWidget(build());
        final Element e0 = tester.element(find.byKey(firstBox));
        await tester.pumpWidget(build());
        final Element e1 = tester.element(find.byKey(firstBox));
        expect(e0, equals(e1));
      });

      testWidgets('Uses the PrimaryScrollController when available', (WidgetTester tester) async {
        final ScrollController primary = ScrollController();
        addTearDown(primary.dispose);
        final Widget reorderableList = ReorderableListView(
          children: const <Widget>[
            SizedBox(width: 100.0, height: 100.0, key: Key('C'), child: Text('C')),
            SizedBox(width: 100.0, height: 100.0, key: Key('B'), child: Text('B')),
            SizedBox(width: 100.0, height: 100.0, key: Key('A'), child: Text('A')),
          ],
          onReorder: (int oldIndex, int newIndex) { },
        );

        Widget buildWithScrollController(ScrollController controller) {
          return MaterialApp(
            home: PrimaryScrollController(
              controller: controller,
              child: SizedBox(
                height: 100.0,
                width: 100.0,
                child: reorderableList,
              ),
            ),
          );
        }

        await tester.pumpWidget(buildWithScrollController(primary));
        Scrollable scrollView = tester.widget(
          find.byType(Scrollable),
        );
        expect(scrollView.controller, primary);

        // Now try changing the primary scroll controller and checking that the scroll view gets updated.
        final ScrollController primary2 = ScrollController();
        addTearDown(primary2.dispose);

        await tester.pumpWidget(buildWithScrollController(primary2));
        scrollView = tester.widget(
          find.byType(Scrollable),
        );
        expect(scrollView.controller, primary2);
      });

      testWidgets('Test custom ScrollController behavior when set', (WidgetTester tester) async {
        const Key firstBox = Key('C');
        const Key secondBox = Key('B');
        const Key thirdBox = Key('A');
        final ScrollController customController = ScrollController();
        addTearDown(customController.dispose);

        await tester.pumpWidget(
          MaterialApp(
            home: Scaffold(
              body: SizedBox(
                height: 150,
                child: ReorderableListView(
                  scrollController: customController,
                  onReorder: (int oldIndex, int newIndex) { },
                  children: const <Widget>[
                    SizedBox(width: 100.0, height: 100.0, key: firstBox, child: Text('C')),
                    SizedBox(width: 100.0, height: 100.0, key: secondBox, child: Text('B')),
                    SizedBox(width: 100.0, height: 100.0, key: thirdBox, child: Text('A')),
                  ],
                ),
              ),
            ),
          ),
        );

        // Check initial scroll offset of first list item relative to
        // the offset of the list view.
        customController.animateTo(
          40.0,
          duration: const Duration(milliseconds: 200),
          curve: Curves.linear,
        );
        await tester.pumpAndSettle();
        Offset listViewTopLeft = tester.getTopLeft(
          find.byType(ReorderableListView),
        );
        Offset firstBoxTopLeft = tester.getTopLeft(
          find.byKey(firstBox),
        );
        expect(firstBoxTopLeft.dy, listViewTopLeft.dy - 40.0);

        // Drag the UI to see if the scroll controller updates accordingly
        await tester.drag(
          find.text('B'),
          const Offset(0.0, -100.0),
        );
        listViewTopLeft = tester.getTopLeft(
          find.byType(ReorderableListView),
        );
        firstBoxTopLeft = tester.getTopLeft(
          find.byKey(firstBox),
        );
        // Initial scroll controller offset: 40.0
        // Drag UI by 100.0 upwards vertically
        // First 20.0 px always ignored, so scroll offset is only
        // shifted by 80.0.
        // Final offset: 40.0 + 80.0 = 120.0
        // The total distance available to scroll is 300.0 - 150.0 = 150.0, or
        // height of the ReorderableListView minus height of the SizedBox. Since
        // The final offset is less than this, it's not limited.
        expect(customController.offset, 120.0);
      });

      testWidgets('ReorderableList auto scrolling is fast enough', (WidgetTester tester) async {
        // Regression test for https://github.com/flutter/flutter/issues/121603.
        final ScrollController controller = ScrollController();
        addTearDown(controller.dispose);

        await tester.pumpWidget(
          MaterialApp(
            home: Scaffold(
              body: ReorderableListView.builder(
                scrollController: controller,
                itemCount: 100,
                itemBuilder: (BuildContext context, int index) {
                  return Text('data', key: ValueKey<int>(index));
                },
                onReorder: (int oldIndex, int newIndex) {},
              ),
            ),
          ),
        );

        // Start gesture on first item.
        final TestGesture drag = await tester.startGesture(tester.getCenter(find.byKey(const ValueKey<int>(0))));
        await tester.pump(kLongPressTimeout + kPressTimeout);
        final Offset bottomRight = tester.getBottomRight(find.byType(ReorderableListView));
        // Drag enough for move to start.
        await drag.moveTo(Offset(bottomRight.dx / 2, bottomRight.dy));
        await tester.pump();
        // Use a fixed value to make sure the default velocity scalar is bigger
        // than a certain amount.
        const double kMinimumAllowedAutoScrollDistancePer5ms = 1.7;

        await tester.pump(const Duration(milliseconds: 5));
        expect(controller.offset, greaterThan(kMinimumAllowedAutoScrollDistancePer5ms));
        await tester.pump(const Duration(milliseconds: 5));
        expect(controller.offset, greaterThan(kMinimumAllowedAutoScrollDistancePer5ms * 2));
        await tester.pump(const Duration(milliseconds: 5));
        expect(controller.offset, greaterThan(kMinimumAllowedAutoScrollDistancePer5ms * 3));
        await tester.pump(const Duration(milliseconds: 5));
        expect(controller.offset, greaterThan(kMinimumAllowedAutoScrollDistancePer5ms * 4));
      });

      testWidgets('Still builds when no PrimaryScrollController is available', (WidgetTester tester) async {
        final Widget reorderableList = ReorderableListView(
          children: const <Widget>[
            SizedBox(width: 100.0, height: 100.0, key: Key('C'), child: Text('C')),
            SizedBox(width: 100.0, height: 100.0, key: Key('B'), child: Text('B')),
            SizedBox(width: 100.0, height: 100.0, key: Key('A'), child: Text('A')),
          ],
          onReorder: (int oldIndex, int newIndex) { },
        );

        late final OverlayEntry entry;
        addTearDown(() => entry..remove()..dispose());

        final Widget overlay = Overlay(
          initialEntries: <OverlayEntry>[
            entry = OverlayEntry(builder: (BuildContext context) => reorderableList),
          ],
        );
        final Widget boilerplate = Localizations(
          locale: const Locale('en'),
          delegates: const <LocalizationsDelegate<dynamic>>[
            DefaultMaterialLocalizations.delegate,
            DefaultWidgetsLocalizations.delegate,
          ],
          child:SizedBox(
            width: 100.0,
            height: 100.0,
            child: Directionality(
              textDirection: TextDirection.ltr,
              child: overlay,
            ),
          ),
        );
        await expectLater(
          () => tester.pumpWidget(boilerplate),
          returnsNormally,
        );
      });

      group('Accessibility (a11y/Semantics)', () {
        Map<CustomSemanticsAction, VoidCallback> getSemanticsActions(int index) {
          final Semantics semantics = find.ancestor(
            of: find.byKey(Key(listItems[index])),
            matching: find.byType(Semantics),
          ).evaluate().first.widget as Semantics;
          return semantics.properties.customSemanticsActions!;
        }

        const CustomSemanticsAction moveToStart = CustomSemanticsAction(label: 'Move to the start');
        const CustomSemanticsAction moveToEnd = CustomSemanticsAction(label: 'Move to the end');
        const CustomSemanticsAction moveUp = CustomSemanticsAction(label: 'Move up');
        const CustomSemanticsAction moveDown = CustomSemanticsAction(label: 'Move down');

        testWidgets('Provides the correct accessibility actions in LTR and RTL modes', (WidgetTester tester) async {
          // The a11y actions for a vertical list are the same in LTR and RTL modes.
          final SemanticsHandle handle = tester.ensureSemantics();
          for (final TextDirection direction in TextDirection.values) {
            await tester.pumpWidget(build());

            // The first item can be moved down or to the end.
            final Map<CustomSemanticsAction, VoidCallback> firstSemanticsActions = getSemanticsActions(0);
            expect(firstSemanticsActions.length, 2, reason: 'The first list item should have 2 custom actions with $direction.');
            expect(firstSemanticsActions.containsKey(moveToStart), false, reason: 'The first item cannot `Move to the start` with $direction.');
            expect(firstSemanticsActions.containsKey(moveUp), false, reason: 'The first item cannot `Move up` with $direction.');
            expect(firstSemanticsActions.containsKey(moveDown), true, reason: 'The first item should be able to `Move down` with $direction.');
            expect(firstSemanticsActions.containsKey(moveToEnd), true, reason: 'The first item should be able to `Move to the end` with $direction.');

            // Items in the middle can be moved to the start, end, up or down.
            for (int i = 1; i < listItems.length - 1; i += 1) {
              final Map<CustomSemanticsAction, VoidCallback> ithSemanticsActions = getSemanticsActions(i);
              expect(ithSemanticsActions.length, 4, reason: 'List item $i should have 4 custom actions with $direction.');
              expect(ithSemanticsActions.containsKey(moveToStart), true, reason: 'List item $i should be able to `Move to the start` with $direction.');
              expect(ithSemanticsActions.containsKey(moveUp), true, reason: 'List item $i should be able to `Move up` with $direction.');
              expect(ithSemanticsActions.containsKey(moveDown), true, reason: 'List item $i should be able to `Move down` with $direction.');
              expect(ithSemanticsActions.containsKey(moveToEnd), true, reason: 'List item $i should be able to `Move to the end` with $direction.');
            }

            // The last item can be moved up or to the start.
            final Map<CustomSemanticsAction, VoidCallback> lastSemanticsActions = getSemanticsActions(listItems.length - 1);
            expect(lastSemanticsActions.length, 2, reason: 'The last list item should have 2 custom actions with $direction.');
            expect(lastSemanticsActions.containsKey(moveToStart), true, reason: 'The last item should be able to `Move to the start` with $direction.');
            expect(lastSemanticsActions.containsKey(moveUp), true, reason: 'The last item should be able to `Move up` with $direction.');
            expect(lastSemanticsActions.containsKey(moveDown), false, reason: 'The last item cannot `Move down` with $direction.');
            expect(lastSemanticsActions.containsKey(moveToEnd), false, reason: 'The last item cannot `Move to the end` with $direction.');
          }
          handle.dispose();
        });

        testWidgets('First item accessibility (a11y) actions work', (WidgetTester tester) async {
          final SemanticsHandle handle = tester.ensureSemantics();
          expect(listItems, orderedEquals(originalListItems));

          // Test out move to end: move Item 1 to the end of the list.
          await tester.pumpWidget(build());
          Map<CustomSemanticsAction, VoidCallback> firstSemanticsActions = getSemanticsActions(0);
          firstSemanticsActions[moveToEnd]!();
          await tester.pumpAndSettle();
          expect(listItems, orderedEquals(<String>['Item 2', 'Item 3', 'Item 4', 'Item 1']));

          // Test out move after: move Item 2 (the current first item) one space down.
          await tester.pumpWidget(build());
          firstSemanticsActions = getSemanticsActions(0);
          firstSemanticsActions[moveDown]!();
          await tester.pumpAndSettle();
          expect(listItems, orderedEquals(<String>['Item 3', 'Item 2', 'Item 4', 'Item 1']));

          handle.dispose();
        });

        testWidgets('Middle item accessibility (a11y) actions work', (WidgetTester tester) async {
          final SemanticsHandle handle = tester.ensureSemantics();
          expect(listItems, orderedEquals(originalListItems));

          // Test out move to end: move Item 2 to the end of the list.
          await tester.pumpWidget(build());
          Map<CustomSemanticsAction, VoidCallback> middleSemanticsActions = getSemanticsActions(1);
          middleSemanticsActions[moveToEnd]!();
          await tester.pumpAndSettle();
          expect(listItems, orderedEquals(<String>['Item 1', 'Item 3', 'Item 4', 'Item 2']));

          // Test out move after: move Item 3 (the current second item) one space down.
          await tester.pumpWidget(build());
          middleSemanticsActions = getSemanticsActions(1);
          middleSemanticsActions[moveDown]!();
          await tester.pumpAndSettle();
          expect(listItems, orderedEquals(<String>['Item 1', 'Item 4', 'Item 3', 'Item 2']));

          // Test out move after: move Item 3 (the current third item) one space up.
          await tester.pumpWidget(build());
          middleSemanticsActions = getSemanticsActions(2);
          middleSemanticsActions[moveUp]!();
          await tester.pumpAndSettle();
          expect(listItems, orderedEquals(<String>['Item 1', 'Item 3', 'Item 4', 'Item 2']));

          // Test out move to start: move Item 4 (the current third item) to the start of the list.
          await tester.pumpWidget(build());
          middleSemanticsActions = getSemanticsActions(2);
          middleSemanticsActions[moveToStart]!();
          await tester.pumpAndSettle();
          expect(listItems, orderedEquals(<String>['Item 4', 'Item 1', 'Item 3', 'Item 2']));

          handle.dispose();
        });

        testWidgets('Last item accessibility (a11y) actions work', (WidgetTester tester) async {
          final SemanticsHandle handle = tester.ensureSemantics();
          expect(listItems, orderedEquals(originalListItems));

          // Test out move to start: move Item 4 to the start of the list.
          await tester.pumpWidget(build());
          Map<CustomSemanticsAction, VoidCallback> lastSemanticsActions = getSemanticsActions(listItems.length - 1);
          lastSemanticsActions[moveToStart]!();
          await tester.pumpAndSettle();
          expect(listItems, orderedEquals(<String>['Item 4', 'Item 1', 'Item 2', 'Item 3']));

          // Test out move up: move Item 3 (the current last item) one space up.
          await tester.pumpWidget(build());
          lastSemanticsActions = getSemanticsActions(listItems.length - 1);
          lastSemanticsActions[moveUp]!();
          await tester.pumpAndSettle();
          expect(listItems, orderedEquals(<String>['Item 4', 'Item 1', 'Item 3', 'Item 2']));

          handle.dispose();
        });

        testWidgets("Doesn't hide accessibility when a child declares its own semantics", (WidgetTester tester) async {
          final SemanticsHandle handle = tester.ensureSemantics();
          final Widget reorderableListView = ReorderableListView(
            onReorder: (int oldIndex, int newIndex) { },
            children: <Widget>[
              const SizedBox(
                key: Key('List tile 1'),
                height: itemHeight,
                child: Text('List tile 1'),
              ),
              SizedBox(
                key: const Key('Switch tile'),
                height: itemHeight,
                child: Material(
                  child: SwitchListTile(
                    title: const Text('Switch tile'),
                    value: true,
                    onChanged: (bool? newValue) { },
                  ),
                ),
              ),
              const SizedBox(
                key: Key('List tile 2'),
                height: itemHeight,
                child: Text('List tile 2'),
              ),
            ],
          );
          await tester.pumpWidget(MaterialApp(
            home: SizedBox(
              height: itemHeight * 10,
              child: reorderableListView,
            ),
          ));

          // Get the switch tile's semantics:
          final SemanticsNode semanticsNode = tester.getSemantics(find.byKey(const Key('Switch tile')));

          // Check for ReorderableListView custom semantics actions.
          expect(semanticsNode, matchesSemantics(
            customActions: const <CustomSemanticsAction>[
              CustomSemanticsAction(label: 'Move up'),
              CustomSemanticsAction(label: 'Move down'),
              CustomSemanticsAction(label: 'Move to the end'),
              CustomSemanticsAction(label: 'Move to the start'),
            ],
          ));

          // Check for properties of SwitchTile semantics.
          late SemanticsNode child;
          semanticsNode.visitChildren((SemanticsNode node) {
            child = node;
            return false;
          });
          expect(child, matchesSemantics(
            hasToggledState: true,
            isToggled: true,
            isEnabled: true,
            isFocusable: true,
            hasEnabledState: true,
            label: 'Switch tile',
            hasTapAction: true,
          ));
          handle.dispose();
        });
      });
    });

    group('in horizontal mode', () {
      testWidgets('reorder is not triggered when children length is less or equals to 1', (WidgetTester tester) async {
        bool onReorderWasCalled = false;
        final List<String> currentListItems = listItems.take(1).toList();
        final ReorderableListView reorderableListView = ReorderableListView(
          header: const Text('Header'),
          scrollDirection: Axis.horizontal,
          onReorder: (_, __) => onReorderWasCalled = true,
          children: currentListItems.map<Widget>(listItemToWidget).toList(),
        );
        final List<String> currentOriginalListItems = originalListItems.take(1).toList();
        await tester.pumpWidget(MaterialApp(
          home: SizedBox(
            height: itemHeight * 10,
            child: reorderableListView,
          ),
        ));
        expect(currentListItems, orderedEquals(currentOriginalListItems));
        final TestGesture drag = await tester.startGesture(tester.getCenter(find.text('Item 1')));
        await tester.pump(kLongPressTimeout + kPressTimeout);
        expect(currentListItems, orderedEquals(currentOriginalListItems));
        await drag.moveTo(tester.getBottomLeft(find.text('Item 1')) * 2);
        expect(currentListItems, orderedEquals(currentOriginalListItems));
        await drag.up();
        expect(onReorderWasCalled, false);
        expect(currentListItems, orderedEquals(<String>['Item 1']));
      });

      testWidgets('allows reordering from the very top to the very bottom', (WidgetTester tester) async {
        await tester.pumpWidget(build(scrollDirection: Axis.horizontal));
        expect(listItems, orderedEquals(originalListItems));
        await longPressDrag(
          tester,
          tester.getCenter(find.text('Item 1')),
          tester.getCenter(find.text('Item 4')) + const Offset(itemHeight * 2, 0.0),
        );
        await tester.pumpAndSettle();
        expect(listItems, orderedEquals(<String>['Item 2', 'Item 3', 'Item 4', 'Item 1']));
      });

      testWidgets('allows reordering from the very bottom to the very top', (WidgetTester tester) async {
        await tester.pumpWidget(build(scrollDirection: Axis.horizontal));
        expect(listItems, orderedEquals(originalListItems));
        await longPressDrag(
          tester,
          tester.getCenter(find.text('Item 4')),
          tester.getCenter(find.text('Item 1')),
        );
        await tester.pumpAndSettle();
        expect(listItems, orderedEquals(<String>['Item 4', 'Item 1', 'Item 2', 'Item 3']));
      });

      testWidgets('allows reordering inside the middle of the widget', (WidgetTester tester) async {
        await tester.pumpWidget(build(scrollDirection: Axis.horizontal));
        expect(listItems, orderedEquals(originalListItems));
        await longPressDrag(
          tester,
          tester.getCenter(find.text('Item 3')),
          tester.getCenter(find.text('Item 2')),
        );
        await tester.pumpAndSettle();
        expect(listItems, orderedEquals(<String>['Item 1', 'Item 3', 'Item 2', 'Item 4']));
      });

      testWidgets('properly reorders with a header', (WidgetTester tester) async {
        await tester.pumpWidget(build(header: const Text('Header Text'), scrollDirection: Axis.horizontal));
        expect(find.text('Header Text'), findsOneWidget);
        expect(listItems, orderedEquals(originalListItems));
        await longPressDrag(
          tester,
          tester.getCenter(find.text('Item 1')),
          tester.getCenter(find.text('Item 4')) + const Offset(itemHeight * 2, 0.0),
        );
        await tester.pumpAndSettle();
        expect(find.text('Header Text'), findsOneWidget);
        expect(listItems, orderedEquals(<String>['Item 2', 'Item 3', 'Item 4', 'Item 1']));
        await tester.pumpWidget(build(header: const Text('Header Text'), scrollDirection: Axis.horizontal));
        await longPressDrag(
          tester,
          tester.getCenter(find.text('Item 4')),
          tester.getCenter(find.text('Item 3')),
        );
        await tester.pumpAndSettle();
        expect(find.text('Header Text'), findsOneWidget);
        expect(listItems, orderedEquals(<String>['Item 2', 'Item 4', 'Item 3', 'Item 1']));
      });

      testWidgets('properly reorders with a footer', (WidgetTester tester) async {
        await tester.pumpWidget(build(footer: const Text('Footer Text'), scrollDirection: Axis.horizontal));
        expect(find.text('Footer Text'), findsOneWidget);
        expect(listItems, orderedEquals(originalListItems));
        await longPressDrag(
          tester,
          tester.getCenter(find.text('Item 1')),
          tester.getCenter(find.text('Item 4')) + const Offset(itemHeight * 2, 0.0),
        );
        await tester.pumpAndSettle();
        expect(find.text('Footer Text'), findsOneWidget);
        expect(listItems, orderedEquals(<String>['Item 2', 'Item 3', 'Item 4', 'Item 1']));
        await tester.pumpWidget(build(footer: const Text('Footer Text'), scrollDirection: Axis.horizontal));
        await longPressDrag(
          tester,
          tester.getCenter(find.text('Item 4')),
          tester.getCenter(find.text('Item 3')),
        );
        await tester.pumpAndSettle();
        expect(find.text('Footer Text'), findsOneWidget);
        expect(listItems, orderedEquals(<String>['Item 2', 'Item 4', 'Item 3', 'Item 1']));
      });

      testWidgets('properly determines the horizontal drop area extents', (WidgetTester tester) async {
        final Widget reorderableListView = ReorderableListView(
          scrollDirection: Axis.horizontal,
          onReorder: (int oldIndex, int newIndex) { },
          children: const <Widget>[
            SizedBox(
              key: Key('Normal item'),
              width: itemHeight,
              child: Text('Normal item'),
            ),
            SizedBox(
              key: Key('Tall item'),
              width: itemHeight * 2,
              child: Text('Tall item'),
            ),
            SizedBox(
              key: Key('Last item'),
              width: itemHeight,
              child: Text('Last item'),
            ),
          ],
        );
        await tester.pumpWidget(MaterialApp(
          home: SizedBox(
            width: itemHeight * 10,
            child: reorderableListView,
          ),
        ));

        double getListWidth() {
          final RenderSliverList listScrollView = tester.renderObject(find.byType(SliverList));
          return listScrollView.geometry!.maxPaintExtent;
        }

        const double kDraggingListWidth = 4 * itemHeight;
        // Drag a normal text item
        expect(getListWidth(), kDraggingListWidth);
        TestGesture drag = await tester.startGesture(tester.getCenter(find.text('Normal item')));
        await tester.pump(kLongPressTimeout + kPressTimeout);
        await tester.pumpAndSettle();
        expect(getListWidth(), kDraggingListWidth);

        // Move it
        await drag.moveTo(tester.getCenter(find.text('Last item')));
        await tester.pumpAndSettle();
        expect(getListWidth(), kDraggingListWidth);

        // Drop it
        await drag.up();
        await tester.pumpAndSettle();
        expect(getListWidth(), kDraggingListWidth);

        // Drag a tall item
        drag = await tester.startGesture(tester.getCenter(find.text('Tall item')));
        await tester.pump(kLongPressTimeout + kPressTimeout);
        await tester.pumpAndSettle();
        expect(getListWidth(), kDraggingListWidth);
        // Move it
        await drag.moveTo(tester.getCenter(find.text('Last item')));
        await tester.pumpAndSettle();
        expect(getListWidth(), kDraggingListWidth);

        // Drop it
        await drag.up();
        await tester.pumpAndSettle();
        expect(getListWidth(), kDraggingListWidth);
      });

      testWidgets('Horizontal drag in progress golden image', (WidgetTester tester) async {
        debugDisableShadows = false;
        final Widget reorderableListView = ReorderableListView(
          scrollDirection: Axis.horizontal,
          onReorder: (int oldIndex, int newIndex) { },
          children: <Widget>[
            Container(
              key: const Key('pink'),
              height: double.infinity,
              width: itemHeight,
              color: Colors.pink,
            ),
            Container(
              key: const Key('blue'),
              height: double.infinity,
              width: itemHeight,
              color: Colors.blue,
            ),
            Container(
              key: const Key('green'),
              height: double.infinity,
              width: itemHeight,
              color: Colors.green,
            ),
          ],
        );

        late final OverlayEntry entry;
        addTearDown(() => entry..remove()..dispose());

        await tester.pumpWidget(MaterialApp(
          home: Container(
            color: Colors.white,
            width: itemHeight * 3,
            // Wrap in an overlay so that the golden image includes the dragged item.
            child: Overlay(
              initialEntries: <OverlayEntry>[
                entry = OverlayEntry(builder: (BuildContext context) {
                  // Wrap the list in padding to test that the positioning
                  // is correct when the origin of the overlay is different
                  // from the list.
                  return Padding(
                    padding: const EdgeInsets.all(24),
                    child: reorderableListView,
                  );
                }),
              ],
            ),
          ),
        ));

        // Start dragging the second item.
        final TestGesture drag = await tester.startGesture(tester.getCenter(find.byKey(const Key('blue'))));
        await tester.pump(kLongPressTimeout + kPressTimeout);

        // Drag it left to be partially over the first item.
        await drag.moveBy(const Offset(-itemHeight / 3, 0));
        await tester.pumpAndSettle();

        // Should be an image of the second item overlapping the right of the
        // first with a gap between the first and third and a drop shadow on
        // the dragged item.
        await expectLater(
          find.byType(Overlay).last,
          matchesGoldenFile('reorderable_list_test.horizontal.drop_area.png'),
        );
        debugDisableShadows = true;
      });

      testWidgets('Preserves children states when the list parent changes the order', (WidgetTester tester) async {
        _StatefulState findState(Key key) {
          return find.byElementPredicate((Element element) => element.findAncestorWidgetOfExactType<_Stateful>()?.key == key)
              .evaluate()
              .first
              .findAncestorStateOfType<_StatefulState>()!;
        }
        await tester.pumpWidget(MaterialApp(
          home: ReorderableListView(
            onReorder: (int oldIndex, int newIndex) { },
            scrollDirection: Axis.horizontal,
            children: <Widget>[
              _Stateful(key: const Key('A')),
              _Stateful(key: const Key('B')),
              _Stateful(key: const Key('C')),
            ],
          ),
        ));
        await tester.tap(find.byKey(const Key('A')));
        await tester.pumpAndSettle();
        // Only the 'A' widget should be checked.
        expect(findState(const Key('A')).checked, true);
        expect(findState(const Key('B')).checked, false);
        expect(findState(const Key('C')).checked, false);

        await tester.pumpWidget(MaterialApp(
          home: ReorderableListView(
            onReorder: (int oldIndex, int newIndex) { },
            scrollDirection: Axis.horizontal,
            children: <Widget>[
              _Stateful(key: const Key('B')),
              _Stateful(key: const Key('C')),
              _Stateful(key: const Key('A')),
            ],
          ),
        ));
        // Only the 'A' widget should be checked.
        expect(findState(const Key('B')).checked, false);
        expect(findState(const Key('C')).checked, false);
        expect(findState(const Key('A')).checked, true);
      });

      testWidgets('Preserves children states when rebuilt', (WidgetTester tester) async {
        const Key firstBox = Key('key');
        Widget build() {
          return MaterialApp(
            home: Directionality(
              textDirection: TextDirection.ltr,
              child: SizedBox(
                width: 100,
                height: 100,
                child: ReorderableListView(
                  scrollDirection: Axis.horizontal,
                  children: const <Widget>[
                    SizedBox(key: firstBox, width: 10, height: 10),
                  ],
                  onReorder: (_, __) {},
                ),
              ),
            ),
          );
        }

        // When the widget is rebuilt, the state of child should be consistent.
        await tester.pumpWidget(build());
        final Element e0 = tester.element(find.byKey(firstBox));
        await tester.pumpWidget(build());
        final Element e1 = tester.element(find.byKey(firstBox));
        expect(e0, equals(e1));
      });

      group('Accessibility (a11y/Semantics)', () {
        Map<CustomSemanticsAction, VoidCallback> getSemanticsActions(int index) {
          final Semantics semantics = find.ancestor(
            of: find.byKey(Key(listItems[index])),
            matching: find.byType(Semantics),
          ).evaluate().first.widget as Semantics;
          return semantics.properties.customSemanticsActions!;
        }

        const CustomSemanticsAction moveToStart = CustomSemanticsAction(label: 'Move to the start');
        const CustomSemanticsAction moveToEnd = CustomSemanticsAction(label: 'Move to the end');
        const CustomSemanticsAction moveLeft = CustomSemanticsAction(label: 'Move left');
        const CustomSemanticsAction moveRight = CustomSemanticsAction(label: 'Move right');

        testWidgets('Provides the correct accessibility actions in LTR mode', (WidgetTester tester) async {
          final SemanticsHandle handle = tester.ensureSemantics();

          await tester.pumpWidget(build(scrollDirection: Axis.horizontal));

          // The first item can be moved right or to the end.
          final Map<CustomSemanticsAction, VoidCallback> firstSemanticsActions = getSemanticsActions(0);
          expect(firstSemanticsActions.length, 2, reason: 'The first list item should have 2 custom actions.');
          expect(firstSemanticsActions.containsKey(moveToStart), false, reason: 'The first item cannot `Move to the start`.');
          expect(firstSemanticsActions.containsKey(moveLeft), false, reason: 'The first item cannot `Move left`.');
          expect(firstSemanticsActions.containsKey(moveRight), true, reason: 'The first item should be able to `Move right`.');
          expect(firstSemanticsActions.containsKey(moveToEnd), true, reason: 'The first item should be able to `Move to the end`.');

          // Items in the middle can be moved to the start, end, left or right.
          for (int i = 1; i < listItems.length - 1; i += 1) {
            final Map<CustomSemanticsAction, VoidCallback> ithSemanticsActions = getSemanticsActions(i);
            expect(ithSemanticsActions.length, 4, reason: 'List item $i should have 4 custom actions.');
            expect(ithSemanticsActions.containsKey(moveToStart), true, reason: 'List item $i should be able to `Move to the start`.');
            expect(ithSemanticsActions.containsKey(moveLeft), true, reason: 'List item $i should be able to `Move left`.');
            expect(ithSemanticsActions.containsKey(moveRight), true, reason: 'List item $i should be able to `Move right`.');
            expect(ithSemanticsActions.containsKey(moveToEnd), true, reason: 'List item $i should be able to `Move to the end`.');
          }

          // The last item can be moved left or to the start.
          final Map<CustomSemanticsAction, VoidCallback> lastSemanticsActions = getSemanticsActions(listItems.length - 1);
          expect(lastSemanticsActions.length, 2, reason: 'The last list item should have 2 custom actions.');
          expect(lastSemanticsActions.containsKey(moveToStart), true, reason: 'The last item should be able to `Move to the start`.');
          expect(lastSemanticsActions.containsKey(moveLeft), true, reason: 'The last item should be able to `Move left`.');
          expect(lastSemanticsActions.containsKey(moveRight), false, reason: 'The last item cannot `Move right`.');
          expect(lastSemanticsActions.containsKey(moveToEnd), false, reason: 'The last item cannot `Move to the end`.');
          handle.dispose();
        });

        testWidgets('Provides the correct accessibility actions in Right-To-Left directionality', (WidgetTester tester) async {
          // In RTL mode, the right is the start and the left is the end.
          // The array representation is unchanged (LTR), but the direction of the motion actions is reversed.
          final SemanticsHandle handle = tester.ensureSemantics();

          await tester.pumpWidget(build(scrollDirection: Axis.horizontal, textDirection: TextDirection.rtl));

          // The first item can be moved right or to the end.
          final Map<CustomSemanticsAction, VoidCallback> firstSemanticsActions = getSemanticsActions(0);
          expect(firstSemanticsActions.length, 2, reason: 'The first list item should have 2 custom actions.');
          expect(firstSemanticsActions.containsKey(moveToStart), false, reason: 'The first item cannot `Move to the start`.');
          expect(firstSemanticsActions.containsKey(moveRight), false, reason: 'The first item cannot `Move right`.');
          expect(firstSemanticsActions.containsKey(moveLeft), true, reason: 'The first item should be able to `Move left`.');
          expect(firstSemanticsActions.containsKey(moveToEnd), true, reason: 'The first item should be able to `Move to the end`.');

          // Items in the middle can be moved to the start, end, left or right.
          for (int i = 1; i < listItems.length - 1; i += 1) {
            final Map<CustomSemanticsAction, VoidCallback> ithSemanticsActions = getSemanticsActions(i);
            expect(ithSemanticsActions.length, 4, reason: 'List item $i should have 4 custom actions.');
            expect(ithSemanticsActions.containsKey(moveToStart), true, reason: 'List item $i should be able to `Move to the start`.');
            expect(ithSemanticsActions.containsKey(moveRight), true, reason: 'List item $i should be able to `Move right`.');
            expect(ithSemanticsActions.containsKey(moveLeft), true, reason: 'List item $i should be able to `Move left`.');
            expect(ithSemanticsActions.containsKey(moveToEnd), true, reason: 'List item $i should be able to `Move to the end`.');
          }

          // The last item can be moved left or to the start.
          final Map<CustomSemanticsAction, VoidCallback> lastSemanticsActions = getSemanticsActions(listItems.length - 1);
          expect(lastSemanticsActions.length, 2, reason: 'The last list item should have 2 custom actions.');
          expect(lastSemanticsActions.containsKey(moveToStart), true, reason: 'The last item should be able to `Move to the start`.');
          expect(lastSemanticsActions.containsKey(moveRight), true, reason: 'The last item should be able to `Move right`.');
          expect(lastSemanticsActions.containsKey(moveLeft), false, reason: 'The last item cannot `Move left`.');
          expect(lastSemanticsActions.containsKey(moveToEnd), false, reason: 'The last item cannot `Move to the end`.');
          handle.dispose();
        });

        testWidgets('First item accessibility (a11y) actions work in LTR mode', (WidgetTester tester) async {
          final SemanticsHandle handle = tester.ensureSemantics();
          expect(listItems, orderedEquals(originalListItems));

          // Test out move to end: move Item 1 to the end of the list.
          await tester.pumpWidget(build(scrollDirection: Axis.horizontal));
          Map<CustomSemanticsAction, VoidCallback> firstSemanticsActions = getSemanticsActions(0);
          firstSemanticsActions[moveToEnd]!();
          await tester.pumpAndSettle();
          expect(listItems, orderedEquals(<String>['Item 2', 'Item 3', 'Item 4', 'Item 1']));

          // Test out move after: move Item 2 (the current first item) one space to the right.
          await tester.pumpWidget(build(scrollDirection: Axis.horizontal));
          firstSemanticsActions = getSemanticsActions(0);
          firstSemanticsActions[moveRight]!();
          await tester.pumpAndSettle();
          expect(listItems, orderedEquals(<String>['Item 3', 'Item 2', 'Item 4', 'Item 1']));

          handle.dispose();
        });

        testWidgets('First item accessibility (a11y) actions work in Right-To-Left directionality', (WidgetTester tester) async {
          // In RTL mode, the right is the start and the left is the end.
          // The array representation is unchanged (LTR), but the direction of the motion actions is reversed.
          final SemanticsHandle handle = tester.ensureSemantics();
          expect(listItems, orderedEquals(originalListItems));

          // Test out move to end: move Item 1 to the end of the list.
          await tester.pumpWidget(build(scrollDirection: Axis.horizontal, textDirection: TextDirection.rtl));
          Map<CustomSemanticsAction, VoidCallback> firstSemanticsActions = getSemanticsActions(0);
          firstSemanticsActions[moveToEnd]!();
          await tester.pumpAndSettle();
          expect(listItems, orderedEquals(<String>['Item 2', 'Item 3', 'Item 4', 'Item 1']));

          // Test out move after: move Item 2 (the current first item) one space to the left.
          await tester.pumpWidget(build(scrollDirection: Axis.horizontal, textDirection: TextDirection.rtl));
          firstSemanticsActions = getSemanticsActions(0);
          firstSemanticsActions[moveLeft]!();
          await tester.pumpAndSettle();
          expect(listItems, orderedEquals(<String>['Item 3', 'Item 2', 'Item 4', 'Item 1']));

          handle.dispose();
        });

        testWidgets('Middle item accessibility (a11y) actions work in LTR mode', (WidgetTester tester) async {
          final SemanticsHandle handle = tester.ensureSemantics();
          expect(listItems, orderedEquals(originalListItems));

          // Test out move to end: move Item 2 to the end of the list.
          await tester.pumpWidget(build(scrollDirection: Axis.horizontal));
          Map<CustomSemanticsAction, VoidCallback> middleSemanticsActions = getSemanticsActions(1);
          middleSemanticsActions[moveToEnd]!();
          await tester.pumpAndSettle();
          expect(listItems, orderedEquals(<String>['Item 1', 'Item 3', 'Item 4', 'Item 2']));

          // Test out move after: move Item 3 (the current second item) one space to the right.
          await tester.pumpWidget(build(scrollDirection: Axis.horizontal));
          middleSemanticsActions = getSemanticsActions(1);
          middleSemanticsActions[moveRight]!();
          await tester.pumpAndSettle();
          expect(listItems, orderedEquals(<String>['Item 1', 'Item 4', 'Item 3', 'Item 2']));

          // Test out move after: move Item 3 (the current third item) one space to the left.
          await tester.pumpWidget(build(scrollDirection: Axis.horizontal));
          middleSemanticsActions = getSemanticsActions(2);
          middleSemanticsActions[moveLeft]!();
          await tester.pumpAndSettle();
          expect(listItems, orderedEquals(<String>['Item 1', 'Item 3', 'Item 4', 'Item 2']));

          // Test out move to start: move Item 4 (the current third item) to the start of the list.
          await tester.pumpWidget(build(scrollDirection: Axis.horizontal));
          middleSemanticsActions = getSemanticsActions(2);
          middleSemanticsActions[moveToStart]!();
          await tester.pumpAndSettle();
          expect(listItems, orderedEquals(<String>['Item 4', 'Item 1', 'Item 3', 'Item 2']));

          handle.dispose();
        });

        testWidgets('Middle item accessibility (a11y) actions work in Right-To-Left directionality', (WidgetTester tester) async {
          // In RTL mode, the right is the start and the left is the end.
          // The array representation is unchanged (LTR), but the direction of the motion actions is reversed.
          final SemanticsHandle handle = tester.ensureSemantics();
          expect(listItems, orderedEquals(originalListItems));

          // Test out move to end: move Item 2 to the end of the list.
          await tester.pumpWidget(build(scrollDirection: Axis.horizontal, textDirection: TextDirection.rtl));
          Map<CustomSemanticsAction, VoidCallback> middleSemanticsActions = getSemanticsActions(1);
          middleSemanticsActions[moveToEnd]!();
          await tester.pumpAndSettle();
          expect(listItems, orderedEquals(<String>['Item 1', 'Item 3', 'Item 4', 'Item 2']));

          // Test out move after: move Item 3 (the current second item) one space to the left.
          await tester.pumpWidget(build(scrollDirection: Axis.horizontal, textDirection: TextDirection.rtl));
          middleSemanticsActions = getSemanticsActions(1);
          middleSemanticsActions[moveLeft]!();
          await tester.pumpAndSettle();
          expect(listItems, orderedEquals(<String>['Item 1', 'Item 4', 'Item 3', 'Item 2']));

          // Test out move after: move Item 3 (the current third item) one space to the right.
          await tester.pumpWidget(build(scrollDirection: Axis.horizontal, textDirection: TextDirection.rtl));
          middleSemanticsActions = getSemanticsActions(2);
          middleSemanticsActions[moveRight]!();
          await tester.pumpAndSettle();
          expect(listItems, orderedEquals(<String>['Item 1', 'Item 3', 'Item 4', 'Item 2']));

          // Test out move to start: move Item 4 (the current third item) to the start of the list.
          await tester.pumpWidget(build(scrollDirection: Axis.horizontal, textDirection: TextDirection.rtl));
          middleSemanticsActions = getSemanticsActions(2);
          middleSemanticsActions[moveToStart]!();
          await tester.pumpAndSettle();
          expect(listItems, orderedEquals(<String>['Item 4', 'Item 1', 'Item 3', 'Item 2']));

          handle.dispose();
        });

        testWidgets('Last item accessibility (a11y) actions work in LTR mode', (WidgetTester tester) async {
          final SemanticsHandle handle = tester.ensureSemantics();
          expect(listItems, orderedEquals(originalListItems));

          // Test out move to start: move Item 4 to the start of the list.
          await tester.pumpWidget(build(scrollDirection: Axis.horizontal));
          Map<CustomSemanticsAction, VoidCallback> lastSemanticsActions = getSemanticsActions(listItems.length - 1);
          lastSemanticsActions[moveToStart]!();
          await tester.pumpAndSettle();
          expect(listItems, orderedEquals(<String>['Item 4', 'Item 1', 'Item 2', 'Item 3']));

          // Test out move before: move Item 3 (the current last item) one space to the left.
          await tester.pumpWidget(build(scrollDirection: Axis.horizontal));
          lastSemanticsActions = getSemanticsActions(listItems.length - 1);
          lastSemanticsActions[moveLeft]!();
          await tester.pumpAndSettle();
          expect(listItems, orderedEquals(<String>['Item 4', 'Item 1', 'Item 3', 'Item 2']));

          handle.dispose();
        });

        testWidgets('Last item accessibility (a11y) actions work in Right-To-Left directionality', (WidgetTester tester) async {
          // In RTL mode, the right is the start and the left is the end.
          // The array representation is unchanged (LTR), but the direction of the motion actions is reversed.
          final SemanticsHandle handle = tester.ensureSemantics();
          expect(listItems, orderedEquals(originalListItems));

          // Test out move to start: move Item 4 to the start of the list.
          await tester.pumpWidget(build(scrollDirection: Axis.horizontal, textDirection: TextDirection.rtl));
          Map<CustomSemanticsAction, VoidCallback> lastSemanticsActions = getSemanticsActions(listItems.length - 1);
          lastSemanticsActions[moveToStart]!();
          await tester.pumpAndSettle();
          expect(listItems, orderedEquals(<String>['Item 4', 'Item 1', 'Item 2', 'Item 3']));

          // Test out move before: move Item 3 (the current last item) one space to the right.
          await tester.pumpWidget(build(scrollDirection: Axis.horizontal, textDirection: TextDirection.rtl));
          lastSemanticsActions = getSemanticsActions(listItems.length - 1);
          lastSemanticsActions[moveRight]!();
          await tester.pumpAndSettle();
          expect(listItems, orderedEquals(<String>['Item 4', 'Item 1', 'Item 3', 'Item 2']));

          handle.dispose();
        });
      });

    });


    testWidgets('ReorderableListView.builder asserts on negative childCount', (WidgetTester tester) async {
      expect(() => ReorderableListView.builder(
        itemBuilder: (BuildContext context, int index) {
          return const SizedBox();
        },
        itemCount: -1,
        onReorder: (int from, int to) {},
      ), throwsAssertionError);
    });

    testWidgets('ReorderableListView.builder only creates the children it needs', (WidgetTester tester) async {
      final Set<int> itemsCreated = <int>{};
      await tester.pumpWidget(MaterialApp(
        home: ReorderableListView.builder(
          itemBuilder: (BuildContext context, int index) {
            itemsCreated.add(index);
            return Text(index.toString(), key: ValueKey<int>(index));
          },
          itemCount: 1000,
          onReorder: (int from, int to) {},
        ),
      ));

      // Should have only created the first 18 items.
      expect(itemsCreated, <int>{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17});
    });

    group('Padding', () {
      testWidgets('Padding with no header & footer', (WidgetTester tester) async {
        const EdgeInsets padding = EdgeInsets.fromLTRB(10, 20, 30, 40);

        // Vertical
        await tester.pumpWidget(build(padding: padding));
        expect(tester.getRect(find.byKey(const Key('Item 1'))), const Rect.fromLTRB(10, 20, 770, 68));
        expect(tester.getRect(find.byKey(const Key('Item 4'))), const Rect.fromLTRB(10, 164, 770, 212));

        // Horizontal
        await tester.pumpWidget(build(padding: padding, scrollDirection: Axis.horizontal));
        expect(tester.getRect(find.byKey(const Key('Item 1'))), const Rect.fromLTRB(10, 20, 58, 560));
        expect(tester.getRect(find.byKey(const Key('Item 4'))), const Rect.fromLTRB(154, 20, 202, 560));
      });

      testWidgets('Padding with header or footer', (WidgetTester tester) async {
        const EdgeInsets padding = EdgeInsets.fromLTRB(10, 20, 30, 40);
        const Key headerKey = Key('Header');
        const Key footerKey = Key('Footer');
        const Widget verticalHeader = SizedBox(key: headerKey, height: 10);
        const Widget horizontalHeader = SizedBox(key: headerKey, width: 10);
        const Widget verticalFooter = SizedBox(key: footerKey, height: 10);
        const Widget horizontalFooter = SizedBox(key: footerKey, width: 10);

        // Vertical Header
        await tester.pumpWidget(build(padding: padding, header: verticalHeader));
        expect(tester.getRect(find.byKey(headerKey)), const Rect.fromLTRB(10, 20, 770, 30));
        expect(tester.getRect(find.byKey(const Key('Item 1'))), const Rect.fromLTRB(10, 30, 770, 78));
        expect(tester.getRect(find.byKey(const Key('Item 4'))), const Rect.fromLTRB(10, 174, 770, 222));

        // Vertical Footer
        await tester.pumpWidget(build(padding: padding, footer: verticalFooter));
        expect(tester.getRect(find.byKey(footerKey)), const Rect.fromLTRB(10, 212, 770, 222));
        expect(tester.getRect(find.byKey(const Key('Item 1'))), const Rect.fromLTRB(10, 20, 770, 68));
        expect(tester.getRect(find.byKey(const Key('Item 4'))), const Rect.fromLTRB(10, 164, 770, 212));

        // Vertical Header, reversed
        await tester.pumpWidget(build(padding: padding, header: verticalHeader, reverse: true));
        expect(tester.getRect(find.byKey(headerKey)), const Rect.fromLTRB(10, 550, 770, 560));
        expect(tester.getRect(find.byKey(const Key('Item 1'))), const Rect.fromLTRB(10, 502, 770, 550));
        expect(tester.getRect(find.byKey(const Key('Item 4'))), const Rect.fromLTRB(10, 358, 770, 406));

        // Vertical Footer, reversed
        await tester.pumpWidget(build(padding: padding, footer: verticalFooter, reverse: true));
        expect(tester.getRect(find.byKey(footerKey)), const Rect.fromLTRB(10, 358, 770, 368));
        expect(tester.getRect(find.byKey(const Key('Item 1'))), const Rect.fromLTRB(10, 512, 770, 560));
        expect(tester.getRect(find.byKey(const Key('Item 4'))), const Rect.fromLTRB(10, 368, 770, 416));

        // Horizontal Header
        await tester.pumpWidget(build(padding: padding, header: horizontalHeader, scrollDirection: Axis.horizontal));
        expect(tester.getRect(find.byKey(headerKey)), const Rect.fromLTRB(10, 20, 20, 560));
        expect(tester.getRect(find.byKey(const Key('Item 1'))), const Rect.fromLTRB(20, 20, 68, 560));
        expect(tester.getRect(find.byKey(const Key('Item 4'))), const Rect.fromLTRB(164, 20, 212, 560));

        // // Horizontal Footer
        await tester.pumpWidget(build(padding: padding, footer: horizontalFooter, scrollDirection: Axis.horizontal));
        expect(tester.getRect(find.byKey(footerKey)), const Rect.fromLTRB(202, 20, 212, 560));
        expect(tester.getRect(find.byKey(const Key('Item 1'))), const Rect.fromLTRB(10, 20, 58, 560));
        expect(tester.getRect(find.byKey(const Key('Item 4'))), const Rect.fromLTRB(154, 20, 202, 560));

        // Horizontal Header, reversed
        await tester.pumpWidget(build(padding: padding, header: horizontalHeader, scrollDirection: Axis.horizontal, reverse: true));
        expect(tester.getRect(find.byKey(headerKey)), const Rect.fromLTRB(760, 20, 770, 560));
        expect(tester.getRect(find.byKey(const Key('Item 1'))), const Rect.fromLTRB(712, 20, 760, 560));
        expect(tester.getRect(find.byKey(const Key('Item 4'))), const Rect.fromLTRB(568, 20, 616, 560));

        // // Horizontal Footer, reversed
        await tester.pumpWidget(build(padding: padding, footer: horizontalFooter, scrollDirection: Axis.horizontal, reverse: true));
        expect(tester.getRect(find.byKey(footerKey)), const Rect.fromLTRB(568, 20, 578, 560));
        expect(tester.getRect(find.byKey(const Key('Item 1'))), const Rect.fromLTRB(722, 20, 770, 560));
        expect(tester.getRect(find.byKey(const Key('Item 4'))), const Rect.fromLTRB(578, 20, 626, 560));
      });
    });

    testWidgets('ReorderableListView can be reversed', (WidgetTester tester) async {
      final Widget reorderableListView = ReorderableListView(
        reverse: true,
        onReorder: (int oldIndex, int newIndex) { },
        children: const <Widget>[
          SizedBox(
            key: Key('A'),
            child: Text('A'),
          ),
          SizedBox(
            key: Key('B'),
            child: Text('B'),
          ),
          SizedBox(
            key: Key('C'),
            child: Text('C'),
          ),
        ],
      );
      await tester.pumpWidget(MaterialApp(
        home: reorderableListView,
      ));
      expect(tester.getCenter(find.text('A')).dy, greaterThan(tester.getCenter(find.text('B')).dy));
    });

    testWidgets('Animation test when placing an item in place', (WidgetTester tester) async {
      const Key testItemKey = Key('Test item');
      final Widget reorderableListView = ReorderableListView(
        onReorder: (int oldIndex, int newIndex) { },
        children: const <Widget>[
          SizedBox(
            key: Key('First item'),
            height: itemHeight,
            child: Text('First item'),
          ),
          SizedBox(
            key: testItemKey,
            height: itemHeight,
            child: Text('Test item'),
          ),
          SizedBox(
            key: Key('Last item'),
            height: itemHeight,
            child: Text('Last item'),
          ),
        ],
      );
      await tester.pumpWidget(MaterialApp(
        home: SizedBox(
          height: itemHeight * 10,
          child: reorderableListView,
        ),
      ));

      Offset getTestItemPosition() {
        final RenderBox testItem = tester.renderObject<RenderBox>(find.byKey(testItemKey));
        return testItem.localToGlobal(Offset.zero);
      }
      // Before pick it up.
      final Offset startPosition = getTestItemPosition();

      // Pick it up.
      final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byKey(testItemKey)));
      await tester.pump(kLongPressTimeout + kPressTimeout);
      expect(getTestItemPosition(), startPosition);

      // Put it down.
      await gesture.up();
      await tester.pump();
      expect(getTestItemPosition(), startPosition);

      // After put it down.
      await tester.pumpAndSettle();
      expect(getTestItemPosition(), startPosition);
    });
    // TODO(djshuckerow): figure out how to write a test for scrolling the list.

    testWidgets('ReorderableListView on desktop platforms should have drag handles', (WidgetTester tester) async {
      await tester.pumpWidget(build());
      // All four items should have drag handles and not delayed listeners.
      expect(find.byIcon(Icons.drag_handle), findsNWidgets(4));
      expect(find.byType(ReorderableDelayedDragStartListener), findsNothing);
    }, variant: TargetPlatformVariant.desktop());

    testWidgets('ReorderableListView on mobile platforms should not have drag handles', (WidgetTester tester) async {
      await tester.pumpWidget(build());
      // All four items should have delayed listeners and not drag handles.
      expect(find.byType(ReorderableDelayedDragStartListener), findsNWidgets(4));
      expect(find.byIcon(Icons.drag_handle), findsNothing);
    }, variant: TargetPlatformVariant.mobile());

    testWidgets('Vertical list renders drag handle in correct position', (WidgetTester tester) async {
      await tester.pumpWidget(build(platform: TargetPlatform.macOS));
      final Finder listView = find.byType(ReorderableListView);
      final Finder item1 = find.byKey(const Key('Item 1'));
      final Finder dragHandle = find.byIcon(Icons.drag_handle).first;

      // Should be centered vertically within the item and 8 pixels from the right edge of the list.
      expect(tester.getCenter(dragHandle).dy, tester.getCenter(item1).dy);
      expect(tester.getTopRight(dragHandle).dx, tester.getSize(listView).width - 8);
    });

    testWidgets('Horizontal list renders drag handle in correct position', (WidgetTester tester) async {
      await tester.pumpWidget(build(scrollDirection: Axis.horizontal, platform: TargetPlatform.macOS));
      final Finder listView = find.byType(ReorderableListView);
      final Finder item1 = find.byKey(const Key('Item 1'));
      final Finder dragHandle = find.byIcon(Icons.drag_handle).first;

      // Should be centered horizontally within the item and 8 pixels from the bottom of the list.
      expect(tester.getCenter(dragHandle).dx, tester.getCenter(item1).dx);
      expect(tester.getBottomRight(dragHandle).dy, tester.getSize(listView).height - 8);
    });
  });

  testWidgets('ReorderableListView, can deal with the dragged item getting unmounted and rebuilt during drag', (WidgetTester tester) async {
    // See https://github.com/flutter/flutter/issues/74840 for more details.
    final List<int> items = List<int>.generate(100, (int index) => index);

    void handleReorder(int fromIndex, int toIndex) {
      if (toIndex > fromIndex) {
        toIndex -= 1;
      }
      items.insert(toIndex, items.removeAt(fromIndex));
    }

    // The list is 800x600, 8 items, each item is 800x100 with
    // an "item $index" text widget at the item's origin.  Drags are initiated by
    // a simple press on the text widget.
    await tester.pumpWidget(MaterialApp(
      home: ReorderableListView.builder(
        itemBuilder: (BuildContext context, int index) {
          return SizedBox(
            key: ValueKey<int>(items[index]),
            height: 100,
            child: ReorderableDragStartListener(
              index: index,
              child: Row(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  Text('item ${items[index]}'),
                ],
              ),
            ),
          );
        },
        buildDefaultDragHandles: false,
        itemCount: items.length,
        onReorder: handleReorder,
      ),
    ));

    // Drag item 0 downwards and force an auto scroll off the end of the list
    // far enough that item zeros original entry in the list is unmounted.
    final TestGesture drag = await tester.startGesture(tester.getCenter(find.text('item 0')));
    await tester.pump(kPressTimeout);
    // Off the bottom of the screen, which should autoscroll until we hit the
    // end of the list
    await drag.moveBy(const Offset(0, 700));
    await tester.pump(const Duration(seconds: 30));
    await tester.pumpAndSettle();
    // Ensure we made it to the bottom (only 4 should be showing as there should
    // be a gap at the end for the drop area of the dragged item.
    for (final int i in <int>[95, 96, 97, 98, 99]) {
      expect(find.text('item $i'), findsOneWidget);
    }

    // Drag back to off the top of the list, which should autoscroll until
    // we hit the beginning of the list. This should cause the first item's
    // entry to be rebuilt. However, the contents should not be in both places.
    await drag.moveBy(const Offset(0, -1400));
    await tester.pump(const Duration(seconds: 30));
    await tester.pumpAndSettle();
    // Release back at the top so item 0 should drop where it was
    await drag.up();
    await tester.pumpAndSettle();

    // Should not have changed anything
    for (final int i in <int>[0, 1, 2, 3, 4, 5]) {
      expect(find.text('item $i'), findsOneWidget);
    }
    expect(items.take(8), orderedEquals(<int>[0, 1, 2, 3, 4, 5, 6, 7]));
  });

  testWidgets('ReorderableListView calls onReorderStart and onReorderEnd correctly', (WidgetTester tester) async {
    final List<int> items = List<int>.generate(8, (int index) => index);
    int? startIndex, endIndex;
    final Finder item0 = find.textContaining('item 0');

    void handleReorder(int fromIndex, int toIndex) {
      if (toIndex > fromIndex) {
        toIndex -= 1;
      }
      items.insert(toIndex, items.removeAt(fromIndex));
    }

    await tester.pumpWidget(MaterialApp(
      home: ReorderableListView.builder(
        itemBuilder: (BuildContext context, int index) {
          return SizedBox(
            key: ValueKey<int>(items[index]),
            height: 100,
            child: ReorderableDragStartListener(
              index: index,
              child: Row(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  Text('item ${items[index]}'),
                ],
              ),
            ),
          );
        },
        buildDefaultDragHandles: false,
        itemCount: items.length,
        onReorder: handleReorder,
        onReorderStart: (int index) {
          startIndex = index;
        },
        onReorderEnd: (int index) {
          endIndex = index;
        },
      ),
    ));

    TestGesture drag = await tester.startGesture(tester.getCenter(item0));
    await tester.pump(kPressTimeout);
    // Drag enough for move to start.
    await drag.moveBy(const Offset(0, 20));

    expect(startIndex, equals(0));
    expect(endIndex, isNull);

    // Move item0 from index 0 to index 3
    await drag.moveBy(const Offset(0, 300));
    await tester.pumpAndSettle();
    await drag.up();
    await tester.pumpAndSettle();

    expect(endIndex, equals(3));

    startIndex = null;
    endIndex = null;

    drag = await tester.startGesture(tester.getCenter(item0));
    await tester.pump(kPressTimeout);
    // Drag enough for move to start.
    await drag.moveBy(const Offset(0, 20));

    expect(startIndex, equals(2));
    expect(endIndex, isNull);

    // Move item0 from index 2 to index 0
    await drag.moveBy(const Offset(0, -200));
    await tester.pumpAndSettle();
    await drag.up();
    await tester.pumpAndSettle();

    expect(endIndex, equals(0));
  });

  testWidgets('ReorderableListView throws an error when key is not passed to its children', (WidgetTester tester) async {
    final Widget reorderableListView = ReorderableListView.builder(
      itemBuilder: (BuildContext context, int index) {
        return SizedBox(child: Text('Item $index'));
      },
      itemCount: 3,
      onReorder: (int oldIndex, int newIndex) { },
    );
    await tester.pumpWidget(MaterialApp(
      home: reorderableListView,
    ));
    final dynamic exception = tester.takeException();
    expect(exception, isFlutterError);
    expect(exception.toString(), contains('Every item of ReorderableListView must have a key.'));
  });

  testWidgets('Throws an error if no overlay present', (WidgetTester tester) async {
    final Widget reorderableList = ReorderableListView(
      children: const <Widget>[
        SizedBox(width: 100.0, height: 100.0, key: Key('C'), child: Text('C')),
        SizedBox(width: 100.0, height: 100.0, key: Key('B'), child: Text('B')),
        SizedBox(width: 100.0, height: 100.0, key: Key('A'), child: Text('A')),
      ],
      onReorder: (int oldIndex, int newIndex) { },
    );
    final Widget boilerplate = Localizations(
      locale: const Locale('en'),
      delegates: const <LocalizationsDelegate<dynamic>>[
        DefaultMaterialLocalizations.delegate,
        DefaultWidgetsLocalizations.delegate,
      ],
      child: SizedBox(
        width: 100.0,
        height: 100.0,
        child: Directionality(
          textDirection: TextDirection.ltr,
          child: reorderableList,
        ),
      ),
    );
    await tester.pumpWidget(boilerplate);

    final dynamic exception = tester.takeException();
    expect(exception, isFlutterError);
    expect(exception.toString(), contains('No Overlay widget found'));
    expect(exception.toString(), contains('ReorderableListView widgets require an Overlay widget ancestor'));
  });

  testWidgets('ReorderableListView asserts on both non-null itemExtent and prototypeItem', (WidgetTester tester) async {
    expect(() => ReorderableListView(
      itemExtent: 30,
      prototypeItem: const SizedBox(),
      onReorder: (int fromIndex, int toIndex) { },
      children: const <Widget>[],
    ), throwsAssertionError);
  });

  testWidgets('ReorderableListView.builder asserts on both non-null itemExtent and prototypeItem', (WidgetTester tester) async {
    final List<int> numbers = <int>[0,1,2];
    expect(() => ReorderableListView.builder(
      itemBuilder: (BuildContext context, int index) {
        return SizedBox(
            key: ValueKey<int>(numbers[index]),
            height: 20 + numbers[index] * 10,
            child: ReorderableDragStartListener(
              index: index,
              child: Text(numbers[index].toString()),
            )
        );
      },
      itemCount: numbers.length,
      itemExtent: 30,
      prototypeItem: const SizedBox(),
      onReorder: (int fromIndex, int toIndex) { },
    ), throwsAssertionError);
  });

  testWidgets('if itemExtent is non-null, children have same extent in the scroll direction', (WidgetTester tester) async {
    final List<int> numbers = <int>[0,1,2];

    await tester.pumpWidget(
        MaterialApp(
          home: Scaffold(
            body: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
                return ReorderableListView.builder(
                  itemBuilder: (BuildContext context, int index) {
                    return SizedBox(
                        key: ValueKey<int>(numbers[index]),
                        // children with different heights
                        height: 20 + numbers[index] * 10,
                        child: ReorderableDragStartListener(
                          index: index,
                          child: Text(numbers[index].toString()),
                        )
                    );
                  },
                  itemCount: numbers.length,
                  itemExtent: 30,
                  onReorder: (int fromIndex, int toIndex) { },
                );
              },
            ),
          ),
        )
    );

    final double item0Height = tester.getSize(find.text('0').hitTestable()).height;
    final double item1Height = tester.getSize(find.text('1').hitTestable()).height;
    final double item2Height = tester.getSize(find.text('2').hitTestable()).height;

    expect(item0Height, 30.0);
    expect(item1Height, 30.0);
    expect(item2Height, 30.0);
  });

  testWidgets('if prototypeItem is non-null, children have same extent in the scroll direction', (WidgetTester tester) async {
    final List<int> numbers = <int>[0,1,2];

    await tester.pumpWidget(
        MaterialApp(
          home: Scaffold(
            body: StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
                return ReorderableListView.builder(
                  itemBuilder: (BuildContext context, int index) {
                    return SizedBox(
                        key: ValueKey<int>(numbers[index]),
                        // children with different heights
                        height: 20 + numbers[index] * 10,
                        child: ReorderableDragStartListener(
                          index: index,
                          child: Text(numbers[index].toString()),
                        )
                    );
                  },
                  itemCount: numbers.length,
                  prototypeItem: const SizedBox(
                    height: 30,
                    child: Text('3'),
                  ),
                  onReorder: (int oldIndex, int newIndex) {  },
                );
              },
            ),
          ),
        )
    );

    final double item0Height = tester.getSize(find.text('0').hitTestable()).height;
    final double item1Height = tester.getSize(find.text('1').hitTestable()).height;
    final double item2Height = tester.getSize(find.text('2').hitTestable()).height;

    expect(item0Height, 30.0);
    expect(item1Height, 30.0);
    expect(item2Height, 30.0);
  });

  testWidgets('ReorderableListView auto scrolls speed is configurable', (WidgetTester tester) async {
    Future<void> pumpFor({
      required Duration duration,
      Duration interval = const Duration(milliseconds: 50),
    }) async {
      await tester.pump();

      int times = (duration.inMilliseconds / interval.inMilliseconds).ceil();
      while (times > 0) {
        await tester.pump(interval + const Duration(milliseconds: 1));
        await tester.idle();
        times--;
      }
    }

    Future<double> pumpListAndDrag({required double autoScrollerVelocityScalar}) async {
      final List<int> items = List<int>.generate(10, (int index) => index);
      final ScrollController scrollController = ScrollController();
      addTearDown(scrollController.dispose);

      await tester.pumpWidget(
        MaterialApp(
          home: ReorderableListView.builder(
            itemBuilder: (BuildContext context, int index) {
              return Container(
                key: ValueKey<int>(items[index]),
                height: 100,
                color: items[index].isOdd ? Colors.red : Colors.green,
                child: ReorderableDragStartListener(
                  index: index,
                  child: Row(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
                      Text('item ${items[index]}'),
                      const Icon(Icons.drag_handle),
                    ],
                  ),
                ),
              );
            },
            itemCount: items.length,
            onReorder: (int fromIndex, int toIndex) {},
            scrollController: scrollController,
            autoScrollerVelocityScalar: autoScrollerVelocityScalar,
          ),
        ),
      );

      expect(scrollController.offset, 0);

      final Finder item = find.text('item 0');
      final TestGesture drag = await tester.startGesture(tester.getCenter(item));

      // Drag just enough to touch the edge but not surpass it, so the
      // auto scroller is not yet triggered
      await drag.moveBy(const Offset(0, 500));
      await pumpFor(duration: const Duration(milliseconds: 200));

      expect(scrollController.offset, 0);

      // Now drag a little bit more so the auto scroller triggers
      await drag.moveBy(const Offset(0, 50));
      await pumpFor(
        duration: const Duration(milliseconds: 600),
        interval: Duration(milliseconds: (1000 / autoScrollerVelocityScalar).round()),
      );

      return scrollController.offset;
    }

    const double fastVelocityScalar = 20;
    final double offsetForFastScroller = await pumpListAndDrag(autoScrollerVelocityScalar: fastVelocityScalar);

    // Reset widget tree
    await tester.pumpWidget(const SizedBox());

    const double slowVelocityScalar = 5;
    final double offsetForSlowScroller = await pumpListAndDrag(autoScrollerVelocityScalar: slowVelocityScalar);

    expect(offsetForFastScroller / offsetForSlowScroller, fastVelocityScalar / slowVelocityScalar);
  });

}

Future<void> longPressDrag(WidgetTester tester, Offset start, Offset end) async {
  final TestGesture drag = await tester.startGesture(start);
  await tester.pump(kLongPressTimeout + kPressTimeout);
  await drag.moveTo(end);
  await tester.pump(kPressTimeout);
  await drag.up();
}

class _Stateful extends StatefulWidget {
  // Ignoring the preference for const constructors because we want to test with regular non-const instances.
  // ignore:prefer_const_constructors_in_immutables
  _Stateful({super.key});

  @override
  State<StatefulWidget> createState() => _StatefulState();
}

class _StatefulState extends State<_Stateful> {
  bool? checked = false;

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: 48.0,
      height: 48.0,
      child: Material(
        child: Checkbox(
          value: checked,
          onChanged: (bool? newValue) => checked = newValue,
        ),
      ),
    );
  }
}
