// 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 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';

import 'editable_text_tester.dart';
import 'list_tile_tester.dart';
import 'multi_view_testing.dart';
import 'widgets_app_tester.dart';

// Matches the Material kMinInteractiveDimension (48.0).
const double _kMinInteractiveDimension = 48.0;

class User {
  const User({required this.email, required this.name});

  final String email;
  final String name;

  @override
  String toString() {
    return '$name, $email';
  }
}

void main() {
  const kOptions = <String>[
    'aardvark',
    'bobcat',
    'chameleon',
    'dingo',
    'elephant',
    'flamingo',
    'goose',
    'hippopotamus',
    'iguana',
    'jaguar',
    'koala',
    'lemur',
    'mouse',
    'northern white rhinoceros',
  ];

  const kOptionsUsers = <User>[
    User(name: 'Alice', email: 'alice@example.com'),
    User(name: 'Bob', email: 'bob@example.com'),
    User(name: 'Charlie', email: 'charlie123@gmail.com'),
  ];

  testWidgets('can filter and select a list of string options', (WidgetTester tester) async {
    final GlobalKey fieldKey = GlobalKey();
    final GlobalKey optionsKey = GlobalKey();
    late Iterable<String> lastOptions;
    late AutocompleteOnSelected<String> lastOnSelected;
    late FocusNode focusNode;
    late TextEditingController textEditingController;

    await tester.pumpWidget(
      TestWidgetsApp(
        home: RawAutocomplete<String>(
          optionsBuilder: (TextEditingValue textEditingValue) {
            return kOptions.where((String option) {
              return option.contains(textEditingValue.text.toLowerCase());
            });
          },
          fieldViewBuilder:
              (
                BuildContext context,
                TextEditingController fieldTextEditingController,
                FocusNode fieldFocusNode,
                VoidCallback onFieldSubmitted,
              ) {
                focusNode = fieldFocusNode;
                textEditingController = fieldTextEditingController;
                return TestTextField(
                  key: fieldKey,
                  focusNode: focusNode,
                  controller: textEditingController,
                );
              },
          optionsViewBuilder:
              (
                BuildContext context,
                AutocompleteOnSelected<String> onSelected,
                Iterable<String> options,
              ) {
                lastOptions = options;
                lastOnSelected = onSelected;
                return Container(key: optionsKey);
              },
        ),
      ),
    );

    // The field is always rendered, but the options are not unless needed.
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsNothing);

    // Focus the empty field. All the options are displayed.
    focusNode.requestFocus();
    await tester.pump();
    expect(find.byKey(optionsKey), findsOneWidget);
    expect(lastOptions.length, kOptions.length);

    // Enter text. The options are filtered by the text.
    textEditingController.value = const TextEditingValue(
      text: 'ele',
      selection: TextSelection(baseOffset: 3, extentOffset: 3),
    );
    await tester.pump();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsOneWidget);
    expect(lastOptions.length, 2);
    expect(lastOptions.elementAt(0), 'chameleon');
    expect(lastOptions.elementAt(1), 'elephant');

    // Select an option. The options hide and the field updates to show the
    // selection.
    final String selection = lastOptions.elementAt(1);
    lastOnSelected(selection);
    await tester.pump();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsNothing);
    expect(textEditingController.text, selection);

    // Modify the field text. The options appear again and are filtered.
    textEditingController.value = const TextEditingValue(
      text: 'e',
      selection: TextSelection(baseOffset: 1, extentOffset: 1),
    );
    await tester.pump();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsOneWidget);
    expect(lastOptions.length, 6);
    expect(lastOptions.elementAt(0), 'chameleon');
    expect(lastOptions.elementAt(1), 'elephant');
    expect(lastOptions.elementAt(2), 'goose');
    expect(lastOptions.elementAt(3), 'lemur');
    expect(lastOptions.elementAt(4), 'mouse');
    expect(lastOptions.elementAt(5), 'northern white rhinoceros');
  });

  testWidgets('can split the field and options', (WidgetTester tester) async {
    final GlobalKey fieldKey = GlobalKey();
    final GlobalKey optionsKey = GlobalKey();
    late Iterable<String> lastOptions;
    late AutocompleteOnSelected<String> lastOnSelected;

    final GlobalKey autocompleteKey = GlobalKey();
    final textEditingController = TextEditingController();
    final focusNode = FocusNode();
    addTearDown(textEditingController.dispose);
    addTearDown(focusNode.dispose);

    await tester.pumpWidget(
      TestWidgetsApp(
        home: Column(
          children: <Widget>[
            // The field that is not actually a child of RawAutocomplete.
            TestTextField(
              key: fieldKey,
              controller: textEditingController,
              focusNode: focusNode,
              onSubmitted: (String value) {
                RawAutocomplete.onFieldSubmitted<String>(autocompleteKey);
              },
            ),
            Expanded(
              child: Align(
                alignment: Alignment.topLeft,
                child: RawAutocomplete<String>(
                  key: autocompleteKey,
                  focusNode: focusNode,
                  textEditingController: textEditingController,
                  optionsBuilder: (TextEditingValue textEditingValue) {
                    return kOptions.where((String option) {
                      return option.contains(textEditingValue.text.toLowerCase());
                    }).toList();
                  },
                  optionsViewBuilder:
                      (
                        BuildContext context,
                        AutocompleteOnSelected<String> onSelected,
                        Iterable<String> options,
                      ) {
                        lastOptions = options;
                        lastOnSelected = onSelected;
                        return ListView(
                          key: optionsKey,
                          children: options
                              .map(
                                (String option) => GestureDetector(
                                  onTap: () {
                                    onSelected(option);
                                  },
                                  child: TestListTile(title: Text(option)),
                                ),
                              )
                              .toList(),
                        );
                      },
                ),
              ),
            ),
          ],
        ),
      ),
    );

    // The field is always rendered, but the options are not unless needed.
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsNothing);

    // Focus the empty field. All the options are displayed.
    focusNode.requestFocus();
    await tester.pump();
    expect(find.byKey(optionsKey), findsOneWidget);
    expect(lastOptions.length, kOptions.length);
    expect(tester.getSize(find.byKey(optionsKey)).width, greaterThan(0.0));

    // Enter text. The options are filtered by the text.
    textEditingController.value = const TextEditingValue(
      text: 'ele',
      selection: TextSelection(baseOffset: 3, extentOffset: 3),
    );
    await tester.pump();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsOneWidget);
    expect(lastOptions.length, 2);
    expect(lastOptions.elementAt(0), 'chameleon');
    expect(lastOptions.elementAt(1), 'elephant');

    // Select an option. The options hide and the field updates to show the
    // selection.
    final String selection = lastOptions.elementAt(1);
    lastOnSelected(selection);
    await tester.pump();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsNothing);
    expect(textEditingController.text, selection);

    // Modify the field text. The options appear again and are filtered.
    textEditingController.value = const TextEditingValue(
      text: 'e',
      selection: TextSelection(baseOffset: 1, extentOffset: 1),
    );
    await tester.pump();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsOneWidget);
    expect(lastOptions.length, 6);
    expect(lastOptions.elementAt(0), 'chameleon');
    expect(lastOptions.elementAt(1), 'elephant');
    expect(lastOptions.elementAt(2), 'goose');
    expect(lastOptions.elementAt(3), 'lemur');
    expect(lastOptions.elementAt(4), 'mouse');
    expect(lastOptions.elementAt(5), 'northern white rhinoceros');
  });

  for (final OptionsViewOpenDirection openDirection in OptionsViewOpenDirection.values) {
    testWidgets('tapping on an option selects it ($openDirection)', (WidgetTester tester) async {
      final GlobalKey fieldKey = GlobalKey();
      final GlobalKey optionsKey = GlobalKey();
      late Iterable<String> lastOptions;
      late FocusNode focusNode;
      late TextEditingController textEditingController;

      await tester.pumpWidget(
        TestWidgetsApp(
          home: Column(
            children: <Widget>[
              const SizedBox(height: 200),
              RawAutocomplete<String>(
                optionsViewOpenDirection: openDirection,
                optionsBuilder: (TextEditingValue textEditingValue) {
                  return kOptions.where((String option) {
                    return option.contains(textEditingValue.text.toLowerCase());
                  });
                },
                fieldViewBuilder:
                    (
                      BuildContext context,
                      TextEditingController fieldTextEditingController,
                      FocusNode fieldFocusNode,
                      VoidCallback onFieldSubmitted,
                    ) {
                      focusNode = fieldFocusNode;
                      textEditingController = fieldTextEditingController;
                      return TestTextField(
                        key: fieldKey,
                        focusNode: focusNode,
                        controller: textEditingController,
                      );
                    },
                optionsViewBuilder:
                    (
                      BuildContext context,
                      AutocompleteOnSelected<String> onSelected,
                      Iterable<String> options,
                    ) {
                      lastOptions = options;
                      return ListView.builder(
                        key: optionsKey,
                        padding: const EdgeInsets.all(8.0),
                        itemCount: options.length,
                        itemBuilder: (BuildContext context, int index) {
                          final String option = options.elementAt(index);
                          return GestureDetector(
                            onTap: () {
                              onSelected(option);
                            },
                            child: TestListTile(title: Text(option)),
                          );
                        },
                      );
                    },
              ),
            ],
          ),
        ),
      );

      // The field is always rendered, but the options are not unless needed.
      expect(find.byKey(fieldKey), findsOneWidget);
      expect(find.byKey(optionsKey), findsNothing);

      // Tap on the text field to open the options.
      await tester.tap(find.byKey(fieldKey));
      await tester.pump();
      expect(find.byKey(optionsKey), findsOneWidget);
      expect(lastOptions.length, kOptions.length);

      await tester.tap(find.text(kOptions[2]));
      await tester.pump();

      expect(find.byKey(optionsKey), findsNothing);

      expect(textEditingController.text, equals(kOptions[2]));
    });

    testWidgets('when not enough room for options, options cover field ($openDirection)', (
      WidgetTester tester,
    ) async {
      const padding = 32.0;
      final GlobalKey fieldKey = GlobalKey();
      final GlobalKey optionsKey = GlobalKey();
      late StateSetter setState;
      Alignment alignment = Alignment.bottomCenter;

      await tester.pumpWidget(
        TestWidgetsApp(
          home: StatefulBuilder(
            builder: (BuildContext context, StateSetter setter) {
              setState = setter;
              return Padding(
                padding: const EdgeInsets.symmetric(horizontal: padding),
                child: Align(
                  alignment: alignment,
                  child: RawAutocomplete<String>(
                    optionsViewOpenDirection: openDirection,
                    optionsBuilder: (TextEditingValue textEditingValue) {
                      return kOptions.where((String option) {
                        return option.contains(textEditingValue.text.toLowerCase());
                      });
                    },
                    optionsViewBuilder:
                        (
                          BuildContext context,
                          AutocompleteOnSelected<String> onSelected,
                          Iterable<String> options,
                        ) {
                          return ListView.builder(
                            key: optionsKey,
                            padding: EdgeInsets.zero,
                            shrinkWrap: true,
                            itemCount: options.length,
                            itemBuilder: (BuildContext context, int index) {
                              final String option = options.elementAt(index);
                              return _OptionTile(
                                onTap: () {
                                  onSelected(option);
                                },
                                child: Padding(
                                  padding: const EdgeInsets.all(16.0),
                                  child: Text(option),
                                ),
                              );
                            },
                          );
                        },
                    fieldViewBuilder:
                        (
                          BuildContext context,
                          TextEditingController textEditingController,
                          FocusNode focusNode,
                          VoidCallback onSubmitted,
                        ) {
                          return TestTextField(
                            key: fieldKey,
                            focusNode: focusNode,
                            controller: textEditingController,
                          );
                        },
                  ),
                ),
              );
            },
          ),
        ),
      );

      expect(find.byKey(fieldKey), findsOneWidget);
      expect(find.byKey(optionsKey), findsNothing);

      await tester.tap(find.byKey(fieldKey));
      await tester.pump();

      expect(find.byKey(fieldKey), findsOneWidget);
      expect(find.byKey(optionsKey), findsOneWidget);

      await tester.enterText(find.byKey(fieldKey), 'go'); // 3 results.
      await tester.pump();

      switch (openDirection) {
        case OptionsViewOpenDirection.up:
          // Options are positioned and sized like normal.
          expect(find.byType(_OptionTile), findsNWidgets(3));
          final double optionHeight = tester.getSize(find.byType(_OptionTile).first).height;
          final double topOfField = tester.getTopLeft(find.byKey(fieldKey)).dy;
          expect(
            tester.getTopLeft(find.byType(_OptionTile).first),
            Offset(padding, topOfField - 3 * optionHeight),
          );
          expect(tester.getBottomLeft(find.byType(_OptionTile).at(2)), Offset(padding, topOfField));
        case OptionsViewOpenDirection.down:
          expect(find.byType(_OptionTile), findsNWidgets(1));
          final Size optionsSize = tester.getSize(find.byKey(optionsKey));
          expect(optionsSize.height, _kMinInteractiveDimension);
          // Options are positioned as low as possible while still fitting on screen.
          final double bottomOfField = tester.getBottomLeft(find.byKey(optionsKey)).dy;
          expect(
            tester.getTopLeft(find.byKey(optionsKey)),
            Offset(padding, bottomOfField - optionsSize.height),
          );
        case OptionsViewOpenDirection.mostSpace:
          // Behaves like OptionsViewOpenDirection.up.
          expect(find.byType(_OptionTile), findsNWidgets(3));
          final double optionHeight = tester.getSize(find.byType(_OptionTile).first).height;
          final double topOfField = tester.getTopLeft(find.byKey(fieldKey)).dy;
          expect(
            tester.getTopLeft(find.byType(_OptionTile).first),
            Offset(padding, topOfField - 3 * optionHeight),
          );
          expect(tester.getBottomLeft(find.byType(_OptionTile).at(2)), Offset(padding, topOfField));
      }

      setState(() {
        alignment = Alignment.topCenter;
      });

      await tester.pump();

      expect(find.byKey(fieldKey), findsOneWidget);
      expect(find.byKey(optionsKey), findsOneWidget);

      switch (openDirection) {
        case OptionsViewOpenDirection.up:
          // Options are positioned as high as possible while still fitting on
          // the screen.
          expect(find.byType(_OptionTile), findsNWidgets(1));
          final Size optionsSize = tester.getSize(find.byKey(optionsKey));
          expect(optionsSize.height, _kMinInteractiveDimension);
          expect(tester.getTopLeft(find.byKey(optionsKey)), const Offset(padding, 0.0));
          expect(tester.getBottomLeft(find.byKey(optionsKey)), Offset(padding, optionsSize.height));
        case OptionsViewOpenDirection.down:
          // Options are positioned and sized like normal.
          expect(find.byType(_OptionTile), findsNWidgets(3));
          final double optionHeight = tester.getSize(find.byType(_OptionTile).first).height;
          final double bottomOfField = tester.getBottomLeft(find.byKey(fieldKey)).dy;
          expect(tester.getTopLeft(find.byType(_OptionTile).first), Offset(padding, bottomOfField));
          expect(
            tester.getBottomLeft(find.byType(_OptionTile).at(2)),
            Offset(padding, bottomOfField + 3 * optionHeight),
          );
        case OptionsViewOpenDirection.mostSpace:
          // Behaves like OptionsViewOpenDirection.down.
          expect(find.byType(_OptionTile), findsNWidgets(3));
          final double optionHeight = tester.getSize(find.byType(_OptionTile).first).height;
          final double bottomOfField = tester.getBottomLeft(find.byKey(fieldKey)).dy;
          expect(tester.getTopLeft(find.byType(_OptionTile).first), Offset(padding, bottomOfField));
          expect(
            tester.getBottomLeft(find.byType(_OptionTile).at(2)),
            Offset(padding, bottomOfField + 3 * optionHeight),
          );
      }
    });

    testWidgets('correct options alignment for RTL in direction $openDirection', (
      WidgetTester tester,
    ) async {
      final GlobalKey fieldKey = GlobalKey();
      final GlobalKey optionsKey = GlobalKey();
      const kOptionsWidth = 100.0;
      await tester.pumpWidget(
        TestWidgetsApp(
          home: Directionality(
            textDirection: TextDirection.rtl,
            child: Padding(
              padding: const EdgeInsets.symmetric(horizontal: 32.0),
              child: RawAutocomplete<String>(
                optionsViewOpenDirection: openDirection,
                optionsBuilder: (TextEditingValue textEditingValue) {
                  return kOptions.where((String option) {
                    return option.contains(textEditingValue.text.toLowerCase());
                  });
                },
                fieldViewBuilder:
                    (
                      BuildContext context,
                      TextEditingController textEditingController,
                      FocusNode focusNode,
                      VoidCallback onSubmitted,
                    ) {
                      return TestTextField(
                        key: fieldKey,
                        focusNode: focusNode,
                        controller: textEditingController,
                      );
                    },
                optionsViewBuilder:
                    (
                      BuildContext context,
                      AutocompleteOnSelected<String> onSelected,
                      Iterable<String> options,
                    ) {
                      return SizedBox(width: kOptionsWidth, key: optionsKey);
                    },
              ),
            ),
          ),
        ),
      );

      expect(find.byKey(fieldKey), findsOneWidget);
      expect(find.byKey(optionsKey), findsNothing);

      await tester.tap(find.byType(TestTextField));
      await tester.pump();

      expect(find.byKey(fieldKey), findsOneWidget);
      expect(find.byKey(optionsKey), findsOneWidget);

      final RenderBox optionsBox = tester.renderObject(find.byKey(optionsKey));
      expect(optionsBox.size.width, kOptionsWidth);
      expect(
        tester.getTopRight(find.byKey(optionsKey)).dx,
        tester.getTopRight(find.byKey(fieldKey)).dx,
      );
    });

    testWidgets('options width matches field width with open direction $openDirection', (
      WidgetTester tester,
    ) async {
      final GlobalKey fieldKey = GlobalKey();
      final GlobalKey optionsKey = GlobalKey();

      await tester.pumpWidget(
        TestWidgetsApp(
          home: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 32.0),
            child: Center(
              child: RawAutocomplete<String>(
                optionsViewOpenDirection: openDirection,
                optionsBuilder: (TextEditingValue textEditingValue) {
                  return kOptions.where((String option) {
                    return option.contains(textEditingValue.text.toLowerCase());
                  });
                },
                fieldViewBuilder:
                    (
                      BuildContext context,
                      TextEditingController textEditingController,
                      FocusNode focusNode,
                      VoidCallback onSubmitted,
                    ) {
                      return TestTextField(
                        key: fieldKey,
                        focusNode: focusNode,
                        controller: textEditingController,
                      );
                    },
                optionsViewBuilder:
                    (
                      BuildContext context,
                      AutocompleteOnSelected<String> onSelected,
                      Iterable<String> options,
                    ) {
                      return Container(key: optionsKey);
                    },
              ),
            ),
          ),
        ),
      );

      expect(find.byKey(fieldKey), findsOneWidget);
      expect(find.byKey(optionsKey), findsNothing);

      await tester.tap(find.byType(TestTextField));
      await tester.pump();

      expect(find.byKey(fieldKey), findsOneWidget);
      expect(find.byKey(optionsKey), findsOneWidget);

      final RenderBox fieldBox = tester.renderObject(find.byKey(fieldKey));
      final RenderBox optionsBox = tester.renderObject(find.byKey(optionsKey));
      expect(optionsBox.size.width, equals(fieldBox.size.width));
      expect(tester.getTopLeft(find.byKey(optionsKey)).dy, switch (openDirection) {
        OptionsViewOpenDirection.down =>
          tester.getTopLeft(find.byKey(fieldKey)).dy + fieldBox.size.height,
        OptionsViewOpenDirection.up =>
          tester.getTopLeft(find.byKey(fieldKey)).dy - optionsBox.size.height,
        OptionsViewOpenDirection.mostSpace =>
          tester.getTopLeft(find.byKey(fieldKey)).dy + fieldBox.size.height,
      });
    });
  }

  testWidgets('can filter and select a list of custom User options', (WidgetTester tester) async {
    final GlobalKey fieldKey = GlobalKey();
    final GlobalKey optionsKey = GlobalKey();
    late Iterable<User> lastOptions;
    late AutocompleteOnSelected<User> lastOnSelected;
    late User lastUserSelected;
    late FocusNode focusNode;
    late TextEditingController textEditingController;

    await tester.pumpWidget(
      TestWidgetsApp(
        home: RawAutocomplete<User>(
          optionsBuilder: (TextEditingValue textEditingValue) {
            return kOptionsUsers.where((User option) {
              return option.toString().contains(textEditingValue.text.toLowerCase());
            });
          },
          onSelected: (User selected) {
            lastUserSelected = selected;
          },
          fieldViewBuilder:
              (
                BuildContext context,
                TextEditingController fieldTextEditingController,
                FocusNode fieldFocusNode,
                VoidCallback onFieldSubmitted,
              ) {
                focusNode = fieldFocusNode;
                textEditingController = fieldTextEditingController;
                return TestTextField(
                  key: fieldKey,
                  focusNode: focusNode,
                  controller: fieldTextEditingController,
                );
              },
          optionsViewBuilder:
              (
                BuildContext context,
                AutocompleteOnSelected<User> onSelected,
                Iterable<User> options,
              ) {
                lastOptions = options;
                lastOnSelected = onSelected;
                return Container(key: optionsKey);
              },
        ),
      ),
    );

    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsNothing);

    // Enter text. The options are filtered by the text.
    focusNode.requestFocus();
    textEditingController.value = const TextEditingValue(
      text: 'example',
      selection: TextSelection(baseOffset: 7, extentOffset: 7),
    );
    await tester.pump();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsOneWidget);
    expect(lastOptions.length, 2);
    expect(lastOptions.elementAt(0), kOptionsUsers[0]);
    expect(lastOptions.elementAt(1), kOptionsUsers[1]);

    // Select an option. The options hide and onSelected is called.
    final User selection = lastOptions.elementAt(1);
    lastOnSelected(selection);
    await tester.pump();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsNothing);
    expect(lastUserSelected, selection);
    expect(textEditingController.text, selection.toString());

    // Modify the field text. The options appear again and are filtered, this
    // time by name instead of email.
    textEditingController.value = const TextEditingValue(
      text: 'B',
      selection: TextSelection(baseOffset: 1, extentOffset: 1),
    );
    await tester.pump();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsOneWidget);
    expect(lastOptions.length, 1);
    expect(lastOptions.elementAt(0), kOptionsUsers[1]);
  });

  testWidgets('can specify a custom display string for a list of custom User options', (
    WidgetTester tester,
  ) async {
    final GlobalKey fieldKey = GlobalKey();
    final GlobalKey optionsKey = GlobalKey();
    late Iterable<User> lastOptions;
    late AutocompleteOnSelected<User> lastOnSelected;
    late User lastUserSelected;
    String displayStringForOption(User option) => option.name;
    late FocusNode focusNode;
    late TextEditingController textEditingController;

    await tester.pumpWidget(
      TestWidgetsApp(
        home: RawAutocomplete<User>(
          optionsBuilder: (TextEditingValue textEditingValue) {
            return kOptionsUsers.where((User option) {
              return option.toString().contains(textEditingValue.text.toLowerCase());
            });
          },
          displayStringForOption: displayStringForOption,
          onSelected: (User selected) {
            lastUserSelected = selected;
          },
          fieldViewBuilder:
              (
                BuildContext context,
                TextEditingController fieldTextEditingController,
                FocusNode fieldFocusNode,
                VoidCallback onFieldSubmitted,
              ) {
                textEditingController = fieldTextEditingController;
                focusNode = fieldFocusNode;
                return TestTextField(
                  key: fieldKey,
                  focusNode: focusNode,
                  controller: fieldTextEditingController,
                );
              },
          optionsViewBuilder:
              (
                BuildContext context,
                AutocompleteOnSelected<User> onSelected,
                Iterable<User> options,
              ) {
                lastOptions = options;
                lastOnSelected = onSelected;
                return Container(key: optionsKey);
              },
        ),
      ),
    );

    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsNothing);

    // Enter text. The options are filtered by the text.
    focusNode.requestFocus();
    textEditingController.value = const TextEditingValue(
      text: 'example',
      selection: TextSelection(baseOffset: 7, extentOffset: 7),
    );
    await tester.pump();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsOneWidget);
    expect(lastOptions.length, 2);
    expect(lastOptions.elementAt(0), kOptionsUsers[0]);
    expect(lastOptions.elementAt(1), kOptionsUsers[1]);

    // Select an option. The options hide and onSelected is called. The field
    // has its text set to the selection's display string.
    final User selection = lastOptions.elementAt(1);
    lastOnSelected(selection);
    await tester.pump();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsNothing);
    expect(lastUserSelected, selection);
    expect(textEditingController.text, selection.name);

    // Modify the field text. The options appear again and are filtered, this
    // time by name instead of email.
    textEditingController.value = const TextEditingValue(
      text: 'B',
      selection: TextSelection(baseOffset: 1, extentOffset: 1),
    );
    await tester.pump();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsOneWidget);
    expect(lastOptions.length, 1);
    expect(lastOptions.elementAt(0), kOptionsUsers[1]);
  });

  testWidgets('onFieldSubmitted selects the first option', (WidgetTester tester) async {
    final GlobalKey fieldKey = GlobalKey();
    final GlobalKey optionsKey = GlobalKey();
    late Iterable<String> lastOptions;
    late VoidCallback lastOnFieldSubmitted;
    late FocusNode focusNode;
    late TextEditingController textEditingController;

    await tester.pumpWidget(
      TestWidgetsApp(
        home: RawAutocomplete<String>(
          optionsBuilder: (TextEditingValue textEditingValue) {
            return kOptions.where((String option) {
              return option.contains(textEditingValue.text.toLowerCase());
            });
          },
          fieldViewBuilder:
              (
                BuildContext context,
                TextEditingController fieldTextEditingController,
                FocusNode fieldFocusNode,
                VoidCallback onFieldSubmitted,
              ) {
                textEditingController = fieldTextEditingController;
                focusNode = fieldFocusNode;
                lastOnFieldSubmitted = onFieldSubmitted;
                return TestTextField(
                  key: fieldKey,
                  focusNode: focusNode,
                  controller: fieldTextEditingController,
                );
              },
          optionsViewBuilder:
              (
                BuildContext context,
                AutocompleteOnSelected<String> onSelected,
                Iterable<String> options,
              ) {
                lastOptions = options;
                return Container(key: optionsKey);
              },
        ),
      ),
    );

    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsNothing);

    // Enter text. The options are filtered by the text.
    focusNode.requestFocus();
    textEditingController.value = const TextEditingValue(
      text: 'ele',
      selection: TextSelection(baseOffset: 3, extentOffset: 3),
    );
    await tester.pump();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsOneWidget);
    expect(lastOptions.length, 2);
    expect(lastOptions.elementAt(0), 'chameleon');
    expect(lastOptions.elementAt(1), 'elephant');

    // Select the current string, as if the field was submitted. The options
    // hide and the field updates to show the selection.
    lastOnFieldSubmitted();
    await tester.pump();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsNothing);
    expect(textEditingController.text, lastOptions.elementAt(0));
  });

  group('optionsViewOpenDirection', () {
    testWidgets('unset (default behavior): open downward', (WidgetTester tester) async {
      await tester.pumpWidget(
        TestWidgetsApp(
          home: Center(
            child: RawAutocomplete<String>(
              optionsBuilder: (TextEditingValue textEditingValue) => <String>['a'],
              fieldViewBuilder:
                  (
                    BuildContext context,
                    TextEditingController controller,
                    FocusNode focusNode,
                    VoidCallback onFieldSubmitted,
                  ) {
                    return TestTextField(controller: controller, focusNode: focusNode);
                  },
              optionsViewBuilder:
                  (
                    BuildContext context,
                    AutocompleteOnSelected<String> onSelected,
                    Iterable<String> options,
                  ) {
                    return const Text('a');
                  },
            ),
          ),
        ),
      );
      await tester.showKeyboard(find.byType(TestTextField));
      await tester.pump();
      expect(
        tester.getBottomLeft(find.byType(TestTextField)),
        offsetMoreOrLessEquals(tester.getTopLeft(find.text('a'))),
      );
    });

    testWidgets('down: open downward', (WidgetTester tester) async {
      await tester.pumpWidget(
        TestWidgetsApp(
          home: Center(
            child: RawAutocomplete<String>(
              // ignore: avoid_redundant_argument_values
              optionsViewOpenDirection: OptionsViewOpenDirection.down,
              optionsBuilder: (TextEditingValue textEditingValue) => <String>['a'],
              fieldViewBuilder:
                  (
                    BuildContext context,
                    TextEditingController controller,
                    FocusNode focusNode,
                    VoidCallback onFieldSubmitted,
                  ) {
                    return TestTextField(controller: controller, focusNode: focusNode);
                  },
              optionsViewBuilder:
                  (
                    BuildContext context,
                    AutocompleteOnSelected<String> onSelected,
                    Iterable<String> options,
                  ) {
                    return const Text('a');
                  },
            ),
          ),
        ),
      );
      await tester.showKeyboard(find.byType(TestTextField));
      await tester.pump();
      expect(
        tester.getBottomLeft(find.byType(TestTextField)),
        offsetMoreOrLessEquals(tester.getTopLeft(find.text('a'))),
      );
    });

    testWidgets('up: open upward', (WidgetTester tester) async {
      await tester.pumpWidget(
        TestWidgetsApp(
          home: Center(
            child: RawAutocomplete<String>(
              optionsViewOpenDirection: OptionsViewOpenDirection.up,
              optionsBuilder: (TextEditingValue textEditingValue) => <String>['a'],
              fieldViewBuilder:
                  (
                    BuildContext context,
                    TextEditingController controller,
                    FocusNode focusNode,
                    VoidCallback onFieldSubmitted,
                  ) {
                    return TestTextField(controller: controller, focusNode: focusNode);
                  },
              optionsViewBuilder:
                  (
                    BuildContext context,
                    AutocompleteOnSelected<String> onSelected,
                    Iterable<String> options,
                  ) {
                    return const Text('a');
                  },
            ),
          ),
        ),
      );
      await tester.showKeyboard(find.byType(TestTextField));
      await tester.pump();
      expect(
        tester.getTopLeft(find.byType(TestTextField)),
        offsetMoreOrLessEquals(tester.getBottomLeft(find.text('a'))),
      );
    });

    testWidgets('auto: open in the direction with more space', (WidgetTester tester) async {
      final GlobalKey fieldKey = GlobalKey();
      final GlobalKey optionsKey = GlobalKey();
      late StateSetter setState;
      Alignment alignment = Alignment.topCenter;

      await tester.pumpWidget(
        TestWidgetsApp(
          home: StatefulBuilder(
            builder: (BuildContext context, StateSetter setter) {
              setState = setter;
              return Align(
                alignment: alignment,
                child: RawAutocomplete<String>(
                  key: fieldKey,
                  optionsViewOpenDirection: OptionsViewOpenDirection.mostSpace,
                  optionsBuilder: (TextEditingValue textEditingValue) => <String>['a', 'b', 'c'],
                  fieldViewBuilder:
                      (
                        BuildContext context,
                        TextEditingController controller,
                        FocusNode focusNode,
                        VoidCallback onFieldSubmitted,
                      ) {
                        return TestTextField(controller: controller, focusNode: focusNode);
                      },
                  optionsViewBuilder:
                      (
                        BuildContext context,
                        AutocompleteOnSelected<String> onSelected,
                        Iterable<String> options,
                      ) {
                        return ListView(
                          key: optionsKey,
                          children: options.map((String option) => Text(option)).toList(),
                        );
                      },
                ),
              );
            },
          ),
        ),
      );

      // Show the options. It should open downwards since there is more space.
      await tester.tap(find.byType(TestTextField));
      await tester.pump();

      expect(
        tester.getBottomLeft(find.byKey(fieldKey)),
        offsetMoreOrLessEquals(tester.getTopLeft(find.byKey(optionsKey))),
      );

      // Move the field to the bottom.
      setState(() {
        alignment = Alignment.bottomCenter;
      });
      await tester.pump();

      // The options should now open upwards, since there is more space above.
      expect(
        tester.getTopLeft(find.byKey(fieldKey)),
        offsetMoreOrLessEquals(tester.getBottomLeft(find.byKey(optionsKey))),
      );
    });

    group('fieldViewBuilder not passed', () {
      testWidgets('down', (WidgetTester tester) async {
        final GlobalKey autocompleteKey = GlobalKey();
        final controller = TextEditingController();
        addTearDown(controller.dispose);
        final focusNode = FocusNode();
        addTearDown(focusNode.dispose);
        await tester.pumpWidget(
          TestWidgetsApp(
            home: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                TestTextField(controller: controller, focusNode: focusNode),
                RawAutocomplete<String>(
                  key: autocompleteKey,
                  textEditingController: controller,
                  focusNode: focusNode,
                  // ignore: avoid_redundant_argument_values
                  optionsViewOpenDirection: OptionsViewOpenDirection.down,
                  optionsBuilder: (TextEditingValue textEditingValue) => <String>['a'],
                  optionsViewBuilder:
                      (
                        BuildContext context,
                        AutocompleteOnSelected<String> onSelected,
                        Iterable<String> options,
                      ) {
                        return const Text('a');
                      },
                ),
              ],
            ),
          ),
        );
        await tester.showKeyboard(find.byType(TestTextField));
        await tester.pump();
        expect(
          tester.getBottomLeft(find.byKey(autocompleteKey)),
          offsetMoreOrLessEquals(tester.getTopLeft(find.text('a'))),
        );
      });

      testWidgets('up', (WidgetTester tester) async {
        final GlobalKey autocompleteKey = GlobalKey();
        final controller = TextEditingController();
        addTearDown(controller.dispose);
        final focusNode = FocusNode();
        addTearDown(focusNode.dispose);
        await tester.pumpWidget(
          TestWidgetsApp(
            home: Column(
              mainAxisAlignment: MainAxisAlignment.end,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                RawAutocomplete<String>(
                  key: autocompleteKey,
                  textEditingController: controller,
                  focusNode: focusNode,
                  optionsViewOpenDirection: OptionsViewOpenDirection.up,
                  optionsBuilder: (TextEditingValue textEditingValue) => <String>['a'],
                  optionsViewBuilder:
                      (
                        BuildContext context,
                        AutocompleteOnSelected<String> onSelected,
                        Iterable<String> options,
                      ) {
                        return const Text('a');
                      },
                ),
                TestTextField(controller: controller, focusNode: focusNode),
              ],
            ),
          ),
        );
        await tester.showKeyboard(find.byType(TestTextField));
        await tester.pump();
        expect(
          tester.getTopLeft(find.byKey(autocompleteKey)),
          offsetMoreOrLessEquals(tester.getBottomLeft(find.text('a'))),
        );
      });
    });
  });

  testWidgets('options follow field when it moves', (WidgetTester tester) async {
    final GlobalKey fieldKey = GlobalKey();
    final GlobalKey optionsKey = GlobalKey();
    late StateSetter setState;
    Alignment alignment = Alignment.center;
    late FocusNode focusNode;
    late TextEditingController textEditingController;

    await tester.pumpWidget(
      TestWidgetsApp(
        home: StatefulBuilder(
          builder: (BuildContext context, StateSetter setter) {
            setState = setter;
            return Align(
              alignment: alignment,
              child: RawAutocomplete<String>(
                optionsBuilder: (TextEditingValue textEditingValue) {
                  return kOptions.where((String option) {
                    return option.contains(textEditingValue.text.toLowerCase());
                  });
                },
                fieldViewBuilder:
                    (
                      BuildContext context,
                      TextEditingController fieldTextEditingController,
                      FocusNode fieldFocusNode,
                      VoidCallback onFieldSubmitted,
                    ) {
                      focusNode = fieldFocusNode;
                      textEditingController = fieldTextEditingController;
                      return TestTextField(
                        controller: fieldTextEditingController,
                        focusNode: focusNode,
                        key: fieldKey,
                      );
                    },
                optionsViewBuilder:
                    (
                      BuildContext context,
                      AutocompleteOnSelected<String> onSelected,
                      Iterable<String> options,
                    ) {
                      return Container(key: optionsKey);
                    },
              ),
            );
          },
        ),
      ),
    );

    // Field is shown but not options.
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsNothing);

    // Enter text to show the options.
    focusNode.requestFocus();
    textEditingController.value = const TextEditingValue(
      text: 'ele',
      selection: TextSelection(baseOffset: 3, extentOffset: 3),
    );
    await tester.pump();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsOneWidget);

    // Options are just below the field.
    final Offset optionsTopLeft = tester.getTopLeft(find.byKey(optionsKey));
    final Offset fieldOffset = tester.getTopLeft(find.byKey(fieldKey));
    final Size fieldSize = tester.getSize(find.byKey(fieldKey));
    expect(optionsTopLeft.dy, fieldOffset.dy + fieldSize.height);

    // Move the field (similar to as if the keyboard opened). The options move
    // to follow the field.
    setState(() {
      alignment = Alignment.topCenter;
    });
    await tester.pump();
    final Offset fieldOffsetFrame1 = tester.getTopLeft(find.byKey(fieldKey));
    final Offset optionsTopLeftOpenFrame1 = tester.getTopLeft(find.byKey(optionsKey));

    expect(fieldOffsetFrame1.dy, lessThan(fieldOffset.dy));
    expect(optionsTopLeftOpenFrame1.dy, isNot(equals(optionsTopLeft.dy)));
    expect(optionsTopLeftOpenFrame1.dy, fieldOffsetFrame1.dy + fieldSize.height);
  });

  testWidgets('options are shown one frame after tapping in field', (WidgetTester tester) async {
    final GlobalKey fieldKey = GlobalKey();
    final GlobalKey optionsKey = GlobalKey();

    await tester.pumpWidget(
      TestWidgetsApp(
        home: Align(
          alignment: Alignment.topCenter,
          child: RawAutocomplete<String>(
            optionsBuilder: (TextEditingValue textEditingValue) {
              return kOptions.where((String option) {
                return option.contains(textEditingValue.text.toLowerCase());
              });
            },
            fieldViewBuilder:
                (
                  BuildContext context,
                  TextEditingController fieldTextEditingController,
                  FocusNode fieldFocusNode,
                  VoidCallback onFieldSubmitted,
                ) {
                  return TestTextField(
                    controller: fieldTextEditingController,
                    focusNode: fieldFocusNode,
                    key: fieldKey,
                  );
                },
            optionsViewBuilder:
                (
                  BuildContext context,
                  AutocompleteOnSelected<String> onSelected,
                  Iterable<String> options,
                ) {
                  return ListView(
                    key: optionsKey,
                    children: options.map((String option) => Text(option)).toList(),
                  );
                },
          ),
        ),
      ),
    );

    // Field is shown but not options.
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsNothing);
    expect(find.text('aardvark'), findsNothing);

    // Tap to show the options.
    await tester.tap(find.byKey(fieldKey));
    await tester.pump();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsOneWidget);
    expect(find.text('aardvark'), findsOneWidget);
  });

  testWidgets('can prevent options from showing by returning an empty iterable', (
    WidgetTester tester,
  ) async {
    final GlobalKey fieldKey = GlobalKey();
    final GlobalKey optionsKey = GlobalKey();
    late Iterable<String> lastOptions;
    late FocusNode focusNode;
    late TextEditingController textEditingController;

    await tester.pumpWidget(
      TestWidgetsApp(
        home: RawAutocomplete<String>(
          optionsBuilder: (TextEditingValue textEditingValue) {
            if (textEditingValue.text == '') {
              return const Iterable<String>.empty();
            }
            return kOptions.where((String option) {
              return option.contains(textEditingValue.text.toLowerCase());
            });
          },
          fieldViewBuilder:
              (
                BuildContext context,
                TextEditingController fieldTextEditingController,
                FocusNode fieldFocusNode,
                VoidCallback onFieldSubmitted,
              ) {
                focusNode = fieldFocusNode;
                textEditingController = fieldTextEditingController;
                return TestTextField(
                  key: fieldKey,
                  focusNode: focusNode,
                  controller: fieldTextEditingController,
                );
              },
          optionsViewBuilder:
              (
                BuildContext context,
                AutocompleteOnSelected<String> onSelected,
                Iterable<String> options,
              ) {
                lastOptions = options;
                return Container(key: optionsKey);
              },
        ),
      ),
    );

    // The field is always rendered, but the options are not unless needed.
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsNothing);

    // Focus the empty field. The options are not displayed because
    // optionsBuilder returns nothing for an empty field query.
    focusNode.requestFocus();
    textEditingController.value = const TextEditingValue(
      selection: TextSelection(baseOffset: 0, extentOffset: 0),
    );
    await tester.pump();
    expect(find.byKey(optionsKey), findsNothing);

    // Enter text. Now the options appear, filtered by the text.
    textEditingController.value = const TextEditingValue(
      text: 'ele',
      selection: TextSelection(baseOffset: 3, extentOffset: 3),
    );
    await tester.pump();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsOneWidget);
    expect(lastOptions.length, 2);
    expect(lastOptions.elementAt(0), 'chameleon');
    expect(lastOptions.elementAt(1), 'elephant');
  });

  testWidgets('can create a field outside of fieldViewBuilder', (WidgetTester tester) async {
    final GlobalKey fieldKey = GlobalKey();
    final GlobalKey optionsKey = GlobalKey();
    final GlobalKey autocompleteKey = GlobalKey();
    late Iterable<String> lastOptions;
    final focusNode = FocusNode();
    addTearDown(focusNode.dispose);
    final textEditingController = TextEditingController();
    addTearDown(textEditingController.dispose);

    await tester.pumpWidget(
      TestWidgetsApp(
        home: Column(
          children: <Widget>[
            // This is where the real field is being built.
            TestTextField(
              key: fieldKey,
              controller: textEditingController,
              focusNode: focusNode,
              onSubmitted: (String value) {
                RawAutocomplete.onFieldSubmitted(autocompleteKey);
              },
            ),
            Expanded(
              child: RawAutocomplete<String>(
                key: autocompleteKey,
                focusNode: focusNode,
                textEditingController: textEditingController,
                optionsBuilder: (TextEditingValue textEditingValue) {
                  return kOptions.where((String option) {
                    return option.contains(textEditingValue.text.toLowerCase());
                  });
                },
                optionsViewBuilder:
                    (
                      BuildContext context,
                      AutocompleteOnSelected<String> onSelected,
                      Iterable<String> options,
                    ) {
                      lastOptions = options;
                      return Container(key: optionsKey);
                    },
              ),
            ),
          ],
        ),
      ),
    );

    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsNothing);

    // Enter text. The options are filtered by the text.
    focusNode.requestFocus();
    textEditingController.value = const TextEditingValue(
      text: 'ele',
      selection: TextSelection(baseOffset: 3, extentOffset: 3),
    );
    await tester.pump();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsOneWidget);
    expect(lastOptions.length, 2);
    expect(lastOptions.elementAt(0), 'chameleon');
    expect(lastOptions.elementAt(1), 'elephant');

    // Submit the field. The options hide and the field updates to show the
    // selection.
    await tester.showKeyboard(find.byType(TestTextField));
    await tester.testTextInput.receiveAction(TextInputAction.done);
    await tester.pump();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsNothing);
    expect(textEditingController.text, lastOptions.elementAt(0));
  });

  testWidgets('initialValue sets initial text field value', (WidgetTester tester) async {
    final GlobalKey fieldKey = GlobalKey();
    final GlobalKey optionsKey = GlobalKey();
    late Iterable<String> lastOptions;
    late AutocompleteOnSelected<String> lastOnSelected;
    late FocusNode focusNode;
    late TextEditingController textEditingController;

    await tester.pumpWidget(
      TestWidgetsApp(
        home: RawAutocomplete<String>(
          // Should initialize text field with 'lem'.
          initialValue: const TextEditingValue(text: 'lem'),
          optionsBuilder: (TextEditingValue textEditingValue) {
            return kOptions.where((String option) {
              return option.contains(textEditingValue.text.toLowerCase());
            });
          },
          fieldViewBuilder:
              (
                BuildContext context,
                TextEditingController fieldTextEditingController,
                FocusNode fieldFocusNode,
                VoidCallback onFieldSubmitted,
              ) {
                focusNode = fieldFocusNode;
                textEditingController = fieldTextEditingController;
                return TestTextField(
                  key: fieldKey,
                  focusNode: focusNode,
                  controller: textEditingController,
                );
              },
          optionsViewBuilder:
              (
                BuildContext context,
                AutocompleteOnSelected<String> onSelected,
                Iterable<String> options,
              ) {
                lastOptions = options;
                lastOnSelected = onSelected;
                return Container(key: optionsKey);
              },
        ),
      ),
    );

    // The field is always rendered, but the options are not unless needed.
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsNothing);
    // The text editing controller value starts off with initialized value.
    expect(textEditingController.text, 'lem');

    // Focus the empty field. All the options are displayed.
    focusNode.requestFocus();
    await tester.pump();
    expect(find.byKey(optionsKey), findsOneWidget);
    expect(lastOptions.elementAt(0), 'lemur');

    // Select an option. The options hide and the field updates to show the
    // selection.
    final String selection = lastOptions.elementAt(0);
    lastOnSelected(selection);
    await tester.pump();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsNothing);
    expect(textEditingController.text, selection);
  });

  testWidgets('initialValue cannot be defined if TextEditingController is defined', (
    WidgetTester tester,
  ) async {
    final focusNode = FocusNode();
    addTearDown(focusNode.dispose);
    final textEditingController = TextEditingController();
    addTearDown(textEditingController.dispose);

    expect(() {
      RawAutocomplete<String>(
        focusNode: focusNode,
        // Both [initialValue] and [textEditingController] cannot be
        // simultaneously defined.
        initialValue: const TextEditingValue(text: 'lemur'),
        textEditingController: textEditingController,
        optionsBuilder: (TextEditingValue textEditingValue) {
          return kOptions.where((String option) {
            return option.contains(textEditingValue.text.toLowerCase());
          });
        },
        optionsViewBuilder:
            (
              BuildContext context,
              AutocompleteOnSelected<String> onSelected,
              Iterable<String> options,
            ) {
              return Container();
            },
        fieldViewBuilder:
            (
              BuildContext context,
              TextEditingController fieldTextEditingController,
              FocusNode fieldFocusNode,
              VoidCallback onFieldSubmitted,
            ) {
              return TestTextField(focusNode: focusNode, controller: textEditingController);
            },
      );
    }, throwsAssertionError);
  });

  testWidgets('support asynchronous options builder', (WidgetTester tester) async {
    final GlobalKey fieldKey = GlobalKey();
    final GlobalKey optionsKey = GlobalKey();
    late FocusNode focusNode;
    late TextEditingController textEditingController;
    Iterable<String>? lastOptions;
    Duration? delay;

    await tester.pumpWidget(
      TestWidgetsApp(
        home: RawAutocomplete<String>(
          optionsBuilder: (TextEditingValue textEditingValue) async {
            final Iterable<String> options = kOptions.where((String option) {
              return option.contains(textEditingValue.text.toLowerCase());
            });
            if (delay == null) {
              return options;
            }
            return Future<Iterable<String>>.delayed(delay, () => options);
          },
          fieldViewBuilder:
              (
                BuildContext context,
                TextEditingController fieldTextEditingController,
                FocusNode fieldFocusNode,
                VoidCallback onFieldSubmitted,
              ) {
                focusNode = fieldFocusNode;
                textEditingController = fieldTextEditingController;
                return TestTextField(
                  key: fieldKey,
                  focusNode: focusNode,
                  controller: textEditingController,
                );
              },
          optionsViewBuilder:
              (
                BuildContext context,
                AutocompleteOnSelected<String> onSelected,
                Iterable<String> options,
              ) {
                lastOptions = options;
                return Container(key: optionsKey);
              },
        ),
      ),
    );

    // Enter text to build the options with delay.
    focusNode.requestFocus();
    delay = const Duration(milliseconds: 500);
    await tester.enterText(find.byKey(fieldKey), 'go');
    await tester.pumpAndSettle();

    // The options have not yet been built.
    expect(find.byKey(optionsKey), findsNothing);
    expect(lastOptions, isNull);

    // Await asynchronous options builder.
    await tester.pumpAndSettle(delay);
    expect(find.byKey(optionsKey), findsOneWidget);
    expect(lastOptions, <String>['dingo', 'flamingo', 'goose']);

    // Enter text to rebuild the options without delay.
    delay = null;
    await tester.enterText(find.byKey(fieldKey), 'ngo');
    await tester.pump();
    expect(lastOptions, <String>['dingo', 'flamingo']);
  });

  testWidgets('can navigate options with the arrow keys', (WidgetTester tester) async {
    final GlobalKey fieldKey = GlobalKey();
    final GlobalKey optionsKey = GlobalKey();
    late Iterable<String> lastOptions;
    late FocusNode focusNode;
    late TextEditingController textEditingController;
    late int lastHighlighted;
    await tester.pumpWidget(
      TestWidgetsApp(
        home: RawAutocomplete<String>(
          optionsBuilder: (TextEditingValue textEditingValue) {
            return kOptions.where((String option) {
              return option.contains(textEditingValue.text.toLowerCase());
            });
          },
          fieldViewBuilder:
              (
                BuildContext context,
                TextEditingController fieldTextEditingController,
                FocusNode fieldFocusNode,
                VoidCallback onFieldSubmitted,
              ) {
                focusNode = fieldFocusNode;
                textEditingController = fieldTextEditingController;
                return TestTextField(
                  key: fieldKey,
                  focusNode: focusNode,
                  controller: textEditingController,
                  onSubmitted: (String value) {
                    onFieldSubmitted();
                  },
                );
              },
          optionsViewBuilder:
              (
                BuildContext context,
                AutocompleteOnSelected<String> onSelected,
                Iterable<String> options,
              ) {
                lastHighlighted = AutocompleteHighlightedOption.of(context);
                lastOptions = options;
                return Container(key: optionsKey);
              },
        ),
      ),
    );

    // Enter text. The options are filtered by the text.
    focusNode.requestFocus();
    await tester.enterText(find.byKey(fieldKey), 'ele');
    await tester.pumpAndSettle();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsOneWidget);
    expect(lastOptions.length, 2);
    expect(lastOptions.elementAt(0), 'chameleon');
    expect(lastOptions.elementAt(1), 'elephant');

    // Move the highlighted option to the second item 'elephant' and select it
    await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
    // Can't use the key event for enter to submit to the text field using
    // the test framework, so this appears to be the equivalent.
    await tester.testTextInput.receiveAction(TextInputAction.done);
    await tester.pump();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsNothing);
    expect(textEditingController.text, 'elephant');

    // Modify the field text. The options appear again and are filtered.
    focusNode.requestFocus();
    textEditingController.clear();
    await tester.enterText(find.byKey(fieldKey), 'e');
    await tester.pump();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsOneWidget);
    expect(lastOptions.length, 6);
    expect(lastOptions.elementAt(0), 'chameleon');
    expect(lastOptions.elementAt(1), 'elephant');
    expect(lastOptions.elementAt(2), 'goose');
    expect(lastOptions.elementAt(3), 'lemur');
    expect(lastOptions.elementAt(4), 'mouse');
    expect(lastOptions.elementAt(5), 'northern white rhinoceros');

    // Selection does not wrap (going up).
    await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
    await tester.pump();
    expect(lastHighlighted, 0);
    await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
    await tester.pump();
    expect(lastHighlighted, 0);

    // Selection does not wrap (going down).
    await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
    await tester.pump();
    expect(lastHighlighted, 1);
    await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
    await tester.pump();
    expect(lastHighlighted, 2);
    await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
    await tester.pump();
    expect(lastHighlighted, 3);
    await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
    await tester.pump();
    expect(lastHighlighted, 4);
    await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
    await tester.pump();
    expect(lastHighlighted, 5);
    await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
    await tester.pump();
    expect(lastHighlighted, 5);
  });

  testWidgets('can jump to ends with keyboard', (WidgetTester tester) async {
    final GlobalKey fieldKey = GlobalKey();
    final GlobalKey optionsKey = GlobalKey();
    late Iterable<String> lastOptions;
    late FocusNode focusNode;
    late TextEditingController textEditingController;
    late int lastHighlighted;
    await tester.pumpWidget(
      TestWidgetsApp(
        home: RawAutocomplete<String>(
          optionsBuilder: (TextEditingValue textEditingValue) {
            return kOptions.where((String option) {
              return option.contains(textEditingValue.text.toLowerCase());
            });
          },
          fieldViewBuilder:
              (
                BuildContext context,
                TextEditingController fieldTextEditingController,
                FocusNode fieldFocusNode,
                VoidCallback onFieldSubmitted,
              ) {
                focusNode = fieldFocusNode;
                textEditingController = fieldTextEditingController;
                return TestTextField(
                  key: fieldKey,
                  focusNode: focusNode,
                  controller: textEditingController,
                  onSubmitted: (String value) {
                    onFieldSubmitted();
                  },
                );
              },
          optionsViewBuilder:
              (
                BuildContext context,
                AutocompleteOnSelected<String> onSelected,
                Iterable<String> options,
              ) {
                lastHighlighted = AutocompleteHighlightedOption.of(context);
                lastOptions = options;
                return Container(key: optionsKey);
              },
        ),
      ),
    );

    // Enter text. The options are filtered by the text.
    focusNode.requestFocus();
    textEditingController.clear();
    await tester.enterText(find.byKey(fieldKey), 'e');
    await tester.pump();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsOneWidget);
    expect(lastOptions.length, 6);
    expect(lastOptions.elementAt(0), 'chameleon');
    expect(lastOptions.elementAt(1), 'elephant');
    expect(lastOptions.elementAt(2), 'goose');
    expect(lastOptions.elementAt(3), 'lemur');
    expect(lastOptions.elementAt(4), 'mouse');
    expect(lastOptions.elementAt(5), 'northern white rhinoceros');

    // Jump to the bottom.
    await tester.sendKeyDownEvent(LogicalKeyboardKey.control);
    await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
    await tester.sendKeyUpEvent(LogicalKeyboardKey.control);
    await tester.pump();
    expect(lastHighlighted, 5);

    // Doesn't wrap down.
    await tester.sendKeyDownEvent(LogicalKeyboardKey.control);
    await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
    await tester.sendKeyUpEvent(LogicalKeyboardKey.control);
    await tester.pump();
    expect(lastHighlighted, 5);

    // Jump to the top.
    await tester.sendKeyDownEvent(LogicalKeyboardKey.control);
    await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
    await tester.sendKeyUpEvent(LogicalKeyboardKey.control);
    await tester.pump();
    expect(lastHighlighted, 0);

    // Doesn't wrap up.
    await tester.sendKeyDownEvent(LogicalKeyboardKey.control);
    await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
    await tester.sendKeyUpEvent(LogicalKeyboardKey.control);
    await tester.pump();
    expect(lastHighlighted, 0);
  });

  testWidgets('can navigate with page up/down keys', (WidgetTester tester) async {
    final GlobalKey fieldKey = GlobalKey();
    final GlobalKey optionsKey = GlobalKey();
    late Iterable<String> lastOptions;
    late FocusNode focusNode;
    late TextEditingController textEditingController;
    late int lastHighlighted;
    await tester.pumpWidget(
      TestWidgetsApp(
        home: RawAutocomplete<String>(
          optionsBuilder: (TextEditingValue textEditingValue) {
            return kOptions.where((String option) {
              return option.contains(textEditingValue.text.toLowerCase());
            });
          },
          fieldViewBuilder:
              (
                BuildContext context,
                TextEditingController fieldTextEditingController,
                FocusNode fieldFocusNode,
                VoidCallback onFieldSubmitted,
              ) {
                focusNode = fieldFocusNode;
                textEditingController = fieldTextEditingController;
                return TestTextField(
                  key: fieldKey,
                  focusNode: focusNode,
                  controller: textEditingController,
                  onSubmitted: (String value) {
                    onFieldSubmitted();
                  },
                );
              },
          optionsViewBuilder:
              (
                BuildContext context,
                AutocompleteOnSelected<String> onSelected,
                Iterable<String> options,
              ) {
                lastHighlighted = AutocompleteHighlightedOption.of(context);
                lastOptions = options;
                return Container(key: optionsKey);
              },
        ),
      ),
    );

    // Enter text. The options are filtered by the text.
    focusNode.requestFocus();
    textEditingController.clear();
    await tester.enterText(find.byKey(fieldKey), 'e');
    await tester.pump();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsOneWidget);
    expect(lastOptions.length, 6);
    expect(lastOptions.elementAt(0), 'chameleon');
    expect(lastOptions.elementAt(1), 'elephant');
    expect(lastOptions.elementAt(2), 'goose');
    expect(lastOptions.elementAt(3), 'lemur');
    expect(lastOptions.elementAt(4), 'mouse');
    expect(lastOptions.elementAt(5), 'northern white rhinoceros');

    // Jump down. Stops at the bottom and doesn't wrap.
    await tester.sendKeyEvent(LogicalKeyboardKey.pageDown);
    await tester.pump();
    expect(lastHighlighted, 4);
    await tester.sendKeyEvent(LogicalKeyboardKey.pageDown);
    await tester.pump();
    expect(lastHighlighted, 5);
    await tester.sendKeyEvent(LogicalKeyboardKey.pageDown);
    await tester.pump();
    expect(lastHighlighted, 5);

    // Jump to the bottom and then jump up a page.
    await tester.sendKeyEvent(LogicalKeyboardKey.pageUp);
    await tester.pump();
    expect(lastHighlighted, 1);
    await tester.sendKeyEvent(LogicalKeyboardKey.pageUp);
    await tester.pump();
    expect(lastHighlighted, 0);
    await tester.sendKeyEvent(LogicalKeyboardKey.pageUp);
    await tester.pump();
    expect(lastHighlighted, 0);
  });

  testWidgets('can hide and show options with the keyboard', (WidgetTester tester) async {
    final GlobalKey fieldKey = GlobalKey();
    final GlobalKey optionsKey = GlobalKey();
    late Iterable<String> lastOptions;
    late FocusNode focusNode;
    late TextEditingController textEditingController;
    await tester.pumpWidget(
      TestWidgetsApp(
        home: RawAutocomplete<String>(
          optionsBuilder: (TextEditingValue textEditingValue) {
            return kOptions.where((String option) {
              return option.contains(textEditingValue.text.toLowerCase());
            });
          },
          fieldViewBuilder:
              (
                BuildContext context,
                TextEditingController fieldTextEditingController,
                FocusNode fieldFocusNode,
                VoidCallback onFieldSubmitted,
              ) {
                focusNode = fieldFocusNode;
                textEditingController = fieldTextEditingController;
                return TestTextField(
                  key: fieldKey,
                  focusNode: focusNode,
                  controller: textEditingController,
                  onSubmitted: (String value) {
                    onFieldSubmitted();
                  },
                );
              },
          optionsViewBuilder:
              (
                BuildContext context,
                AutocompleteOnSelected<String> onSelected,
                Iterable<String> options,
              ) {
                lastOptions = options;
                return Container(key: optionsKey);
              },
        ),
      ),
    );

    // Enter text. The options are filtered by the text.
    focusNode.requestFocus();
    await tester.enterText(find.byKey(fieldKey), 'ele');
    await tester.pumpAndSettle();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsOneWidget);
    expect(lastOptions.length, 2);
    expect(lastOptions.elementAt(0), 'chameleon');
    expect(lastOptions.elementAt(1), 'elephant');

    // Hide the options.
    await tester.sendKeyEvent(LogicalKeyboardKey.escape);
    await tester.pump();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsNothing);

    // Show the options again by pressing arrow keys
    await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
    await tester.pump();
    expect(find.byKey(optionsKey), findsOneWidget);
    await tester.sendKeyEvent(LogicalKeyboardKey.escape);
    await tester.pump();
    expect(find.byKey(optionsKey), findsNothing);
    await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
    await tester.pump();
    expect(find.byKey(optionsKey), findsOneWidget);
    await tester.sendKeyEvent(LogicalKeyboardKey.escape);
    await tester.pump();
    expect(find.byKey(optionsKey), findsNothing);

    // Show the options again by re-focusing the field.
    focusNode.unfocus();
    await tester.pump();
    expect(find.byKey(optionsKey), findsNothing);
    focusNode.requestFocus();
    await tester.pump();
    expect(find.byKey(optionsKey), findsOneWidget);
    await tester.sendKeyEvent(LogicalKeyboardKey.escape);
    await tester.pump();
    expect(find.byKey(optionsKey), findsNothing);

    // Show the options again by editing the text (but not when selecting text
    // or moving the caret).
    await tester.enterText(find.byKey(fieldKey), 'elep');
    await tester.pump();
    expect(find.byKey(optionsKey), findsOneWidget);
    await tester.sendKeyEvent(LogicalKeyboardKey.escape);
    await tester.pump();
    expect(find.byKey(optionsKey), findsNothing);
    textEditingController.selection = TextSelection.fromPosition(const TextPosition(offset: 3));
    await tester.pump();
    expect(find.byKey(optionsKey), findsNothing);
  });

  testWidgets('re-invokes DismissIntent if options not shown', (WidgetTester tester) async {
    final GlobalKey fieldKey = GlobalKey();
    final GlobalKey optionsKey = GlobalKey();
    late FocusNode focusNode;
    var wrappingActionInvoked = false;
    await tester.pumpWidget(
      TestWidgetsApp(
        home: Actions(
          actions: <Type, Action<Intent>>{
            DismissIntent: CallbackAction<DismissIntent>(
              onInvoke: (_) => wrappingActionInvoked = true,
            ),
          },
          child: RawAutocomplete<String>(
            optionsBuilder: (TextEditingValue textEditingValue) {
              return kOptions.where((String option) {
                return option.contains(textEditingValue.text.toLowerCase());
              });
            },
            fieldViewBuilder:
                (
                  BuildContext context,
                  TextEditingController fieldTextEditingController,
                  FocusNode fieldFocusNode,
                  VoidCallback onFieldSubmitted,
                ) {
                  focusNode = fieldFocusNode;
                  return TestTextField(
                    key: fieldKey,
                    focusNode: focusNode,
                    controller: fieldTextEditingController,
                    onSubmitted: (String value) {
                      onFieldSubmitted();
                    },
                  );
                },
            optionsViewBuilder:
                (
                  BuildContext context,
                  AutocompleteOnSelected<String> onSelected,
                  Iterable<String> options,
                ) {
                  return Container(key: optionsKey);
                },
          ),
        ),
      ),
    );

    // Enter text to show options.
    focusNode.requestFocus();
    await tester.enterText(find.byKey(fieldKey), 'ele');
    await tester.pumpAndSettle();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsOneWidget);

    // Hide the options.
    await tester.sendKeyEvent(LogicalKeyboardKey.escape);
    await tester.pump();
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsNothing);
    expect(wrappingActionInvoked, false);

    // Ensure the wrapping Actions can receive the DismissIntent.
    await tester.sendKeyEvent(LogicalKeyboardKey.escape);
    expect(wrappingActionInvoked, true);
  });

  testWidgets(
    'optionsViewBuilders can use AutocompleteHighlightedOption to highlight selected option',
    (WidgetTester tester) async {
      final GlobalKey fieldKey = GlobalKey();
      final GlobalKey optionsKey = GlobalKey();
      late Iterable<String> lastOptions;
      late int lastHighlighted;
      late FocusNode focusNode;
      late TextEditingController textEditingController;
      await tester.pumpWidget(
        TestWidgetsApp(
          home: RawAutocomplete<String>(
            optionsBuilder: (TextEditingValue textEditingValue) {
              return kOptions.where((String option) {
                return option.contains(textEditingValue.text.toLowerCase());
              });
            },
            fieldViewBuilder:
                (
                  BuildContext context,
                  TextEditingController fieldTextEditingController,
                  FocusNode fieldFocusNode,
                  VoidCallback onFieldSubmitted,
                ) {
                  focusNode = fieldFocusNode;
                  textEditingController = fieldTextEditingController;
                  return TestTextField(
                    key: fieldKey,
                    focusNode: focusNode,
                    controller: textEditingController,
                    onSubmitted: (String value) {
                      onFieldSubmitted();
                    },
                  );
                },
            optionsViewBuilder:
                (
                  BuildContext context,
                  AutocompleteOnSelected<String> onSelected,
                  Iterable<String> options,
                ) {
                  lastOptions = options;
                  lastHighlighted = AutocompleteHighlightedOption.of(context);
                  return Container(key: optionsKey);
                },
          ),
        ),
      );

      // Enter text. The options are filtered by the text.
      focusNode.requestFocus();
      await tester.enterText(find.byKey(fieldKey), 'e');
      await tester.pump();
      expect(find.byKey(fieldKey), findsOneWidget);
      expect(find.byKey(optionsKey), findsOneWidget);
      expect(lastOptions.length, 6);
      expect(lastOptions.elementAt(0), 'chameleon');
      expect(lastOptions.elementAt(1), 'elephant');
      expect(lastOptions.elementAt(2), 'goose');
      expect(lastOptions.elementAt(3), 'lemur');
      expect(lastOptions.elementAt(4), 'mouse');
      expect(lastOptions.elementAt(5), 'northern white rhinoceros');

      // Move the highlighted option down and check the highlighted index
      expect(lastHighlighted, 0);
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
      await tester.pump();
      expect(lastHighlighted, 1);
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
      await tester.pump();
      expect(lastHighlighted, 2);
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
      await tester.pump();
      expect(lastHighlighted, 3);
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
      await tester.pump();
      expect(lastHighlighted, 4);
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
      await tester.pump();
      expect(lastHighlighted, 5);

      // And move it back up
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
      await tester.pump();
      expect(lastHighlighted, 4);
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
      await tester.pump();
      expect(lastHighlighted, 3);
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
      await tester.pump();
      expect(lastHighlighted, 2);
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
      await tester.pump();
      expect(lastHighlighted, 1);
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
      await tester.pump();
      expect(lastHighlighted, 0);

      // Arrow keys do not wrap.
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
      await tester.pump();
      expect(lastHighlighted, 0);
    },
  );

  testWidgets('floating menu goes away on select', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/99749.
    final GlobalKey fieldKey = GlobalKey();
    final GlobalKey optionsKey = GlobalKey();
    late AutocompleteOnSelected<String> lastOnSelected;

    await tester.pumpWidget(
      TestWidgetsApp(
        home: RawAutocomplete<String>(
          optionsBuilder: (TextEditingValue textEditingValue) {
            return kOptions.where((String option) {
              return option.contains(textEditingValue.text.toLowerCase());
            });
          },
          fieldViewBuilder:
              (
                BuildContext context,
                TextEditingController fieldTextEditingController,
                FocusNode fieldFocusNode,
                VoidCallback onFieldSubmitted,
              ) {
                return TestTextField(
                  key: fieldKey,
                  focusNode: fieldFocusNode,
                  controller: fieldTextEditingController,
                );
              },
          optionsViewBuilder:
              (
                BuildContext context,
                AutocompleteOnSelected<String> onSelected,
                Iterable<String> options,
              ) {
                lastOnSelected = onSelected;
                return Container(key: optionsKey);
              },
        ),
      ),
    );

    // The field is always rendered, but the options are not unless needed.
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsNothing);

    await tester.enterText(find.byKey(fieldKey), kOptions[0]);
    await tester.pumpAndSettle();
    expect(find.byKey(optionsKey), findsOneWidget);

    // Pretend that the only option is selected. This does not change the
    // text in the text field.
    lastOnSelected(kOptions[0]);
    await tester.pump();
    expect(find.byKey(optionsKey), findsNothing);
  });

  testWidgets('options width matches field width after rebuilding', (WidgetTester tester) async {
    final GlobalKey fieldKey = GlobalKey();
    final GlobalKey optionsKey = GlobalKey();
    late StateSetter setState;
    var width = 100.0;

    await tester.pumpWidget(
      TestWidgetsApp(
        home: Align(
          alignment: Alignment.topLeft,
          child: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 32.0),
            child: StatefulBuilder(
              builder: (BuildContext context, StateSetter localStateSetter) {
                setState = localStateSetter;
                return SizedBox(
                  width: width,
                  child: RawAutocomplete<String>(
                    optionsBuilder: (TextEditingValue textEditingValue) {
                      return kOptions.where((String option) {
                        return option.contains(textEditingValue.text.toLowerCase());
                      });
                    },
                    optionsViewBuilder:
                        (
                          BuildContext context,
                          AutocompleteOnSelected<String> onSelected,
                          Iterable<String> options,
                        ) {
                          return Container(key: optionsKey);
                        },
                    fieldViewBuilder:
                        (
                          BuildContext context,
                          TextEditingController textEditingController,
                          FocusNode focusNode,
                          VoidCallback onSubmitted,
                        ) {
                          return TestTextField(
                            key: fieldKey,
                            focusNode: focusNode,
                            controller: textEditingController,
                          );
                        },
                  ),
                );
              },
            ),
          ),
        ),
      ),
    );

    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsNothing);

    final RenderBox fieldBox = tester.renderObject(find.byKey(fieldKey));
    expect(fieldBox.size.width, 100.0);

    await tester.tap(find.byType(TestTextField));
    await tester.pump();

    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsOneWidget);

    final RenderBox optionsBox = tester.renderObject(find.byKey(optionsKey));
    expect(optionsBox.size.width, 100.0);

    setState(() {
      width = 200.0;
    });
    await tester.pump();

    // The options width changes to match the field width.
    expect(fieldBox.size.width, 200.0);
    expect(optionsBox.size.width, 200.0);
  });

  testWidgets('options width matches field width after changing', (WidgetTester tester) async {
    final GlobalKey fieldKey = GlobalKey();
    final GlobalKey optionsKey = GlobalKey();
    late StateSetter setState;
    var width = 100.0;

    final autocomplete = RawAutocomplete<String>(
      optionsBuilder: (TextEditingValue textEditingValue) {
        return kOptions.where((String option) {
          return option.contains(textEditingValue.text.toLowerCase());
        });
      },
      optionsViewBuilder:
          (
            BuildContext context,
            AutocompleteOnSelected<String> onSelected,
            Iterable<String> options,
          ) {
            return Container(key: optionsKey);
          },
      fieldViewBuilder:
          (
            BuildContext context,
            TextEditingController textEditingController,
            FocusNode focusNode,
            VoidCallback onSubmitted,
          ) {
            return StatefulBuilder(
              builder: (BuildContext context, StateSetter localStateSetter) {
                setState = localStateSetter;
                return SizedBox(
                  width: width,
                  child: TestTextField(
                    key: fieldKey,
                    focusNode: focusNode,
                    controller: textEditingController,
                  ),
                );
              },
            );
          },
    );

    await tester.pumpWidget(
      TestWidgetsApp(
        home: Align(
          alignment: Alignment.topLeft,
          child: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 32.0),
            child: autocomplete,
          ),
        ),
      ),
    );

    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsNothing);

    final RenderBox fieldBox = tester.renderObject(find.byKey(fieldKey));
    expect(fieldBox.size.width, 100.0);

    await tester.tap(find.byType(TestTextField));
    await tester.pump();

    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsOneWidget);

    final RenderBox optionsBox = tester.renderObject(find.byKey(optionsKey));
    expect(fieldBox.size.width, 100.0);
    expect(optionsBox.size.width, 100.0);

    setState(() {
      width = 200.0;
    });
    await tester.pump();

    // The options width changes to match the field width.
    expect(fieldBox.size.width, 200.0);
    expect(optionsBox.size.width, 200.0);
  });

  group('screen size', () {
    Future<void> pumpRawAutocomplete(
      WidgetTester tester, {
      GlobalKey? fieldKey,
      GlobalKey? optionsKey,
      OptionsViewOpenDirection optionsViewOpenDirection = OptionsViewOpenDirection.down,
      Alignment alignment = Alignment.topLeft,
    }) {
      return tester.pumpWidget(
        TestWidgetsApp(
          home: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 32.0),
            child: Align(
              alignment: alignment,
              child: RawAutocomplete<String>(
                optionsViewOpenDirection: optionsViewOpenDirection,
                optionsBuilder: (TextEditingValue textEditingValue) {
                  return kOptions.where((String option) {
                    return option.contains(textEditingValue.text.toLowerCase());
                  });
                },
                optionsViewBuilder:
                    (
                      BuildContext context,
                      AutocompleteOnSelected<String> onSelected,
                      Iterable<String> options,
                    ) {
                      return ListView.builder(
                        key: optionsKey,
                        padding: EdgeInsets.zero,
                        shrinkWrap: true,
                        itemCount: options.length,
                        itemBuilder: (BuildContext context, int index) {
                          final String option = options.elementAt(index);
                          return _OptionTile(
                            onTap: () {
                              onSelected(option);
                            },
                            child: Padding(
                              padding: const EdgeInsets.all(16.0),
                              child: Text(option),
                            ),
                          );
                        },
                      );
                    },
                fieldViewBuilder:
                    (
                      BuildContext context,
                      TextEditingController textEditingController,
                      FocusNode focusNode,
                      VoidCallback onSubmitted,
                    ) {
                      return TestTextField(
                        key: fieldKey,
                        focusNode: focusNode,
                        controller: textEditingController,
                      );
                    },
              ),
            ),
          ),
        ),
      );
    }

    testWidgets('options when screen changes landscape to portrait', (WidgetTester tester) async {
      // Start with a portrait-sized window, with enough space for all of the
      // options.
      const wideWindowSize = Size(1920.0, 1080.0);
      tester.view.physicalSize = wideWindowSize;
      tester.view.devicePixelRatio = 1.0;
      addTearDown(tester.view.reset);

      final GlobalKey fieldKey = GlobalKey();
      final GlobalKey optionsKey = GlobalKey();

      await pumpRawAutocomplete(tester, fieldKey: fieldKey, optionsKey: optionsKey);

      expect(find.byKey(fieldKey), findsOneWidget);
      expect(find.byKey(optionsKey), findsNothing);

      await tester.tap(find.byType(TestTextField));
      await tester.pumpAndSettle();

      expect(find.byKey(fieldKey), findsOneWidget);
      expect(find.byKey(optionsKey), findsOneWidget);
      expect(find.byType(_OptionTile), findsNWidgets(kOptions.length));

      final Size fieldSize1 = tester.getSize(find.byKey(fieldKey));
      final Offset optionsTopLeft1 = tester.getTopLeft(find.byKey(optionsKey));
      expect(
        optionsTopLeft1,
        Offset(
          tester.getTopLeft(find.byKey(fieldKey)).dx,
          tester.getTopLeft(find.byKey(fieldKey)).dy + fieldSize1.height,
        ),
      );
      final Offset optionsBottomRight1 = tester.getBottomRight(find.byKey(optionsKey));
      final double optionHeight = tester.getSize(find.byType(_OptionTile).first).height;
      expect(
        optionsBottomRight1,
        Offset(
          tester.getTopLeft(find.byKey(fieldKey)).dx + fieldSize1.width,
          tester.getTopLeft(find.byKey(fieldKey)).dy +
              fieldSize1.height +
              optionHeight * kOptions.length,
        ),
      );

      // Change the screen size to portrait.
      const narrowWindowSize = Size(1070.0, 1770.0);
      tester.view.physicalSize = narrowWindowSize;
      tester.view.devicePixelRatio = 1.0;
      await tester.pumpAndSettle();

      expect(find.byKey(fieldKey), findsOneWidget);
      expect(find.byType(_OptionTile), findsNWidgets(kOptions.length));
      expect(tester.getTopLeft(find.byKey(optionsKey)), optionsTopLeft1);
      final Size fieldSize2 = tester.getSize(find.byKey(fieldKey));
      expect(fieldSize1.width, greaterThan(fieldSize2.width));
      expect(fieldSize1.height, fieldSize2.height);
      final Offset optionsBottomRight2 = tester.getBottomRight(find.byKey(optionsKey));
      final Offset fieldTopLeft2 = tester.getTopLeft(find.byKey(fieldKey));
      expect(optionsBottomRight2.dx, lessThan(optionsBottomRight1.dx));
      expect(optionsBottomRight2.dy, optionsBottomRight1.dy);
      expect(
        optionsBottomRight2,
        Offset(
          fieldTopLeft2.dx + fieldSize2.width,
          fieldTopLeft2.dy + fieldSize2.height + optionHeight * kOptions.length,
        ),
      );
    });

    testWidgets('options when screen changes portrait to landscape and overflows', (
      WidgetTester tester,
    ) async {
      // Start with a portrait-sized window, with enough space for all of the
      // options.
      const narrowWindowSize = Size(1070.0, 1770.0);
      tester.view.physicalSize = narrowWindowSize;
      tester.view.devicePixelRatio = 1.0;
      addTearDown(tester.view.reset);

      final GlobalKey fieldKey = GlobalKey();
      final GlobalKey optionsKey = GlobalKey();

      await pumpRawAutocomplete(tester, fieldKey: fieldKey, optionsKey: optionsKey);

      expect(find.byKey(fieldKey), findsOneWidget);
      expect(find.byKey(optionsKey), findsNothing);

      await tester.tap(find.byType(TestTextField));
      await tester.pumpAndSettle();

      expect(find.byKey(fieldKey), findsOneWidget);
      expect(find.byKey(optionsKey), findsOneWidget);
      expect(find.byType(_OptionTile), findsNWidgets(kOptions.length));

      final Size fieldSize1 = tester.getSize(find.byKey(fieldKey));
      final Offset optionsTopLeft1 = tester.getTopLeft(find.byKey(optionsKey));
      expect(
        optionsTopLeft1,
        Offset(
          tester.getTopLeft(find.byKey(fieldKey)).dx,
          tester.getTopLeft(find.byKey(fieldKey)).dy + fieldSize1.height,
        ),
      );
      final Offset optionsBottomRight1 = tester.getBottomRight(find.byKey(optionsKey));
      final double optionHeight = tester.getSize(find.byType(_OptionTile).first).height;
      expect(
        optionsBottomRight1,
        Offset(
          tester.getTopLeft(find.byKey(fieldKey)).dx + fieldSize1.width,
          tester.getTopLeft(find.byKey(fieldKey)).dy +
              fieldSize1.height +
              optionHeight * kOptions.length,
        ),
      );

      // Change the screen size to landscape where the options can't all fit on
      // the screen.
      const wideWindowSize = Size(1920.0, 580.0);
      tester.view.physicalSize = wideWindowSize;
      tester.view.devicePixelRatio = 1.0;
      await tester.pumpAndSettle();
      expect(find.byKey(fieldKey), findsOneWidget);

      final int visibleOptions = (wideWindowSize.height / optionHeight).floor();
      expect(visibleOptions, lessThan(kOptions.length));
      expect(find.byType(_OptionTile), findsNWidgets(visibleOptions));
      expect(tester.getTopLeft(find.byKey(optionsKey)), optionsTopLeft1);
      final Size fieldSize2 = tester.getSize(find.byKey(fieldKey));
      expect(fieldSize1.width, lessThan(fieldSize2.width));
      expect(fieldSize1.height, fieldSize2.height);
      final Offset optionsBottomRight2 = tester.getBottomRight(find.byKey(optionsKey));
      final Offset fieldTopLeft2 = tester.getTopLeft(find.byKey(fieldKey));
      expect(optionsBottomRight2.dx, greaterThan(optionsBottomRight1.dx));
      expect(optionsBottomRight2.dy, lessThan(optionsBottomRight1.dy));
      expect(
        optionsBottomRight2,
        Offset(
          fieldTopLeft2.dx + fieldSize2.width,
          // Options are taking all available space below the field.
          wideWindowSize.height,
        ),
      );
    });

    testWidgets('screen changes portrait to landscape and overflows', (WidgetTester tester) async {
      // Start with a portrait-sized window, with enough space for all of the
      // options.
      const narrowWindowSize = Size(1070.0, 1770.0);
      tester.view.physicalSize = narrowWindowSize;
      tester.view.devicePixelRatio = 1.0;
      addTearDown(tester.view.reset);

      final GlobalKey fieldKey = GlobalKey();
      final GlobalKey optionsKey = GlobalKey();

      await pumpRawAutocomplete(tester, fieldKey: fieldKey, optionsKey: optionsKey);

      expect(find.byKey(fieldKey), findsOneWidget);
      expect(find.byKey(optionsKey), findsNothing);

      await tester.tap(find.byType(TestTextField));
      await tester.pumpAndSettle();
      expect(find.byKey(fieldKey), findsOneWidget);
      expect(find.byKey(optionsKey), findsOneWidget);

      final double optionHeight = tester.getSize(find.byType(_OptionTile).first).height;
      final double optionsHeight1 = tester.getSize(find.byKey(optionsKey)).height;
      final int visibleOptions1 = (optionsHeight1 / optionHeight).ceil();
      expect(find.byType(_OptionTile), findsNWidgets(visibleOptions1));
      final Size fieldSize1 = tester.getSize(find.byKey(fieldKey));
      final Offset optionsTopLeft1 = tester.getTopLeft(find.byKey(optionsKey));
      final Offset fieldTopLeft1 = tester.getTopLeft(find.byKey(fieldKey));
      expect(optionsTopLeft1, Offset(fieldTopLeft1.dx, fieldTopLeft1.dy + fieldSize1.height));
      final Offset optionsBottomRight1 = tester.getBottomRight(find.byKey(optionsKey));
      expect(
        optionsBottomRight1,
        Offset(
          fieldTopLeft1.dx + fieldSize1.width,
          fieldTopLeft1.dy + fieldSize1.height + optionsHeight1,
        ),
      );

      // Change the screen size to landscape where the options can't all fit on
      // the screen.
      const wideWindowSize = Size(1920.0, 580.0);
      tester.view.physicalSize = wideWindowSize;
      tester.view.devicePixelRatio = 1.0;
      await tester.pumpAndSettle();
      expect(find.byKey(fieldKey), findsOneWidget);

      final double optionsHeight2 = tester.getSize(find.byKey(optionsKey)).height;
      final int visibleOptions2 = (optionsHeight2 / optionHeight).ceil();
      expect(visibleOptions2, lessThan(kOptions.length));
      expect(find.byType(_OptionTile), findsNWidgets(visibleOptions2));
      final Offset optionsTopLeft2 = tester.getTopLeft(find.byKey(optionsKey));
      expect(optionsTopLeft2, optionsTopLeft1);
      final Size fieldSize2 = tester.getSize(find.byKey(fieldKey));
      expect(fieldSize1.width, lessThan(fieldSize2.width));
      expect(fieldSize1.height, fieldSize2.height);
      final Offset optionsBottomRight2 = tester.getBottomRight(find.byKey(optionsKey));
      final Offset fieldTopLeft2 = tester.getTopLeft(find.byKey(fieldKey));
      expect(optionsBottomRight2.dx, greaterThan(optionsBottomRight1.dx));
      expect(
        optionsBottomRight2,
        Offset(
          fieldTopLeft2.dx + fieldSize2.width,
          // Options are taking all available space below the field.
          wideWindowSize.height,
        ),
      );

      // Shrink the screen further so that the options become smaller than
      // _kMinInteractiveDimension and move to overlap the field.
      const shortWindowSize = Size(1920.0, 48.0);
      tester.view.physicalSize = shortWindowSize;
      tester.view.devicePixelRatio = 1.0;
      await tester.pumpAndSettle();
      expect(find.byKey(fieldKey), findsOneWidget);

      const visibleOptions3 = 1;
      expect(find.byType(_OptionTile), findsNWidgets(visibleOptions3));
      final Offset optionsTopLeft3 = tester.getTopLeft(find.byKey(optionsKey));
      expect(optionsTopLeft3.dx, optionsTopLeft1.dx);
      // The options have moved up, overlapping the field, to still be able to
      // show _kMinInteractiveDimension.
      expect(optionsTopLeft3.dy, lessThan(optionsTopLeft1.dy));
      final Size fieldSize3 = tester.getSize(find.byKey(fieldKey));
      final Offset fieldTopLeft3 = tester.getTopLeft(find.byKey(fieldKey));
      expect(optionsTopLeft3.dy, lessThan(fieldTopLeft3.dy + fieldSize3.height));
      expect(fieldSize3.width, fieldSize2.width);
      expect(fieldSize1.height, fieldSize3.height);
      final Offset optionsBottomRight3 = tester.getBottomRight(find.byKey(optionsKey));
      expect(optionsBottomRight3.dx, greaterThan(optionsBottomRight1.dx));
      expect(
        optionsBottomRight3,
        Offset(fieldTopLeft3.dx + fieldSize3.width, shortWindowSize.height),
      );
    });

    testWidgets('when opening up screen changes portrait to landscape and overflows', (
      WidgetTester tester,
    ) async {
      // Start with a portrait-sized window, with enough space for all of the
      // options.
      const narrowWindowSize = Size(1070.0, 1770.0);
      tester.view.physicalSize = narrowWindowSize;
      tester.view.devicePixelRatio = 1.0;
      addTearDown(tester.view.reset);

      final GlobalKey fieldKey = GlobalKey();
      final GlobalKey optionsKey = GlobalKey();

      await pumpRawAutocomplete(
        tester,
        fieldKey: fieldKey,
        optionsKey: optionsKey,
        optionsViewOpenDirection: OptionsViewOpenDirection.up,
        alignment: Alignment.center,
      );

      expect(find.byKey(fieldKey), findsOneWidget);
      expect(find.byKey(optionsKey), findsNothing);

      await tester.tap(find.byType(TestTextField));
      await tester.pumpAndSettle();
      expect(find.byKey(fieldKey), findsOneWidget);
      expect(find.byKey(optionsKey), findsOneWidget);

      final double optionHeight = tester.getSize(find.byType(_OptionTile).first).height;
      final double optionsHeight1 = tester.getSize(find.byKey(optionsKey)).height;
      final int visibleOptions1 = (optionsHeight1 / optionHeight).ceil();
      expect(find.byType(_OptionTile), findsNWidgets(visibleOptions1));
      final Size fieldSize1 = tester.getSize(find.byKey(fieldKey));
      final Offset optionsTopLeft1 = tester.getTopLeft(find.byKey(optionsKey));
      final Offset fieldTopLeft1 = tester.getTopLeft(find.byKey(fieldKey));
      expect(optionsTopLeft1, Offset(fieldTopLeft1.dx, fieldTopLeft1.dy - optionsHeight1));
      expect(optionsTopLeft1.dy, greaterThan(0.0));
      final Offset optionsBottomRight1 = tester.getBottomRight(find.byKey(optionsKey));
      expect(optionsBottomRight1, Offset(fieldTopLeft1.dx + fieldSize1.width, fieldTopLeft1.dy));

      // Change the screen size to landscape where the options can't all fit on
      // the screen.
      const wideWindowSize = Size(1920.0, 580.0);
      tester.view.physicalSize = wideWindowSize;
      tester.view.devicePixelRatio = 1.0;
      await tester.pumpAndSettle();
      expect(find.byKey(fieldKey), findsOneWidget);

      final double optionsHeight2 = tester.getSize(find.byKey(optionsKey)).height;
      expect(optionsHeight2, lessThan(optionsHeight1));
      final int visibleOptions2 = (optionsHeight2 / optionHeight).ceil();
      expect(visibleOptions2, lessThan(visibleOptions1));
      expect(find.byType(_OptionTile), findsNWidgets(visibleOptions2));
      final Offset optionsTopLeft2 = tester.getTopLeft(find.byKey(optionsKey));
      final Offset fieldTopLeft2 = tester.getTopLeft(find.byKey(fieldKey));
      expect(optionsTopLeft2, Offset(optionsTopLeft1.dx, fieldTopLeft2.dy - optionsHeight2));
      final Size fieldSize2 = tester.getSize(find.byKey(fieldKey));
      expect(fieldSize1.width, lessThan(fieldSize2.width));
      expect(fieldSize1.height, fieldSize2.height);
      final Offset optionsBottomRight2 = tester.getBottomRight(find.byKey(optionsKey));
      expect(optionsBottomRight2.dx, greaterThan(optionsBottomRight1.dx));
      expect(optionsBottomRight2, Offset(fieldTopLeft2.dx + fieldSize2.width, fieldTopLeft2.dy));

      // Shrink the screen further so that the options become smaller than
      // _kMinInteractiveDimension and move to overlap the field.
      const shortWindowSize = Size(1920.0, 90.0);
      tester.view.physicalSize = shortWindowSize;
      tester.view.devicePixelRatio = 1.0;
      await tester.pumpAndSettle();

      expect(find.byKey(fieldKey), findsOneWidget);
      const visibleOptions3 = 1;
      expect(find.byType(_OptionTile), findsNWidgets(visibleOptions3));
      final Offset optionsTopLeft3 = tester.getTopLeft(find.byKey(optionsKey));
      expect(optionsTopLeft3.dx, optionsTopLeft1.dx);
      // The options have moved down, overlapping the field, to still be able to
      // show _kMinInteractiveDimension.
      expect(optionsTopLeft3.dy, lessThan(optionsTopLeft1.dy));
      final Size fieldSize3 = tester.getSize(find.byKey(fieldKey));
      final Offset fieldTopLeft3 = tester.getTopLeft(find.byKey(fieldKey));
      expect(optionsTopLeft3.dy, lessThan(fieldTopLeft3.dy + fieldSize3.height));
      expect(fieldSize3.width, fieldSize2.width);
      expect(fieldSize1.height, fieldSize3.height);
      final Offset optionsBottomRight3 = tester.getBottomRight(find.byKey(optionsKey));
      expect(optionsBottomRight3.dx, greaterThan(optionsBottomRight1.dx));
      expect(optionsBottomRight3.dy, greaterThan(fieldTopLeft3.dy));
      expect(optionsBottomRight3.dx, fieldTopLeft3.dx + fieldSize3.width);
    });
  });

  testWidgets(
    'when field scrolled offscreen, options are hidden and not reshown when scrolled back on desktop and web',
    (WidgetTester tester) async {
      final GlobalKey fieldKey = GlobalKey();
      final GlobalKey optionsKey = GlobalKey();
      final scrollController = ScrollController();
      addTearDown(scrollController.dispose);

      await tester.pumpWidget(
        TestWidgetsApp(
          home: ListView(
            controller: scrollController,
            children: <Widget>[
              const SizedBox(height: 1000.0),
              RawAutocomplete<String>(
                optionsBuilder: (TextEditingValue textEditingValue) {
                  return kOptions.where((String option) {
                    return option.contains(textEditingValue.text.toLowerCase());
                  });
                },
                optionsViewBuilder:
                    (
                      BuildContext context,
                      AutocompleteOnSelected<String> onSelected,
                      Iterable<String> options,
                    ) {
                      return ListView.builder(
                        key: optionsKey,
                        padding: EdgeInsets.zero,
                        shrinkWrap: true,
                        itemCount: options.length,
                        itemBuilder: (BuildContext context, int index) {
                          final String option = options.elementAt(index);
                          return _OptionTile(
                            onTap: () {
                              onSelected(option);
                            },
                            child: Padding(
                              padding: const EdgeInsets.all(16.0),
                              child: Text(option),
                            ),
                          );
                        },
                      );
                    },
                fieldViewBuilder:
                    (
                      BuildContext context,
                      TextEditingController textEditingController,
                      FocusNode focusNode,
                      VoidCallback onSubmitted,
                    ) {
                      return TestTextField(
                        key: fieldKey,
                        focusNode: focusNode,
                        controller: textEditingController,
                      );
                    },
              ),
              const SizedBox(height: 1000.0),
            ],
          ),
        ),
      );

      expect(find.byKey(fieldKey), findsNothing);
      expect(find.byKey(optionsKey), findsNothing);

      await tester.scrollUntilVisible(find.byKey(fieldKey), 500.0);
      await tester.pumpAndSettle();

      expect(find.byKey(fieldKey), findsOneWidget);
      expect(find.byKey(optionsKey), findsNothing);

      await tester.tap(find.byKey(fieldKey));
      await tester.pump();

      expect(find.byKey(fieldKey), findsOneWidget);
      expect(find.byKey(optionsKey), findsOneWidget);

      // Jump to the beginning. The field is off screen and the options are not
      // showing either.
      scrollController.jumpTo(0.0);
      await tester.pumpAndSettle();

      expect(find.byKey(fieldKey), findsNothing);
      expect(find.byKey(optionsKey), findsNothing);

      // Scroll back to the field and ensure it is visible.
      await tester.scrollUntilVisible(find.byKey(fieldKey), 500.0);
      await tester.pumpAndSettle();

      // The options are no longer visible on desktop and web.
      expect(find.byKey(fieldKey), findsOneWidget);
      expect(find.byKey(optionsKey), findsNothing);

      // Jump to the end. The field is hidden again.
      scrollController.jumpTo(2000.0);
      await tester.pumpAndSettle();

      expect(find.byKey(fieldKey), findsNothing);
      expect(find.byKey(optionsKey), findsNothing);
    },
    variant: TargetPlatformVariant.desktop(),
  );

  testWidgets(
    'when field scrolled offscreen, options are hidden and reshown when scrolled back on mobile',
    (WidgetTester tester) async {
      final GlobalKey fieldKey = GlobalKey();
      final GlobalKey optionsKey = GlobalKey();
      final scrollController = ScrollController();
      addTearDown(scrollController.dispose);

      await tester.pumpWidget(
        TestWidgetsApp(
          home: ListView(
            controller: scrollController,
            children: <Widget>[
              const SizedBox(height: 1000.0),
              RawAutocomplete<String>(
                optionsBuilder: (TextEditingValue textEditingValue) {
                  return kOptions.where((String option) {
                    return option.contains(textEditingValue.text.toLowerCase());
                  });
                },
                optionsViewBuilder:
                    (
                      BuildContext context,
                      AutocompleteOnSelected<String> onSelected,
                      Iterable<String> options,
                    ) {
                      return ListView.builder(
                        key: optionsKey,
                        padding: EdgeInsets.zero,
                        shrinkWrap: true,
                        itemCount: options.length,
                        itemBuilder: (BuildContext context, int index) {
                          final String option = options.elementAt(index);
                          return _OptionTile(
                            onTap: () {
                              onSelected(option);
                            },
                            child: Padding(
                              padding: const EdgeInsets.all(16.0),
                              child: Text(option),
                            ),
                          );
                        },
                      );
                    },
                fieldViewBuilder:
                    (
                      BuildContext context,
                      TextEditingController textEditingController,
                      FocusNode focusNode,
                      VoidCallback onSubmitted,
                    ) {
                      return TestTextField(
                        key: fieldKey,
                        focusNode: focusNode,
                        controller: textEditingController,
                      );
                    },
              ),
              const SizedBox(height: 1000.0),
            ],
          ),
        ),
      );

      expect(find.byKey(fieldKey), findsNothing);
      expect(find.byKey(optionsKey), findsNothing);

      await tester.scrollUntilVisible(find.byKey(fieldKey), 500.0);
      await tester.pumpAndSettle();

      expect(find.byKey(fieldKey), findsOneWidget);
      expect(find.byKey(optionsKey), findsNothing);

      await tester.tap(find.byKey(fieldKey));
      await tester.pump();

      expect(find.byKey(fieldKey), findsOneWidget);
      expect(find.byKey(optionsKey), findsOneWidget);

      // Jump to the beginning. The field is off screen and the options are not
      // showing either.
      scrollController.jumpTo(0.0);
      await tester.pumpAndSettle();

      expect(find.byKey(fieldKey), findsNothing);
      expect(find.byKey(optionsKey), findsNothing);

      // Scroll back to the field and ensure it is visible.
      await tester.scrollUntilVisible(find.byKey(fieldKey), 500.0);
      await tester.pumpAndSettle();

      // The options remain visible on mobile, but not on web.
      expect(find.byKey(fieldKey), findsOneWidget);
      kIsWeb
          ? expect(find.byKey(optionsKey), findsNothing)
          : expect(find.byKey(optionsKey), findsOneWidget);

      // Jump to the end. The field is hidden again.
      scrollController.jumpTo(2000.0);
      await tester.pumpAndSettle();

      expect(find.byKey(fieldKey), findsNothing);
      expect(find.byKey(optionsKey), findsNothing);
    },
    variant: TargetPlatformVariant.mobile(),
  );

  testWidgets('can prevent older optionsBuilder results from replacing the new ones', (
    WidgetTester tester,
  ) async {
    final GlobalKey fieldKey = GlobalKey();
    final GlobalKey optionsKey = GlobalKey();
    late FocusNode focusNode;
    late TextEditingController textEditingController;
    Iterable<String>? lastOptions;
    Duration? delay;

    await tester.pumpWidget(
      TestWidgetsApp(
        home: RawAutocomplete<String>(
          optionsBuilder: (TextEditingValue textEditingValue) async {
            final Iterable<String> options = kOptions.where((String option) {
              return option.contains(textEditingValue.text.toLowerCase());
            });
            if (delay == null) {
              return options;
            }
            return Future<Iterable<String>>.delayed(delay, () => options);
          },
          fieldViewBuilder:
              (
                BuildContext context,
                TextEditingController fieldTextEditingController,
                FocusNode fieldFocusNode,
                VoidCallback onFieldSubmitted,
              ) {
                focusNode = fieldFocusNode;
                textEditingController = fieldTextEditingController;
                return TestTextField(
                  key: fieldKey,
                  focusNode: focusNode,
                  controller: textEditingController,
                );
              },
          optionsViewBuilder:
              (
                BuildContext context,
                AutocompleteOnSelected<String> onSelected,
                Iterable<String> options,
              ) {
                lastOptions = options;
                return Container(key: optionsKey);
              },
        ),
      ),
    );

    const longRequestDelay = Duration(milliseconds: 5000);
    const shortRequestDelay = Duration(milliseconds: 1000);
    focusNode.requestFocus();

    // Enter the first letter.
    delay = longRequestDelay;
    await tester.enterText(find.byKey(fieldKey), 'c');
    await tester.pump();
    expect(lastOptions, null);

    // Enter the second letter which resolves faster.
    delay = shortRequestDelay;
    await tester.enterText(find.byKey(fieldKey), 'ch');
    await tester.pump();
    expect(lastOptions, null);

    // Wait for the short request to resolve.
    await tester.pump(shortRequestDelay);

    // lastOptions must contain results from the last request.
    expect(find.byKey(optionsKey), findsOneWidget);
    expect(lastOptions, <String>['chameleon']);

    // Wait for the last timer to finish.
    await tester.pump(longRequestDelay - shortRequestDelay);
    expect(lastOptions, <String>['chameleon']);
  });

  testWidgets('updates result only from the last call made to optionsBuilder', (
    WidgetTester tester,
  ) async {
    final GlobalKey fieldKey = GlobalKey();
    final GlobalKey optionsKey = GlobalKey();
    late FocusNode focusNode;
    late TextEditingController textEditingController;
    Iterable<String>? lastOptions;
    Duration? delay;

    await tester.pumpWidget(
      TestWidgetsApp(
        home: RawAutocomplete<String>(
          optionsBuilder: (TextEditingValue textEditingValue) async {
            final Iterable<String> options = kOptions.where((String option) {
              return option.contains(textEditingValue.text.toLowerCase());
            });
            if (delay == null) {
              return options;
            }
            return Future<Iterable<String>>.delayed(delay, () => options);
          },
          fieldViewBuilder:
              (
                BuildContext context,
                TextEditingController fieldTextEditingController,
                FocusNode fieldFocusNode,
                VoidCallback onFieldSubmitted,
              ) {
                focusNode = fieldFocusNode;
                textEditingController = fieldTextEditingController;
                return TestTextField(
                  key: fieldKey,
                  focusNode: focusNode,
                  controller: textEditingController,
                );
              },
          optionsViewBuilder:
              (
                BuildContext context,
                AutocompleteOnSelected<String> onSelected,
                Iterable<String> options,
              ) {
                lastOptions = options;
                return Container(key: optionsKey);
              },
        ),
      ),
    );

    focusNode.requestFocus();
    const firstRequestDelay = Duration(milliseconds: 1000);
    const secondRequestDelay = Duration(milliseconds: 2000);
    const thirdRequestDelay = Duration(milliseconds: 3000);

    // Enter the first letter.
    delay = firstRequestDelay;
    await tester.enterText(find.byKey(fieldKey), 'l');
    await tester.pump();
    expect(lastOptions, null);

    // Enter the second letter which resolves slower.
    delay = secondRequestDelay;
    await tester.enterText(find.byKey(fieldKey), 'le');
    await tester.pump();
    expect(lastOptions, null);

    // Enter the third letter which resolves the slowest.
    delay = thirdRequestDelay;
    await tester.enterText(find.byKey(fieldKey), 'lem');
    await tester.pump();
    expect(lastOptions, null);

    // lastOptions should get updated only from the last request.
    await tester.pump(firstRequestDelay);
    expect(find.byKey(optionsKey), findsNothing);
    expect(lastOptions, null);

    await tester.pump(secondRequestDelay - firstRequestDelay);
    expect(find.byKey(optionsKey), findsNothing);
    expect(lastOptions, null);

    await tester.pump(thirdRequestDelay - secondRequestDelay);
    expect(find.byKey(optionsKey), findsOneWidget);
    expect(lastOptions, <String>['lemur']);
  });

  testWidgets('update options view when field input changes return to the starting keyword', (
    WidgetTester tester,
  ) async {
    final GlobalKey fieldKey = GlobalKey();
    final GlobalKey optionsKey = GlobalKey();
    late FocusNode focusNode;
    late TextEditingController textEditingController;
    Iterable<String>? lastOptions;
    const delay = Duration(milliseconds: 100);

    await tester.pumpWidget(
      TestWidgetsApp(
        home: RawAutocomplete<String>(
          optionsBuilder: (TextEditingValue textEditingValue) async {
            final Iterable<String> options = kOptions.where((String option) {
              return option.contains(textEditingValue.text.toLowerCase());
            });
            return Future<Iterable<String>>.delayed(delay, () => options);
          },
          fieldViewBuilder:
              (
                BuildContext context,
                TextEditingController fieldTextEditingController,
                FocusNode fieldFocusNode,
                VoidCallback onFieldSubmitted,
              ) {
                focusNode = fieldFocusNode;
                textEditingController = fieldTextEditingController;
                return TestTextField(
                  key: fieldKey,
                  focusNode: focusNode,
                  controller: textEditingController,
                );
              },
          optionsViewBuilder:
              (
                BuildContext context,
                AutocompleteOnSelected<String> onSelected,
                Iterable<String> options,
              ) {
                lastOptions = options;
                return Container(key: optionsKey);
              },
        ),
      ),
    );

    // Setup starting point.
    await tester.enterText(find.byKey(fieldKey), 'ele');
    await tester.pump(delay);
    expect(lastOptions, <String>['chameleon', 'elephant']);
    expect(find.byKey(optionsKey), findsOneWidget);

    // Hide options.
    await tester.sendKeyEvent(LogicalKeyboardKey.escape);
    await tester.pump();
    expect(find.byKey(optionsKey), findsNothing);

    // Enter another letter and then immediately erase it.
    await tester.enterText(find.byKey(fieldKey), 'eleo');
    await tester.pump();
    expect(find.byKey(optionsKey), findsNothing);

    await tester.enterText(find.byKey(fieldKey), 'ele');
    await tester.pump(delay);
    expect(lastOptions, <String>['chameleon', 'elephant']);

    // Options dropdown should be visible after the last optionsBuilder
    // call is resolved.
    expect(find.byKey(optionsKey), findsOneWidget);
  });

  testWidgets('optionsBuilder does not have to be a pure function', (WidgetTester tester) async {
    final GlobalKey fieldKey = GlobalKey();
    final GlobalKey optionsKey = GlobalKey();
    late FocusNode focusNode;
    late TextEditingController textEditingController;
    Iterable<String>? lastOptions;
    const delay = Duration(milliseconds: 100);

    // This is used to tell optionsBuilder to return something different after
    // being called with "ele" the second time. I.e. it is not a pure function.
    var timesOptionsBuilderCalledWithEle = 0;
    final Iterable<String> altEleOptions = <String>['something new and crazy for ele!'];

    await tester.pumpWidget(
      TestWidgetsApp(
        home: RawAutocomplete<String>(
          optionsBuilder: (TextEditingValue textEditingValue) async {
            if (textEditingValue.text == 'ele') {
              timesOptionsBuilderCalledWithEle += 1;
              if (timesOptionsBuilderCalledWithEle > 1) {
                return Future<Iterable<String>>.delayed(delay, () => altEleOptions);
              }
            }
            final Iterable<String> options = kOptions.where((String option) {
              return option.contains(textEditingValue.text.toLowerCase());
            });
            return Future<Iterable<String>>.delayed(delay, () => options);
          },
          fieldViewBuilder:
              (
                BuildContext context,
                TextEditingController fieldTextEditingController,
                FocusNode fieldFocusNode,
                VoidCallback onFieldSubmitted,
              ) {
                focusNode = fieldFocusNode;
                textEditingController = fieldTextEditingController;
                return TestTextField(
                  key: fieldKey,
                  focusNode: focusNode,
                  controller: textEditingController,
                );
              },
          optionsViewBuilder:
              (
                BuildContext context,
                AutocompleteOnSelected<String> onSelected,
                Iterable<String> options,
              ) {
                lastOptions = options;
                return Container(key: optionsKey);
              },
        ),
      ),
    );

    await tester.enterText(find.byKey(fieldKey), 'ele');
    await tester.pump(delay);
    expect(lastOptions, <String>['chameleon', 'elephant']);
    expect(find.byKey(optionsKey), findsOneWidget);

    await tester.sendKeyEvent(LogicalKeyboardKey.escape);
    await tester.pump();
    expect(find.byKey(optionsKey), findsNothing);

    await tester.enterText(find.byKey(fieldKey), 'eleo');
    await tester.pump();
    expect(find.byKey(optionsKey), findsNothing);

    await tester.enterText(find.byKey(fieldKey), 'ele');
    await tester.pump(delay);
    expect(lastOptions, altEleOptions);
    expect(find.byKey(optionsKey), findsOneWidget);
  });

  testWidgets('Autocomplete Semantics announcement', (WidgetTester tester) async {
    final SemanticsHandle handle = tester.ensureSemantics();
    final GlobalKey fieldKey = GlobalKey();
    final GlobalKey optionsKey = GlobalKey();
    late Iterable<String> lastOptions;
    late FocusNode focusNode;
    late TextEditingController textEditingController;
    const localizations = DefaultWidgetsLocalizations();

    await tester.pumpWidget(
      TestWidgetsApp(
        home: RawAutocomplete<String>(
          optionsBuilder: (TextEditingValue textEditingValue) {
            return kOptions.where((String option) {
              return option.contains(textEditingValue.text.toLowerCase());
            });
          },
          fieldViewBuilder:
              (
                BuildContext context,
                TextEditingController fieldTextEditingController,
                FocusNode fieldFocusNode,
                VoidCallback onFieldSubmitted,
              ) {
                focusNode = fieldFocusNode;
                textEditingController = fieldTextEditingController;
                return TestTextField(
                  key: fieldKey,
                  focusNode: focusNode,
                  controller: textEditingController,
                );
              },
          optionsViewBuilder:
              (
                BuildContext context,
                AutocompleteOnSelected<String> onSelected,
                Iterable<String> options,
              ) {
                lastOptions = options;
                return Container(key: optionsKey);
              },
        ),
      ),
    );

    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byKey(optionsKey), findsNothing);

    expect(tester.takeAnnouncements(), isEmpty);

    focusNode.requestFocus();
    await tester.pump();
    expect(find.byKey(optionsKey), findsOneWidget);
    expect(lastOptions.length, kOptions.length);
    expect(
      tester.takeAnnouncements().first,
      isAccessibilityAnnouncement(localizations.searchResultsFound),
    );

    await tester.enterText(find.byKey(fieldKey), 'a');
    await tester.pump();
    expect(find.byKey(optionsKey), findsOneWidget);
    expect(lastOptions.length, greaterThan(0));
    expect(tester.takeAnnouncements(), isEmpty);

    await tester.enterText(find.byKey(fieldKey), 'zzzz');
    await tester.pump();
    expect(find.byKey(optionsKey), findsNothing);
    expect(
      tester.takeAnnouncements().first,
      isAccessibilityAnnouncement(localizations.noResultsFound),
    );

    handle.dispose();
  });

  testWidgets('Autocomplete reports error when SemanticsService.sendAnnouncement fails', (
    WidgetTester tester,
  ) async {
    debugDefaultTargetPlatformOverride = TargetPlatform.macOS;
    try {
      final SemanticsHandle handle = tester.ensureSemantics();
      final GlobalKey fieldKey = GlobalKey();
      final GlobalKey optionsKey = GlobalKey();
      late FocusNode focusNode;
      late TextEditingController textEditingController;
      final errors = <FlutterErrorDetails>[];
      final void Function(FlutterErrorDetails)? originalOnError = FlutterError.onError;
      FlutterError.onError = (FlutterErrorDetails details) {
        final String contextStr = details.context?.toString() ?? '';
        if (contextStr.contains('while sending semantics announcement')) {
          errors.add(details);
          return;
        }
        originalOnError?.call(details);
      };
      addTearDown(() {
        FlutterError.onError = originalOnError;
        TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMessageHandler(
          SystemChannels.accessibility.name,
          null,
        );
      });

      TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMessageHandler(
        SystemChannels.accessibility.name,
        (ByteData? message) async {
          const codec = StandardMessageCodec();
          final Object? decoded = codec.decodeMessage(message);
          if (decoded is Map && decoded['type'] == 'announce') {
            final data = ByteData(1);
            data.setUint8(0, 255); // Invalid type byte
            return data;
          }
          return null; // Success for other events
        },
      );

      final entry = OverlayEntry(
        builder: (BuildContext context) {
          return RawAutocomplete<String>(
            optionsBuilder: (TextEditingValue textEditingValue) {
              return kOptions.where((String option) {
                return option.contains(textEditingValue.text.toLowerCase());
              });
            },
            fieldViewBuilder:
                (
                  BuildContext context,
                  TextEditingController fieldTextEditingController,
                  FocusNode fieldFocusNode,
                  VoidCallback onFieldSubmitted,
                ) {
                  focusNode = fieldFocusNode;
                  textEditingController = fieldTextEditingController;
                  return TestTextField(
                    key: fieldKey,
                    focusNode: focusNode,
                    controller: textEditingController,
                  );
                },
            optionsViewBuilder:
                (
                  BuildContext context,
                  AutocompleteOnSelected<String> onSelected,
                  Iterable<String> options,
                ) {
                  return Container(key: optionsKey);
                },
          );
        },
      );
      addTearDown(() {
        entry.remove();
        entry.dispose();
      });

      await tester.pumpWidget(
        Localizations(
          locale: const Locale('en', 'US'),
          delegates: const <LocalizationsDelegate<dynamic>>[DefaultWidgetsLocalizations.delegate],
          child: Directionality(
            textDirection: TextDirection.ltr,
            child: Overlay(initialEntries: <OverlayEntry>[entry]),
          ),
        ),
      );

      focusNode.requestFocus();
      await tester.pump();

      expect(errors, isNotEmpty);
      final bool hasAnnouncementError = errors.any(
        (e) =>
            e.exception.toString().contains('FormatException') &&
            e.context.toString().contains('while sending semantics announcement'),
      );
      expect(hasAnnouncementError, isTrue);

      handle.dispose();
    } finally {
      debugDefaultTargetPlatformOverride = null;
    }
  });

  testWidgets('Autocomplete Semantics announce in multi-view', (WidgetTester tester) async {
    final SemanticsHandle handle = tester.ensureSemantics();
    final GlobalKey optionsKey = GlobalKey();
    late Iterable<String> lastOptions;
    late FocusNode focusNode;
    late TextEditingController textEditingController;
    const localizations = DefaultWidgetsLocalizations();
    const viewId = 1;

    await tester.pumpWidget(
      ViewAnchor(
        view: View(
          view: FakeView(tester.view, viewId: viewId),
          child: TestWidgetsApp(
            home: RawAutocomplete<String>(
              optionsBuilder: (TextEditingValue textEditingValue) {
                return kOptions.where((String option) {
                  return option.contains(textEditingValue.text.toLowerCase());
                });
              },
              fieldViewBuilder:
                  (
                    BuildContext context,
                    TextEditingController fieldTextEditingController,
                    FocusNode fieldFocusNode,
                    VoidCallback onFieldSubmitted,
                  ) {
                    focusNode = fieldFocusNode;
                    textEditingController = fieldTextEditingController;
                    return TestTextField(focusNode: focusNode, controller: textEditingController);
                  },
              optionsViewBuilder:
                  (
                    BuildContext context,
                    AutocompleteOnSelected<String> onSelected,
                    Iterable<String> options,
                  ) {
                    lastOptions = options;
                    return Container(key: optionsKey);
                  },
            ),
          ),
        ),
        child: const SizedBox(),
      ),
    );

    expect(find.byKey(optionsKey), findsNothing);

    expect(tester.takeAnnouncements(), isEmpty);

    focusNode.requestFocus();
    await tester.pump();
    expect(find.byKey(optionsKey), findsOneWidget);
    expect(lastOptions.length, kOptions.length);
    expect(
      tester.takeAnnouncements().first,
      isAccessibilityAnnouncement(localizations.searchResultsFound, viewId: viewId),
    );

    handle.dispose();
  });

  testWidgets('RawAutocomplete renders at zero area', (WidgetTester tester) async {
    await tester.pumpWidget(
      TestWidgetsApp(
        home: Center(
          child: SizedBox.shrink(
            child: RawAutocomplete<String>(
              initialValue: const TextEditingValue(text: 'X'),
              optionsBuilder: (TextEditingValue textEditingValue) => <String>['Y'],
              fieldViewBuilder:
                  (
                    BuildContext context,
                    TextEditingController textEditingController,
                    FocusNode focusNode,
                    VoidCallback voidCallBack,
                  ) => TestTextField(controller: textEditingController),
              optionsViewBuilder:
                  (
                    BuildContext context,
                    AutocompleteOnSelected<String> onSelected,
                    Iterable<String> options,
                  ) => Container(),
            ),
          ),
        ),
      ),
    );
    final Finder xText = find.text('X');
    expect(tester.getSize(xText).isEmpty, isTrue);
  });

  testWidgets(
    'floating menu is displayed when the field is focused and already has a selected value',
    (WidgetTester tester) async {
      // Regression test for https://github.com/flutter/flutter/issues/177429.
      const fieldKey = Key('field');
      const optionsKey = Key('options');
      late AutocompleteOnSelected<String> lastOnSelected;
      late FocusNode focusNode;

      await tester.pumpWidget(
        TestWidgetsApp(
          home: RawAutocomplete<String>(
            optionsBuilder: (TextEditingValue textEditingValue) {
              return kOptions.where((String option) {
                return option.contains(textEditingValue.text.toLowerCase());
              });
            },
            fieldViewBuilder:
                (
                  BuildContext context,
                  TextEditingController fieldTextEditingController,
                  FocusNode fieldFocusNode,
                  VoidCallback onFieldSubmitted,
                ) {
                  focusNode = fieldFocusNode;
                  return TestTextField(
                    key: fieldKey,
                    focusNode: fieldFocusNode,
                    controller: fieldTextEditingController,
                  );
                },
            optionsViewBuilder:
                (
                  BuildContext context,
                  AutocompleteOnSelected<String> onSelected,
                  Iterable<String> options,
                ) {
                  lastOnSelected = onSelected;
                  return Container(key: optionsKey);
                },
          ),
        ),
      );

      // The field is always rendered, but the options are not unless needed.
      expect(find.byKey(fieldKey), findsOne);
      expect(find.byKey(optionsKey), findsNothing);

      await tester.enterText(find.byKey(fieldKey), kOptions[0]);
      await tester.pumpAndSettle();
      expect(find.byKey(optionsKey), findsOne);

      lastOnSelected(kOptions[0]);
      await tester.pump();
      expect(find.byKey(optionsKey), findsNothing);

      focusNode.unfocus();
      await tester.pump();
      focusNode.requestFocus();
      await tester.pumpAndSettle();

      expect(find.byKey(optionsKey), findsOne);
    },
  );

  // Regression test for https://github.com/flutter/flutter/issues/170403.
  testWidgets('does not crash when disposed during async optionsBuilder', (
    WidgetTester tester,
  ) async {
    final optionsCompleter = Completer<List<String>>();
    late StateSetter setState;
    var showAutocomplete = true;

    await tester.pumpWidget(
      TestWidgetsApp(
        home: StatefulBuilder(
          builder: (BuildContext context, StateSetter innerSetState) {
            setState = innerSetState;
            if (!showAutocomplete) {
              return const SizedBox.shrink();
            }
            return RawAutocomplete<String>(
              optionsBuilder: (TextEditingValue textEditingValue) async {
                return optionsCompleter.future;
              },
              fieldViewBuilder:
                  (
                    BuildContext context,
                    TextEditingController fieldTextEditingController,
                    FocusNode fieldFocusNode,
                    VoidCallback onFieldSubmitted,
                  ) {
                    return TestTextField(
                      focusNode: fieldFocusNode,
                      controller: fieldTextEditingController,
                    );
                  },
              optionsViewBuilder:
                  (
                    BuildContext context,
                    AutocompleteOnSelected<String> onSelected,
                    Iterable<String> options,
                  ) {
                    return Container();
                  },
            );
          },
        ),
      ),
    );

    // Focus the field to trigger optionsBuilder.
    await tester.tap(find.byType(TestTextField));
    await tester.pump();

    // Dispose the widget while optionsBuilder is still pending.
    setState(() {
      showAutocomplete = false;
    });
    await tester.pump();

    optionsCompleter.complete(<String>['option1', 'option2']);
    await tester.pump();

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

  testWidgets('Options view is constrained by MediaQuery bottom padding and view insets', (
    WidgetTester tester,
  ) async {
    const padding = 50.0;
    const bottomInsets = 70.0;
    tester.view.devicePixelRatio = 1.0;
    addTearDown(tester.view.reset);
    await tester.pumpWidget(
      TestWidgetsApp(
        home: Column(
          children: <Widget>[
            const SizedBox(height: 200),
            RawAutocomplete<String>(
              optionsBuilder: (TextEditingValue textEditingValue) => <String>['abcd'],
              fieldViewBuilder:
                  (
                    BuildContext context,
                    TextEditingController textEditingController,
                    FocusNode focusNode,
                    VoidCallback onFieldSubmitted,
                  ) {
                    return TestTextField(controller: textEditingController, focusNode: focusNode);
                  },
              optionsViewBuilder:
                  (
                    BuildContext context,
                    AutocompleteOnSelected<String> onSelected,
                    Iterable<String> options,
                  ) => const Placeholder(),
            ),
            const SizedBox(height: 200),
          ],
        ),
      ),
    );

    await tester.tap(find.byType(TestTextField));
    await tester.enterText(find.byType(TestTextField), 'a');
    await tester.pump();

    final double initialSize = tester.getSize(find.byType(Placeholder)).height;
    tester.view.padding = const FakeViewPadding(bottom: padding);
    await tester.pump();

    // The options view has shrunk to the available height.
    expect(tester.view.padding.bottom, padding);
    expect(tester.getSize(find.byType(Placeholder)).height, closeTo(initialSize - padding, 0.1));

    tester.view.viewInsets = const FakeViewPadding(bottom: bottomInsets);
    await tester.pump();

    // The options view has shrunk to the available height.
    expect(tester.view.padding.bottom, padding);
    expect(tester.view.viewInsets.bottom, bottomInsets);

    await tester.tap(find.byType(TestTextField));
    await tester.enterText(find.byType(TestTextField), 'abc');
    await tester.pump();

    // The options view has shrunk to the available height.
    expect(
      tester.getSize(find.byType(Placeholder)).height,
      closeTo(initialSize - bottomInsets - padding, 0.1),
    );
  });

  testWidgets('Options view is constrained by MediaQuery top padding', (WidgetTester tester) async {
    const padding = 100.0;
    tester.view.devicePixelRatio = 1.0;
    addTearDown(tester.view.reset);
    await tester.pumpWidget(
      TestWidgetsApp(
        home: Column(
          children: <Widget>[
            const SizedBox(height: 200),
            RawAutocomplete<String>(
              optionsViewOpenDirection: OptionsViewOpenDirection.up,
              optionsBuilder: (TextEditingValue textEditingValue) => <String>['abcd'],
              fieldViewBuilder:
                  (
                    BuildContext context,
                    TextEditingController textEditingController,
                    FocusNode focusNode,
                    VoidCallback onFieldSubmitted,
                  ) {
                    return TestTextField(controller: textEditingController, focusNode: focusNode);
                  },
              optionsViewBuilder:
                  (
                    BuildContext context,
                    AutocompleteOnSelected<String> onSelected,
                    Iterable<String> options,
                  ) => const Placeholder(),
            ),
            const SizedBox(height: 200),
          ],
        ),
      ),
    );

    await tester.tap(find.byType(TestTextField));
    await tester.enterText(find.byType(TestTextField), 'a');
    await tester.pump();

    final double initialSize = tester.getSize(find.byType(Placeholder)).height;
    tester.view.padding = const FakeViewPadding(top: padding);
    await tester.pump();

    // The options view has shrunk to the available height.
    expect(tester.getSize(find.byType(Placeholder)).height, closeTo(initialSize - padding, 0.1));
  });

  testWidgets('RawAutocomplete does not crash when hiding non-displayed overlay', (
    WidgetTester tester,
  ) async {
    final controller = TextEditingController();
    final focusNode = FocusNode();

    addTearDown(controller.dispose);
    addTearDown(focusNode.dispose);

    await tester.pumpWidget(
      TestWidgetsApp(
        home: RawAutocomplete<String>(
          key: const ValueKey('initial'),
          textEditingController: controller,
          focusNode: focusNode,
          optionsBuilder: (TextEditingValue value) => [],
          fieldViewBuilder: (context, ctrl, node, onFieldSubmitted) {
            return TestTextField(controller: ctrl, focusNode: node);
          },
          optionsViewBuilder: (context, onSelected, options) => const SizedBox(),
        ),
      ),
    );

    // Change the key to force the RawAutocomplete to dispose and re-initialize.
    await tester.pumpWidget(
      TestWidgetsApp(
        home: RawAutocomplete<String>(
          key: const ValueKey('new-key'),
          textEditingController: controller,
          focusNode: focusNode,
          optionsBuilder: (TextEditingValue value) => [],
          fieldViewBuilder: (context, ctrl, node, onFieldSubmitted) {
            return TestTextField(controller: ctrl, focusNode: node);
          },
          optionsViewBuilder: (context, onSelected, options) => const SizedBox(),
        ),
      ),
    );

    await tester.enterText(find.byType(TestTextField), 'trigger');
    await tester.pump();

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

  testWidgets('Same option in RawAutocomplete should be selectable again after text is cleared', (
    WidgetTester tester,
  ) async {
    final textCtrl = TextEditingController();
    addTearDown(textCtrl.dispose);
    final textFocus = FocusNode();
    addTearDown(textFocus.dispose);
    final listItem = <String>['test', 'abc', 'dexter'];

    await tester.pumpWidget(
      TestWidgetsApp(
        home: Row(
          children: <Widget>[
            Expanded(
              child: RawAutocomplete<String>(
                textEditingController: textCtrl,
                focusNode: textFocus,
                optionsBuilder: (TextEditingValue textEditingValue) {
                  return listItem.where((String e) => e.contains(textEditingValue.text));
                },
                fieldViewBuilder:
                    (
                      BuildContext context,
                      TextEditingController textEditingController,
                      FocusNode focusNode,
                      VoidCallback onFieldSubmitted,
                    ) {
                      return TestTextField(controller: textEditingController, focusNode: focusNode);
                    },
                optionsViewBuilder:
                    (
                      BuildContext context,
                      AutocompleteOnSelected<String> onSelected,
                      Iterable<String> options,
                    ) {
                      return ListView.builder(
                        itemCount: options.length,
                        itemBuilder: (BuildContext context, int index) {
                          final String option = options.elementAt(index);
                          return GestureDetector(
                            onTap: () => onSelected(option),
                            child: Text(option),
                          );
                        },
                      );
                    },
              ),
            ),
            GestureDetector(
              onTap: () {
                textCtrl.clear();
              },
              child: const Text('Clear'),
            ),
          ],
        ),
      ),
    );

    // Open the popup menu.
    await tester.enterText(find.byType(TestTextField), '');
    await tester.pumpAndSettle();
    expect(find.text('test'), findsOneWidget);

    // Select option 'test'
    await tester.tap(find.text('test'));
    await tester.pumpAndSettle();
    expect(textCtrl.text, 'test');

    // Clear text
    await tester.tap(find.text('Clear'));
    textFocus.unfocus();
    await tester.pumpAndSettle();
    expect(textCtrl.text, '');

    // Select 'test' again
    await tester.tap(find.byType(TestTextField));
    await tester.pumpAndSettle();
    expect(find.text('test'), findsWidgets);
    await tester.tap(find.text('test').last);
    await tester.pumpAndSettle();

    // The text field should be updated to 'test'.
    expect(textCtrl.text, 'test');
  });

  testWidgets(
    'TAB from field skips the options overlay and advances to the next focusable sibling',
    (WidgetTester tester) async {
      // Regression test for https://github.com/flutter/flutter/issues/183456.
      final targetFocus = FocusNode(debugLabel: 'target');
      addTearDown(targetFocus.dispose);

      await tester.pumpWidget(
        TestWidgetsApp(
          home: Column(
            children: <Widget>[
              RawAutocomplete<String>(
                optionsBuilder: (TextEditingValue value) =>
                    kOptions.where((String option) => option.contains(value.text.toLowerCase())),
                fieldViewBuilder:
                    (
                      BuildContext context,
                      TextEditingController textEditingController,
                      FocusNode focusNode,
                      VoidCallback onFieldSubmitted,
                    ) => TestTextField(controller: textEditingController, focusNode: focusNode),
                optionsViewBuilder:
                    (
                      BuildContext context,
                      AutocompleteOnSelected<String> onSelected,
                      Iterable<String> options,
                    ) => ListView.builder(
                      shrinkWrap: true,
                      itemCount: options.length,
                      itemBuilder: (BuildContext context, int index) {
                        final String option = options.elementAt(index);
                        return GestureDetector(
                          onTap: () => onSelected(option),
                          child: Focus(child: Text(option)),
                        );
                      },
                    ),
              ),
              const ExcludeFocus(child: TestTextField()),
              TestTextField(focusNode: targetFocus),
            ],
          ),
        ),
      );

      // Focus the autocomplete field by tapping it, then TAB.
      await tester.tap(find.byType(TestTextField).first);
      await tester.pumpAndSettle();
      await tester.sendKeyEvent(LogicalKeyboardKey.tab);
      await tester.pumpAndSettle();

      expect(targetFocus.hasFocus, isTrue);
    },
  );
}

/// A simple tappable widget used as a replacement for [InkWell] in tests.
///
/// This provides the same tap handling behavior without requiring a [Material]
/// ancestor, and a minimum height matching [_kMinInteractiveDimension] to
/// preserve sizing behavior in layout-sensitive tests.
class _OptionTile extends StatelessWidget {
  const _OptionTile({required this.onTap, required this.child});

  final VoidCallback onTap;
  final Widget child;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTap,
      child: ConstrainedBox(constraints: const BoxConstraints(minHeight: 48.0), child: child),
    );
  }
}
