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

import 'states.dart';

class MaterialLocalizationsDelegate extends LocalizationsDelegate<MaterialLocalizations> {
  @override
  bool isSupported(Locale locale) => true;

  @override
  Future<MaterialLocalizations> load(Locale locale) => DefaultMaterialLocalizations.load(locale);

  @override
  bool shouldReload(MaterialLocalizationsDelegate old) => false;
}

class WidgetsLocalizationsDelegate extends LocalizationsDelegate<WidgetsLocalizations> {
  @override
  bool isSupported(Locale locale) => true;

  @override
  Future<WidgetsLocalizations> load(Locale locale) => DefaultWidgetsLocalizations.load(locale);

  @override
  bool shouldReload(WidgetsLocalizationsDelegate old) => false;
}

Widget textFieldBoilerplate({ required Widget child }) {
  return MaterialApp(
    home: Localizations(
      locale: const Locale('en', 'US'),
      delegates: <LocalizationsDelegate<dynamic>>[
        WidgetsLocalizationsDelegate(),
        MaterialLocalizationsDelegate(),
      ],
      child: Directionality(
        textDirection: TextDirection.ltr,
        child: MediaQuery(
          data: const MediaQueryData(size: Size(800.0, 600.0)),
          child: Center(
            child: Material(
              child: child,
            ),
          ),
        ),
      ),
    ),
  );
}

Widget primaryScrollControllerBoilerplate({ required Widget child, required ScrollController controller }) {
  return Directionality(
    textDirection: TextDirection.ltr,
    child: MediaQuery(
      data: const MediaQueryData(),
      child: PrimaryScrollController(
        controller: controller,
        child: child,
      ),
    ),
  );
}

void main() {
  testWidgets('ListView control test', (WidgetTester tester) async {
    final List<String> log = <String>[];

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: ListView(
          dragStartBehavior: DragStartBehavior.down,
          children: kStates.map<Widget>((String state) {
            return GestureDetector(
              onTap: () {
                log.add(state);
              },
              dragStartBehavior: DragStartBehavior.down,
              child: Container(
                height: 200.0,
                color: const Color(0xFF0000FF),
                child: Text(state),
              ),
            );
          }).toList(),
        ),
      ),
    );

    await tester.tap(find.text('Alabama'));
    expect(log, equals(<String>['Alabama']));
    log.clear();

    expect(find.text('Nevada'), findsNothing);

    await tester.drag(find.text('Alabama'), const Offset(0.0, -4000.0));
    await tester.pump();

    expect(find.text('Alabama'), findsNothing);
    expect(tester.getCenter(find.text('Massachusetts')), equals(const Offset(400.0, 100.0)));

    await tester.tap(find.text('Massachusetts'));
    expect(log, equals(<String>['Massachusetts']));
    log.clear();
  });

  testWidgets('ListView dismiss keyboard onDrag test', (WidgetTester tester) async {
    final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());

    await tester.pumpWidget(textFieldBoilerplate(
      child: ListView(
        padding: EdgeInsets.zero,
        keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
        children: focusNodes.map((FocusNode focusNode) {
          return Container(
            height: 50,
            color: Colors.green,
            child: TextField(
              focusNode: focusNode,
              style: const TextStyle(
                fontSize: 24,
                fontWeight: FontWeight.bold,
              ),
            ),
          );
        }).toList(),
      ),
    ));

    final Finder finder = find.byType(TextField).first;
    final TextField textField = tester.widget(finder);
    await tester.showKeyboard(finder);
    expect(textField.focusNode!.hasFocus, isTrue);

    await tester.drag(finder, const Offset(0.0, -40.0));
    await tester.pumpAndSettle();
    expect(textField.focusNode!.hasFocus, isFalse);
  });

  testWidgets('GridView.builder supports null items', (WidgetTester tester) async {
    await tester.pumpWidget(textFieldBoilerplate(
      child: GridView.builder(
        gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 42,
        ),
        itemCount: 42,
        itemBuilder: (BuildContext context, int index) {
          if (index == 5) {
            return null;
          }

          return const Text('item');
        },
      ),
    ));

    expect(find.text('item'), findsNWidgets(5));
  });

  testWidgets('ListView.builder supports null items', (WidgetTester tester) async {
    await tester.pumpWidget(textFieldBoilerplate(
      child: ListView.builder(
        itemCount: 42,
        itemBuilder: (BuildContext context, int index) {
          if (index == 5) {
            return null;
          }

          return const Text('item');
        },
      ),
    ));

    expect(find.text('item'), findsNWidgets(5));
  });

  testWidgets('PageView supports null items in itemBuilder', (WidgetTester tester) async {
    await tester.pumpWidget(textFieldBoilerplate(
      child: PageView.builder(
        itemCount: 5,
        controller: PageController(viewportFraction: 1/5),
        itemBuilder: (BuildContext context, int index) {
          if (index == 2) {
            return null;
          }

          return const Text('item');
        },
      ),
    ));

    expect(find.text('item'), findsNWidgets(2));
  });

  testWidgets('ListView.separated supports null items in itemBuilder', (WidgetTester tester) async {
    await tester.pumpWidget(textFieldBoilerplate(
      child: ListView.separated(
        itemCount: 42,
        separatorBuilder: (BuildContext context, int index) {
          return const Text('separator');
        },
        itemBuilder: (BuildContext context, int index) {
          if (index == 5) {
            return null;
          }

          return const Text('item');
        },
      ),
    ));

    expect(find.text('item'), findsNWidgets(5));
    expect(find.text('separator'), findsNWidgets(5));
  });

  testWidgets('ListView.builder dismiss keyboard onDrag test', (WidgetTester tester) async {
    final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());

    await tester.pumpWidget(textFieldBoilerplate(
      child: ListView.builder(
        padding: EdgeInsets.zero,
        keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
        itemCount: focusNodes.length,
        itemBuilder: (BuildContext context,int index) {
          return Container(
            height: 50,
            color: Colors.green,
            child: TextField(
              focusNode: focusNodes[index],
              style: const TextStyle(
                fontSize: 24,
                fontWeight: FontWeight.bold,
              ),
            ),
          );
        },
      ),
    ));

    final Finder finder = find.byType(TextField).first;
    final TextField textField = tester.widget(finder);
    await tester.showKeyboard(finder);
    expect(textField.focusNode!.hasFocus, isTrue);

    await tester.drag(finder, const Offset(0.0, -40.0));
    await tester.pumpAndSettle();
    expect(textField.focusNode!.hasFocus, isFalse);
  });

  testWidgets('ListView.custom dismiss keyboard onDrag test', (WidgetTester tester) async {
    final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());

    await tester.pumpWidget(textFieldBoilerplate(
      child: ListView.custom(
        padding: EdgeInsets.zero,
        keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
        childrenDelegate: SliverChildBuilderDelegate(
          (BuildContext context,int index) {
            return Container(
              height: 50,
              color: Colors.green,
              child: TextField(
                focusNode: focusNodes[index],
                style: const TextStyle(
                  fontSize: 24,
                  fontWeight: FontWeight.bold,
                ),
              ),
            );
          },
          childCount: focusNodes.length,
        ),
      ),
    ));

    final Finder finder = find.byType(TextField).first;
    final TextField textField = tester.widget(finder);
    await tester.showKeyboard(finder);
    expect(textField.focusNode!.hasFocus, isTrue);

    await tester.drag(finder, const Offset(0.0, -40.0));
    await tester.pumpAndSettle();
    expect(textField.focusNode!.hasFocus, isFalse);
  });

  testWidgets('ListView.separated dismiss keyboard onDrag test', (WidgetTester tester) async {
    final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());

    await tester.pumpWidget(textFieldBoilerplate(
      child: ListView.separated(
        padding: EdgeInsets.zero,
        keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
        itemCount: focusNodes.length,
        separatorBuilder: (BuildContext context, int index) => const Divider(),
        itemBuilder: (BuildContext context,int index) {
          return Container(
            height: 50,
            color: Colors.green,
            child: TextField(
              focusNode: focusNodes[index],
              style: const TextStyle(
                fontSize: 24,
                fontWeight: FontWeight.bold,
              ),
            ),
          );
        },
      ),
    ));

    final Finder finder = find.byType(TextField).first;
    final TextField textField = tester.widget(finder);
    await tester.showKeyboard(finder);
    expect(textField.focusNode!.hasFocus, isTrue);

    await tester.drag(finder, const Offset(0.0, -40.0));
    await tester.pumpAndSettle();
    expect(textField.focusNode!.hasFocus, isFalse);
  });

  testWidgets('GridView dismiss keyboard onDrag test', (WidgetTester tester) async {
    final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());

    await tester.pumpWidget(textFieldBoilerplate(
      child: GridView(
        padding: EdgeInsets.zero,
        gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount:2),
        keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
        children: focusNodes.map((FocusNode focusNode) {
          return Container(
            height: 50,
            color: Colors.green,
            child: TextField(
              focusNode: focusNode,
              style: const TextStyle(
                fontSize: 24,
                fontWeight: FontWeight.bold,
              ),
            ),
          );
        }).toList(),
      ),
    ));

    final Finder finder = find.byType(TextField).first;
    final TextField textField = tester.widget(finder);
    await tester.showKeyboard(finder);
    expect(textField.focusNode!.hasFocus, isTrue);

    await tester.drag(finder, const Offset(0.0, -40.0));
    await tester.pumpAndSettle();
    expect(textField.focusNode!.hasFocus, isFalse);
  });

  testWidgets('GridView.builder dismiss keyboard onDrag test', (WidgetTester tester) async {
    final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());

    await tester.pumpWidget(textFieldBoilerplate(
      child: GridView.builder(
        padding: EdgeInsets.zero,
        gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount:2),
        keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
        itemCount: focusNodes.length,
        itemBuilder: (BuildContext context, int index) {
          return Container(
            height: 50,
            color: Colors.green,
            child: TextField(
              focusNode: focusNodes[index],
              style: const TextStyle(
                fontSize: 24,
                fontWeight: FontWeight.bold,
              ),
            ),
          );
        },
      ),
    ));

    final Finder finder = find.byType(TextField).first;
    final TextField textField = tester.widget(finder);
    await tester.showKeyboard(finder);
    expect(textField.focusNode!.hasFocus, isTrue);

    await tester.drag(finder, const Offset(0.0, -40.0));
    await tester.pumpAndSettle();
    expect(textField.focusNode!.hasFocus, isFalse);
  });

  testWidgets('GridView.count dismiss keyboard onDrag test', (WidgetTester tester) async {
    final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());

    await tester.pumpWidget(textFieldBoilerplate(
      child: GridView.count(
        padding: EdgeInsets.zero,
        crossAxisCount: 2,
        keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
        children: focusNodes.map((FocusNode focusNode) {
          return Container(
            height: 50,
            color: Colors.green,
            child: TextField(
              focusNode: focusNode,
              style: const TextStyle(
                fontSize: 24,
                fontWeight: FontWeight.bold,
              ),
            ),
          );
        }).toList(),
      ),
    ));

    final Finder finder = find.byType(TextField).first;
    final TextField textField = tester.widget(finder);
    await tester.showKeyboard(finder);
    expect(textField.focusNode!.hasFocus, isTrue);

    await tester.drag(finder, const Offset(0.0, -40.0));
    await tester.pumpAndSettle();
    expect(textField.focusNode!.hasFocus, isFalse);
  });

  testWidgets('GridView.extent dismiss keyboard onDrag test', (WidgetTester tester) async {
    final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());

    await tester.pumpWidget(textFieldBoilerplate(
      child: GridView.extent(
        padding: EdgeInsets.zero,
        maxCrossAxisExtent: 300,
        keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
        children: focusNodes.map((FocusNode focusNode) {
          return Container(
            height: 50,
            color: Colors.green,
            child: TextField(
              focusNode: focusNode,
              style: const TextStyle(
                fontSize: 24,
                fontWeight: FontWeight.bold,
              ),
            ),
          );
        }).toList(),
      ),
    ));

    final Finder finder = find.byType(TextField).first;
    final TextField textField = tester.widget(finder);
    await tester.showKeyboard(finder);
    expect(textField.focusNode!.hasFocus, isTrue);

    await tester.drag(finder, const Offset(0.0, -40.0));
    await tester.pumpAndSettle();
    expect(textField.focusNode!.hasFocus, isFalse);
  });

  testWidgets('GridView.custom dismiss keyboard onDrag test', (WidgetTester tester) async {
    final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());

    await tester.pumpWidget(textFieldBoilerplate(
      child: GridView.custom(
        padding: EdgeInsets.zero,
        gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount:2),
        keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
        childrenDelegate: SliverChildBuilderDelegate(
          (BuildContext context,int index) {
            return Container(
              height: 50,
              color: Colors.green,
              child: TextField(
                focusNode: focusNodes[index],
                style: const TextStyle(
                  fontSize: 24,
                  fontWeight: FontWeight.bold,
                ),
              ),
            );
          },
          childCount: focusNodes.length,
        ),
      ),
    ));

    final Finder finder = find.byType(TextField).first;
    final TextField textField = tester.widget(finder);
    await tester.showKeyboard(finder);
    expect(textField.focusNode!.hasFocus, isTrue);

    await tester.drag(finder, const Offset(0.0, -40.0));
    await tester.pumpAndSettle();
    expect(textField.focusNode!.hasFocus, isFalse);
  });

  testWidgets('ListView dismiss keyboard manual test', (WidgetTester tester) async {
    final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());

    await tester.pumpWidget(textFieldBoilerplate(
      child: ListView(
        padding: EdgeInsets.zero,
        children: focusNodes.map((FocusNode focusNode) {
          return Container(
            height: 50,
            color: Colors.green,
            child: TextField(
              focusNode: focusNode,
              style: const TextStyle(
                fontSize: 24,
                fontWeight: FontWeight.bold,
              ),
            ),
          );
        }).toList(),
      ),
    ));

    final Finder finder = find.byType(TextField).first;
    final TextField textField = tester.widget(finder);
    await tester.showKeyboard(finder);
    expect(textField.focusNode!.hasFocus, isTrue);

    await tester.drag(finder, const Offset(0.0, -40.0));
    await tester.pumpAndSettle();
    expect(textField.focusNode!.hasFocus, isTrue);
  });

  testWidgets('ListView.builder dismiss keyboard manual test', (WidgetTester tester) async {
    final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());

    await tester.pumpWidget(textFieldBoilerplate(
      child: ListView.builder(
        padding: EdgeInsets.zero,
        itemCount: focusNodes.length,
        itemBuilder: (BuildContext context,int index) {
          return Container(
            height: 50,
            color: Colors.green,
            child: TextField(
              focusNode: focusNodes[index],
              style: const TextStyle(
                fontSize: 24,
                fontWeight: FontWeight.bold,
              ),
            ),
          );
        },
      ),
    ));

    final Finder finder = find.byType(TextField).first;
    final TextField textField = tester.widget(finder);
    await tester.showKeyboard(finder);
    expect(textField.focusNode!.hasFocus, isTrue);

    await tester.drag(finder, const Offset(0.0, -40.0));
    await tester.pumpAndSettle();
    expect(textField.focusNode!.hasFocus, isTrue);
  });

  testWidgets('ListView.custom dismiss keyboard manual test', (WidgetTester tester) async {
    final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());

    await tester.pumpWidget(textFieldBoilerplate(
      child: ListView.custom(
        padding: EdgeInsets.zero,
        childrenDelegate: SliverChildBuilderDelegate(
          (BuildContext context,int index) {
            return Container(
              height: 50,
              color: Colors.green,
              child: TextField(
                focusNode: focusNodes[index],
                style: const TextStyle(
                  fontSize: 24,
                  fontWeight: FontWeight.bold,
                ),
              ),
            );
          },
          childCount: focusNodes.length,
        ),
      ),
    ));

    final Finder finder = find.byType(TextField).first;
    final TextField textField = tester.widget(finder);
    await tester.showKeyboard(finder);
    expect(textField.focusNode!.hasFocus, isTrue);

    await tester.drag(finder, const Offset(0.0, -40.0));
    await tester.pumpAndSettle();
    expect(textField.focusNode!.hasFocus, isTrue);
  });

  testWidgets('ListView.separated dismiss keyboard manual test', (WidgetTester tester) async {
    final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());

    await tester.pumpWidget(textFieldBoilerplate(
      child: ListView.separated(
        padding: EdgeInsets.zero,
        itemCount: focusNodes.length,
        separatorBuilder: (BuildContext context, int index) => const Divider(),
        itemBuilder: (BuildContext context,int index) {
          return Container(
            height: 50,
            color: Colors.green,
            child: TextField(
              focusNode: focusNodes[index],
              style: const TextStyle(
                fontSize: 24,
                fontWeight: FontWeight.bold,
              ),
            ),
          );
        },
      ),
    ));

    final Finder finder = find.byType(TextField).first;
    final TextField textField = tester.widget(finder);
    await tester.showKeyboard(finder);
    expect(textField.focusNode!.hasFocus, isTrue);

    await tester.drag(finder, const Offset(0.0, -40.0));
    await tester.pumpAndSettle();
    expect(textField.focusNode!.hasFocus, isTrue);
  });

  testWidgets('GridView dismiss keyboard manual test', (WidgetTester tester) async {
    final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());

    await tester.pumpWidget(textFieldBoilerplate(
      child: GridView(
        padding: EdgeInsets.zero,
        gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount:2),
        children: focusNodes.map((FocusNode focusNode) {
          return Container(
            height: 50,
            color: Colors.green,
            child: TextField(
              focusNode: focusNode,
              style: const TextStyle(
                fontSize: 24,
                fontWeight: FontWeight.bold,
              ),
            ),
          );
        }).toList(),
      ),
    ));

    final Finder finder = find.byType(TextField).first;
    final TextField textField = tester.widget(finder);
    await tester.showKeyboard(finder);
    expect(textField.focusNode!.hasFocus, isTrue);

    await tester.drag(finder, const Offset(0.0, -40.0));
    await tester.pumpAndSettle();
    expect(textField.focusNode!.hasFocus, isTrue);
  });

  testWidgets('GridView.builder dismiss keyboard manual test', (WidgetTester tester) async {
    final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());

    await tester.pumpWidget(textFieldBoilerplate(
      child: GridView.builder(
        padding: EdgeInsets.zero,
        gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount:2),
        itemCount: focusNodes.length,
        itemBuilder: (BuildContext context, int index) {
          return Container(
            height: 50,
            color: Colors.green,
            child: TextField(
              focusNode: focusNodes[index],
              style: const TextStyle(
                fontSize: 24,
                fontWeight: FontWeight.bold,
              ),
            ),
          );
        },
      ),
    ));

    final Finder finder = find.byType(TextField).first;
    final TextField textField = tester.widget(finder);
    await tester.showKeyboard(finder);
    expect(textField.focusNode!.hasFocus, isTrue);

    await tester.drag(finder, const Offset(0.0, -40.0));
    await tester.pumpAndSettle();
    expect(textField.focusNode!.hasFocus, isTrue);
  });

  testWidgets('GridView.count dismiss keyboard manual test', (WidgetTester tester) async {
    final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());

    await tester.pumpWidget(textFieldBoilerplate(
      child: GridView.count(
        padding: EdgeInsets.zero,
        crossAxisCount: 2,
        children: focusNodes.map((FocusNode focusNode) {
          return Container(
            height: 50,
            color: Colors.green,
            child: TextField(
              focusNode: focusNode,
              style: const TextStyle(
                fontSize: 24,
                fontWeight: FontWeight.bold,
              ),
            ),
          );
        }).toList(),
      ),
    ));

    final Finder finder = find.byType(TextField).first;
    final TextField textField = tester.widget(finder);
    await tester.showKeyboard(finder);
    expect(textField.focusNode!.hasFocus, isTrue);

    await tester.drag(finder, const Offset(0.0, -40.0));
    await tester.pumpAndSettle();
    expect(textField.focusNode!.hasFocus, isTrue);
  });

  testWidgets('GridView.extent dismiss keyboard manual test', (WidgetTester tester) async {
    final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());

    await tester.pumpWidget(textFieldBoilerplate(
      child: GridView.extent(
        padding: EdgeInsets.zero,
        maxCrossAxisExtent: 300,
        children: focusNodes.map((FocusNode focusNode) {
          return Container(
            height: 50,
            color: Colors.green,
            child: TextField(
              focusNode: focusNode,
              style: const TextStyle(
                fontSize: 24,
                fontWeight: FontWeight.bold,
              ),
            ),
          );
        }).toList(),
      ),
    ));

    final Finder finder = find.byType(TextField).first;
    final TextField textField = tester.widget(finder);
    await tester.showKeyboard(finder);
    expect(textField.focusNode!.hasFocus, isTrue);

    await tester.drag(finder, const Offset(0.0, -40.0));
    await tester.pumpAndSettle();
    expect(textField.focusNode!.hasFocus, isTrue);
  });

  testWidgets('GridView.custom dismiss keyboard manual test', (WidgetTester tester) async {
    final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());

    await tester.pumpWidget(textFieldBoilerplate(
      child: GridView.custom(
        padding: EdgeInsets.zero,
        gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount:2),
        childrenDelegate: SliverChildBuilderDelegate(
          (BuildContext context,int index) {
            return Container(
              height: 50,
              color: Colors.green,
              child: TextField(
                focusNode: focusNodes[index],
                style: const TextStyle(
                  fontSize: 24,
                  fontWeight: FontWeight.bold,
                ),
              ),
            );
          },
          childCount: focusNodes.length,
        ),
      ),
    ));

    final Finder finder = find.byType(TextField).first;
    final TextField textField = tester.widget(finder);
    await tester.showKeyboard(finder);
    expect(textField.focusNode!.hasFocus, isTrue);

    await tester.drag(finder, const Offset(0.0, -40.0));
    await tester.pumpAndSettle();
    expect(textField.focusNode!.hasFocus, isTrue);
  });

  testWidgets('ListView restart ballistic activity out of range', (WidgetTester tester) async {
    Widget buildListView(int n) {
      return Directionality(
        textDirection: TextDirection.ltr,
        child: ListView(
          dragStartBehavior: DragStartBehavior.down,
          children: kStates.take(n).map<Widget>((String state) {
            return Container(
              height: 200.0,
              color: const Color(0xFF0000FF),
              child: Text(state),
            );
          }).toList(),
        ),
      );
    }

    await tester.pumpWidget(buildListView(30));
    await tester.fling(find.byType(ListView), const Offset(0.0, -4000.0), 4000.0);
    await tester.pumpWidget(buildListView(15));
    await tester.pump(const Duration(milliseconds: 10));
    await tester.pump(const Duration(milliseconds: 10));
    await tester.pump(const Duration(milliseconds: 10));
    await tester.pump(const Duration(milliseconds: 10));
    await tester.pumpAndSettle();

    final Viewport viewport = tester.widget(find.byType(Viewport));
    expect(viewport.offset.pixels, equals(2400.0));
  });

  testWidgets('CustomScrollView control test', (WidgetTester tester) async {
    final List<String> log = <String>[];

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: CustomScrollView(
          dragStartBehavior: DragStartBehavior.down,
          slivers: <Widget>[
            SliverList(
              delegate: SliverChildListDelegate(
                kStates.map<Widget>((String state) {
                  return GestureDetector(
                    dragStartBehavior: DragStartBehavior.down,
                    onTap: () {
                      log.add(state);
                    },
                    child: Container(
                      height: 200.0,
                      color: const Color(0xFF0000FF),
                      child: Text(state),
                    ),
                  );
                }).toList(),
              ),
            ),
          ],
        ),
      ),
    );

    await tester.tap(find.text('Alabama'));
    expect(log, equals(<String>['Alabama']));
    log.clear();

    expect(find.text('Nevada'), findsNothing);

    await tester.drag(find.text('Alabama'), const Offset(0.0, -4000.0));
    await tester.pump();

    expect(find.text('Alabama'), findsNothing);
    expect(tester.getCenter(find.text('Massachusetts')), equals(const Offset(400.0, 100.0)));

    await tester.tap(find.text('Massachusetts'));
    expect(log, equals(<String>['Massachusetts']));
    log.clear();
  });

  testWidgets('CustomScrollView dismiss keyboard onDrag test', (WidgetTester tester) async {
    final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());

    await tester.pumpWidget(textFieldBoilerplate(
      child: CustomScrollView(
        dragStartBehavior: DragStartBehavior.down,
        keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
        slivers: <Widget>[
          SliverList(
            delegate: SliverChildListDelegate(
              focusNodes.map((FocusNode focusNode) {
                return Container(
                  height: 50,
                  color: Colors.green,
                  child: TextField(
                    focusNode: focusNode,
                    style: const TextStyle(
                      fontSize: 24,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                );
              }).toList(),
            ),
          ),
        ],
      ),
    ));

    final Finder finder = find.byType(TextField).first;
    final TextField textField = tester.widget(finder);
    await tester.showKeyboard(finder);
    expect(textField.focusNode!.hasFocus, isTrue);

    await tester.drag(finder, const Offset(0.0, -40.0));
    await tester.pumpAndSettle();
    expect(textField.focusNode!.hasFocus, isFalse);
  });

  testWidgets('Can jumpTo during drag', (WidgetTester tester) async {
    final List<Type> log = <Type>[];
    final ScrollController controller = ScrollController();

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: NotificationListener<ScrollNotification>(
          onNotification: (ScrollNotification notification) {
            log.add(notification.runtimeType);
            return false;
          },
          child: ListView(
            controller: controller,
            children: kStates.map<Widget>((String state) {
              return SizedBox(
                height: 200.0,
                child: Text(state),
              );
            }).toList(),
          ),
        ),
      ),
    );

    expect(log, isEmpty);

    final TestGesture gesture = await tester.startGesture(const Offset(100.0, 100.0));
    await gesture.moveBy(const Offset(0.0, -100.0));

    expect(log, equals(<Type>[
      ScrollStartNotification,
      UserScrollNotification,
      ScrollUpdateNotification,
    ]));
    log.clear();

    await tester.pump();

    controller.jumpTo(550.0);

    expect(controller.offset, equals(550.0));
    expect(log, equals(<Type>[
      ScrollEndNotification,
      UserScrollNotification,
      ScrollStartNotification,
      ScrollUpdateNotification,
      ScrollEndNotification,
    ]));
    log.clear();

    await tester.pump();
    await gesture.moveBy(const Offset(0.0, -100.0));

    expect(controller.offset, equals(550.0));
    expect(log, isEmpty);
  });

  test('PrimaryScrollController.automaticallyInheritOnPlatforms defaults to all mobile platforms', (){
     final PrimaryScrollController primaryScrollController = PrimaryScrollController(
        controller: ScrollController(),
       child: const SizedBox(),
     );
     expect(
       primaryScrollController.automaticallyInheritForPlatforms,
       TargetPlatformVariant.mobile().values,
     );
  });

  testWidgets('Vertical CustomScrollViews are not primary by default', (WidgetTester tester) async {
    const CustomScrollView view = CustomScrollView();
    expect(view.primary, isNull);
  });

  testWidgets('Vertical CustomScrollViews use PrimaryScrollController by default on mobile', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    await tester.pumpWidget(primaryScrollControllerBoilerplate(
      child: const CustomScrollView(),
      controller: controller,
    ));
    expect(controller.hasClients, isTrue);
  }, variant: TargetPlatformVariant.mobile());

  testWidgets("Vertical CustomScrollViews don't use PrimaryScrollController by default on desktop", (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    await tester.pumpWidget(primaryScrollControllerBoilerplate(
        child: const CustomScrollView(),
        controller: controller,
    ));
    expect(controller.hasClients, isFalse);
  }, variant: TargetPlatformVariant.desktop());

  testWidgets('Vertical ListViews are not primary by default', (WidgetTester tester) async {
    final ListView view = ListView();
    expect(view.primary, isNull);
  });

  testWidgets('Vertical ListViews use PrimaryScrollController by default on mobile', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    await tester.pumpWidget(primaryScrollControllerBoilerplate(
      child: ListView(),
      controller: controller,
    ));
    expect(controller.hasClients, isTrue);
  }, variant: TargetPlatformVariant.mobile());

  testWidgets("Vertical ListViews don't use PrimaryScrollController by default on desktop", (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    await tester.pumpWidget(primaryScrollControllerBoilerplate(
      child: ListView(),
      controller: controller,
    ));
    expect(controller.hasClients, isFalse);
  }, variant: TargetPlatformVariant.desktop());

  testWidgets('Vertical GridViews are not primary by default', (WidgetTester tester) async {
    final GridView view = GridView.count(crossAxisCount: 1);
    expect(view.primary, isNull);
  });

  testWidgets('Vertical GridViews use PrimaryScrollController by default on mobile', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    await tester.pumpWidget(primaryScrollControllerBoilerplate(
      child: GridView.count(crossAxisCount: 1),
      controller: controller,
    ));
    expect(controller.hasClients, isTrue);
  }, variant: TargetPlatformVariant.mobile());

  testWidgets("Vertical GridViews don't use PrimaryScrollController by default on desktop", (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    await tester.pumpWidget(primaryScrollControllerBoilerplate(
      child: GridView.count(crossAxisCount: 1),
      controller: controller,
    ));
    expect(controller.hasClients, isFalse);
  }, variant: TargetPlatformVariant.desktop());

  testWidgets('Horizontal CustomScrollViews are non-primary by default', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    await tester.pumpWidget(primaryScrollControllerBoilerplate(
      child: CustomScrollView(
        scrollDirection: Axis.horizontal,
        controller: ScrollController(),
      ),
      controller: controller,
    ));
    expect(controller.hasClients, isFalse);
  });

  testWidgets('Horizontal ListViews are non-primary by default', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    await tester.pumpWidget(primaryScrollControllerBoilerplate(
      child: ListView(
        scrollDirection: Axis.horizontal,
        controller: ScrollController(),
      ),
      controller: controller,
    ));
    expect(controller.hasClients, isFalse);
  });

  testWidgets('Horizontal GridViews are non-primary by default', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    await tester.pumpWidget(primaryScrollControllerBoilerplate(
      child: GridView.count(
        scrollDirection: Axis.horizontal,
        controller: ScrollController(),
        crossAxisCount: 1,
      ),
      controller: controller,
    ));
    expect(controller.hasClients, isFalse);
  });

  testWidgets('CustomScrollViews with controllers are non-primary by default', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    await tester.pumpWidget(primaryScrollControllerBoilerplate(
      child: CustomScrollView(
        controller: ScrollController(),
      ),
      controller: controller,
    ));
    expect(controller.hasClients, isFalse);
  });

  testWidgets('ListViews with controllers are non-primary by default', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    await tester.pumpWidget(primaryScrollControllerBoilerplate(
      child: ListView(
        controller: ScrollController(),
      ),
      controller: controller,
    ));
    expect(controller.hasClients, isFalse);
  });

  testWidgets('GridViews with controllers are non-primary by default', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    await tester.pumpWidget(primaryScrollControllerBoilerplate(
      child: GridView.count(
        controller: ScrollController(),
        crossAxisCount: 1,
      ),
      controller: controller,
    ));
    expect(controller.hasClients, isFalse);
  });

  testWidgets('CustomScrollView sets PrimaryScrollController when primary', (WidgetTester tester) async {
    final ScrollController primaryScrollController = ScrollController();
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: PrimaryScrollController(
          controller: primaryScrollController,
          child: const CustomScrollView(primary: true),
        ),
      ),
    );
    final Scrollable scrollable = tester.widget(find.byType(Scrollable));
    expect(scrollable.controller, primaryScrollController);
  });

  testWidgets('ListView sets PrimaryScrollController when primary', (WidgetTester tester) async {
    final ScrollController primaryScrollController = ScrollController();
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: PrimaryScrollController(
          controller: primaryScrollController,
          child: ListView(primary: true),
        ),
      ),
    );
    final Scrollable scrollable = tester.widget(find.byType(Scrollable));
    expect(scrollable.controller, primaryScrollController);
  });

  testWidgets('GridView sets PrimaryScrollController when primary', (WidgetTester tester) async {
    final ScrollController primaryScrollController = ScrollController();
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: PrimaryScrollController(
          controller: primaryScrollController,
          child: GridView.count(primary: true, crossAxisCount: 1),
        ),
      ),
    );
    final Scrollable scrollable = tester.widget(find.byType(Scrollable));
    expect(scrollable.controller, primaryScrollController);
  });

  testWidgets('Nested scrollables have a null PrimaryScrollController', (WidgetTester tester) async {
    const Key innerKey = Key('inner');
    final ScrollController primaryScrollController = ScrollController();
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: PrimaryScrollController(
          controller: primaryScrollController,
          child: ListView(
            primary: true,
            children: <Widget>[
              Container(
                constraints: const BoxConstraints(maxHeight: 200.0),
                child: ListView(key: innerKey, primary: true),
              ),
            ],
          ),
        ),
      ),
    );

    final Scrollable innerScrollable = tester.widget(
      find.descendant(
        of: find.byKey(innerKey),
        matching: find.byType(Scrollable),
      ),
    );
    expect(innerScrollable.controller, isNull);
  });

  testWidgets('Primary ListViews are always scrollable', (WidgetTester tester) async {
    final ListView view = ListView(primary: true);
    expect(view.physics, isA<AlwaysScrollableScrollPhysics>());
  });

  testWidgets('Non-primary ListViews are not always scrollable', (WidgetTester tester) async {
    final ListView view = ListView(primary: false);
    expect(view.physics, isNot(isA<AlwaysScrollableScrollPhysics>()));
  });

  testWidgets('Defaulting-to-primary ListViews are always scrollable', (WidgetTester tester) async {
    final ListView view = ListView();
    expect(view.physics, isA<AlwaysScrollableScrollPhysics>());
  });

  testWidgets('Defaulting-to-not-primary ListViews are not always scrollable', (WidgetTester tester) async {
    final ListView view = ListView(scrollDirection: Axis.horizontal);
    expect(view.physics, isNot(isA<AlwaysScrollableScrollPhysics>()));
  });

  testWidgets('primary:true leads to scrolling', (WidgetTester tester) async {
    bool scrolled = false;
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: NotificationListener<OverscrollNotification>(
          onNotification: (OverscrollNotification message) {
            scrolled = true;
            return false;
          },
          child: ListView(
            primary: true,
          ),
        ),
      ),
    );
    await tester.dragFrom(const Offset(100.0, 100.0), const Offset(0.0, 100.0));
    expect(scrolled, isTrue);
  });

  testWidgets('primary:false leads to no scrolling', (WidgetTester tester) async {
    bool scrolled = false;
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: NotificationListener<OverscrollNotification>(
          onNotification: (OverscrollNotification message) {
            scrolled = true;
            return false;
          },
          child: ListView(
            primary: false,
          ),
        ),
      ),
    );
    await tester.dragFrom(const Offset(100.0, 100.0), const Offset(0.0, 100.0));
    expect(scrolled, isFalse);
  });

  testWidgets('physics:AlwaysScrollableScrollPhysics actually overrides primary:false default behavior', (WidgetTester tester) async {
    bool scrolled = false;
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: NotificationListener<OverscrollNotification>(
          onNotification: (OverscrollNotification message) {
            scrolled = true;
            return false;
          },
          child: ListView(
            primary: false,
            physics: const AlwaysScrollableScrollPhysics(),
          ),
        ),
      ),
    );
    await tester.dragFrom(const Offset(100.0, 100.0), const Offset(0.0, 100.0));
    expect(scrolled, isTrue);
  });

  testWidgets('physics:ScrollPhysics actually overrides primary:true default behavior', (WidgetTester tester) async {
    bool scrolled = false;
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: NotificationListener<OverscrollNotification>(
          onNotification: (OverscrollNotification message) {
            scrolled = true;
            return false;
          },
          child: ListView(
            primary: true,
            physics: const ScrollPhysics(),
          ),
        ),
      ),
    );
    await tester.dragFrom(const Offset(100.0, 100.0), const Offset(0.0, 100.0));
    expect(scrolled, isFalse);
  });

  testWidgets('separatorBuilder must return something', (WidgetTester tester) async {
    const List<String> listOfValues = <String>['ALPHA', 'BETA', 'GAMMA', 'DELTA'];

    Widget buildFrame(Widget firstSeparator) {
      return MaterialApp(
        home: Material(
          child: ListView.separated(
            itemBuilder: (BuildContext context, int index) {
              return Text(listOfValues[index]);
            },
            separatorBuilder: (BuildContext context, int index) {
              if (index == 0) {
                return firstSeparator;
              } else {
                return const Divider();
              }
            },
            itemCount: listOfValues.length,
          ),
        ),
      );
    }

    // A separatorBuilder that always returns a Divider is fine
    await tester.pumpWidget(buildFrame(const Divider()));
    expect(tester.takeException(), isNull);
  });

  testWidgets('when itemBuilder throws, creates Error Widget', (WidgetTester tester) async {
    const List<String> listOfValues = <String>['ALPHA', 'BETA', 'GAMMA', 'DELTA'];

    Widget buildFrame(bool throwOnFirstItem) {
      return MaterialApp(
        home: Material(
          child: ListView.builder(
            itemBuilder: (BuildContext context, int index) {
              if (index == 0 && throwOnFirstItem) {
                throw Exception('itemBuilder fail');
              }
              return Text(listOfValues[index]);
            },
            itemCount: listOfValues.length,
          ),
        ),
      );
    }

    // When itemBuilder doesn't throw, no ErrorWidget
    await tester.pumpWidget(buildFrame(false));
    expect(tester.takeException(), isNull);
    final Finder finder = find.byType(ErrorWidget);
    expect(find.byType(ErrorWidget), findsNothing);

    // When it does throw, one error widget is rendered in the item's place
    await tester.pumpWidget(buildFrame(true));
    expect(tester.takeException(), isA<Exception>());
    expect(finder, findsOneWidget);
  });

  testWidgets('when separatorBuilder throws, creates ErrorWidget', (WidgetTester tester) async {
    const List<String> listOfValues = <String>['ALPHA', 'BETA', 'GAMMA', 'DELTA'];
    const Key key = Key('list');

    Widget buildFrame(bool throwOnFirstSeparator) {
      return MaterialApp(
        home: Material(
          child: ListView.separated(
            key: key,
            itemBuilder: (BuildContext context, int index) {
              return Text(listOfValues[index]);
            },
            separatorBuilder: (BuildContext context, int index) {
              if (index == 0 && throwOnFirstSeparator) {
                throw Exception('separatorBuilder fail');
              }
              return const Divider();
            },
            itemCount: listOfValues.length,
          ),
        ),
      );
    }

    // When separatorBuilder doesn't throw, no ErrorWidget
    await tester.pumpWidget(buildFrame(false));
    expect(tester.takeException(), isNull);
    final Finder finder = find.byType(ErrorWidget);
    expect(find.byType(ErrorWidget), findsNothing);

    // When it does throw, one error widget is rendered in the separator's place
    await tester.pumpWidget(buildFrame(true));
    expect(tester.takeException(), isA<Exception>());
    expect(finder, findsOneWidget);
  });

   testWidgets('ListView asserts on both non-null itemExtent and prototypeItem', (WidgetTester tester) async {
    expect(() => ListView(
      itemExtent: 100,
      prototypeItem: const SizedBox(),
    ), throwsAssertionError);
  });

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

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

  testWidgets('ListView.builder asserts on nonsensical childCount/semanticChildCount', (WidgetTester tester) async {
    expect(() => ListView.builder(
      itemBuilder: (BuildContext context, int index) {
        return const SizedBox();
      },
      itemCount: 1,
      semanticChildCount: 4,
    ), throwsAssertionError);
  });

  testWidgets('ListView.builder asserts on both non-null itemExtent and prototypeItem', (WidgetTester tester) async {
    expect(() => ListView.builder(
      itemBuilder: (BuildContext context, int index) {
        return const SizedBox();
      },
      itemExtent: 100,
      prototypeItem: const SizedBox(),
    ), throwsAssertionError);
  });

  testWidgets('ListView.custom asserts on both non-null itemExtent and prototypeItem', (WidgetTester tester) async {
    expect(() => ListView.custom(
      childrenDelegate: SliverChildBuilderDelegate(
        (BuildContext context, int index) {
          return const SizedBox();
        },
      ),
      itemExtent: 100,
      prototypeItem: const SizedBox(),
    ), throwsAssertionError);
  });

  testWidgets('PrimaryScrollController provides fallback ScrollActions', (WidgetTester tester)  async {
    await tester.pumpWidget(
      MaterialApp(
        home: CustomScrollView(
          primary: true,
          slivers: List<Widget>.generate(
            20,
            (int index) {
              return SliverToBoxAdapter(
                child: Focus(
                  autofocus: index == 0,
                  child: SizedBox(key: ValueKey<String>('Box $index'), height: 50.0),
                ),
              );
            },
          ),
        ),
      ),
    );
    final ScrollController controller = PrimaryScrollController.of(
      tester.element(find.byType(CustomScrollView)),
    )!;
    await tester.pumpAndSettle();
    expect(controller.position.pixels, equals(0.0));
    expect(
      tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)),
      equals(const Rect.fromLTRB(0.0, 0.0, 800.0, 50.0)),
    );
    await tester.sendKeyEvent(LogicalKeyboardKey.pageDown);
    await tester.pumpAndSettle();
    expect(controller.position.pixels, equals(400.0));
    expect(
      tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)),
      equals(const Rect.fromLTRB(0.0, -400.0, 800.0, -350.0)),
    );
    await tester.sendKeyEvent(LogicalKeyboardKey.pageUp);
    await tester.pumpAndSettle();
    expect(controller.position.pixels, equals(0.0));
    expect(
      tester.getRect(find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false)),
      equals(const Rect.fromLTRB(0.0, 0.0, 800.0, 50.0)),
    );
  });

  testWidgets('Fallback ScrollActions handle too many positions with error message', (WidgetTester tester)  async {
    Widget getScrollView() {
      return SizedBox(
        width: 400.0,
        child: CustomScrollView(
          primary: true,
          slivers: List<Widget>.generate(
            20,
            (int index) {
              return SliverToBoxAdapter(
                child: Focus(
                  child: SizedBox(key: ValueKey<String>('Box $index'), height: 50.0),
                ),
              );
            },
          ),
        ),
      );
    }

    await tester.pumpWidget(
      MaterialApp(
        home: Row(
          children: <Widget>[
            getScrollView(),
            getScrollView(),
          ],
        ),
      ),
    );
    await tester.pumpAndSettle();
    expect(
      tester.getRect(
        find.byKey(const ValueKey<String>('Box 0'), skipOffstage: false).first
      ),
      equals(const Rect.fromLTRB(0.0, 0.0, 400.0, 50.0)),
    );
    await tester.sendKeyEvent(LogicalKeyboardKey.pageDown);
    final AssertionError exception = tester.takeException() as AssertionError;
    expect(exception, isAssertionError);
    expect(
      exception.message,
      contains(
        'A ScrollAction was invoked with the PrimaryScrollController, but '
        'more than one ScrollPosition is attached.'
      ),
    );
  });

  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 ListView.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,
                );
              },
            ),
          ),
        )
    );

    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 ListView.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'),
                  ),
                );
              },
            ),
          ),
        )
    );

    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);
  });
}
