// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';

import '../widgets/semantics_tester.dart';

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 {
    late String lastSelection;
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: Autocomplete<String>(
            onSelected: (String selection) {
              lastSelection = selection;
            },
            optionsBuilder: (TextEditingValue textEditingValue) {
              return kOptions.where((String option) {
                return option.contains(textEditingValue.text.toLowerCase());
              });
            },
          ),
        ),
      ),
    );

    // The field is always rendered, but the options are not unless needed.
    expect(find.byType(TextFormField), findsOneWidget);
    expect(find.byType(ListView), findsNothing);

    // Focus the empty field. All the options are displayed.
    await tester.tap(find.byType(TextFormField));
    await tester.pump();
    expect(find.byType(ListView), findsOneWidget);
    var list = find.byType(ListView).evaluate().first.widget as ListView;
    expect(list.semanticChildCount, kOptions.length);

    // Enter text. The options are filtered by the text.
    await tester.enterText(find.byType(TextFormField), 'ele');
    await tester.pump();
    expect(find.byType(TextFormField), findsOneWidget);
    expect(find.byType(ListView), findsOneWidget);
    list = find.byType(ListView).evaluate().first.widget as ListView;
    // 'chameleon' and 'elephant' are displayed.
    expect(list.semanticChildCount, 2);

    // Select a option. The options hide and the field updates to show the
    // selection.
    await tester.tap(find.byType(InkWell).first);
    await tester.pump();
    expect(find.byType(TextFormField), findsOneWidget);
    expect(find.byType(ListView), findsNothing);
    final field = find.byType(TextFormField).evaluate().first.widget as TextFormField;
    expect(field.controller!.text, 'chameleon');
    expect(lastSelection, 'chameleon');

    // Modify the field text. The options appear again and are filtered.
    await tester.enterText(find.byType(TextFormField), 'e');
    await tester.pump();
    expect(find.byType(TextFormField), findsOneWidget);
    expect(find.byType(ListView), findsOneWidget);
    list = find.byType(ListView).evaluate().first.widget as ListView;
    // 'chameleon', 'elephant', 'goose', 'lemur', 'mouse', and
    // 'northern white rhinoceros' are displayed.
    expect(list.semanticChildCount, 6);
  });

  testWidgets('can filter and select a list of custom User options', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: Autocomplete<User>(
            optionsBuilder: (TextEditingValue textEditingValue) {
              return kOptionsUsers.where((User option) {
                return option.toString().contains(textEditingValue.text.toLowerCase());
              });
            },
          ),
        ),
      ),
    );

    // The field is always rendered, but the options are not unless needed.
    expect(find.byType(TextFormField), findsOneWidget);
    expect(find.byType(ListView), findsNothing);

    // Focus the empty field. All the options are displayed.
    await tester.tap(find.byType(TextFormField));
    await tester.pump();
    expect(find.byType(ListView), findsOneWidget);
    var list = find.byType(ListView).evaluate().first.widget as ListView;
    expect(list.semanticChildCount, kOptionsUsers.length);

    // Enter text. The options are filtered by the text.
    await tester.enterText(find.byType(TextFormField), 'example');
    await tester.pump();
    expect(find.byType(TextFormField), findsOneWidget);
    expect(find.byType(ListView), findsOneWidget);
    list = find.byType(ListView).evaluate().first.widget as ListView;
    // 'Alice' and 'Bob' are displayed because they have "example.com" emails.
    expect(list.semanticChildCount, 2);

    // Select a option. The options hide and the field updates to show the
    // selection.
    await tester.tap(find.byType(InkWell).first);
    await tester.pump();
    expect(find.byType(TextFormField), findsOneWidget);
    expect(find.byType(ListView), findsNothing);
    final field = find.byType(TextFormField).evaluate().first.widget as TextFormField;
    expect(field.controller!.text, 'Alice, alice@example.com');

    // Modify the field text. The options appear again and are filtered.
    await tester.enterText(find.byType(TextFormField), 'B');
    await tester.pump();
    expect(find.byType(TextFormField), findsOneWidget);
    expect(find.byType(ListView), findsOneWidget);
    list = find.byType(ListView).evaluate().first.widget as ListView;
    // 'Bob' is displayed.
    expect(list.semanticChildCount, 1);
  });

  testWidgets('displayStringForOption is displayed in the options', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: Autocomplete<User>(
            displayStringForOption: (User option) {
              return option.name;
            },
            optionsBuilder: (TextEditingValue textEditingValue) {
              return kOptionsUsers.where((User option) {
                return option.toString().contains(textEditingValue.text.toLowerCase());
              });
            },
          ),
        ),
      ),
    );

    // The field is always rendered, but the options are not unless needed.
    expect(find.byType(TextFormField), findsOneWidget);
    expect(find.byType(ListView), findsNothing);

    // Focus the empty field. All the options are displayed, and the string that
    // is used comes from displayStringForOption.
    await tester.tap(find.byType(TextFormField));
    await tester.pump();
    expect(find.byType(ListView), findsOneWidget);
    final list = find.byType(ListView).evaluate().first.widget as ListView;
    expect(list.semanticChildCount, kOptionsUsers.length);
    for (var i = 0; i < kOptionsUsers.length; i++) {
      expect(find.text(kOptionsUsers[i].name), findsOneWidget);
    }

    // Select a option. The options hide and the field updates to show the
    // selection. The text in the field is given by displayStringForOption.
    await tester.tap(find.byType(InkWell).first);
    await tester.pump();
    expect(find.byType(TextFormField), findsOneWidget);
    expect(find.byType(ListView), findsNothing);
    final field = find.byType(TextFormField).evaluate().first.widget as TextFormField;
    expect(field.controller!.text, kOptionsUsers.first.name);
  });

  testWidgets('can build a custom field', (WidgetTester tester) async {
    final GlobalKey fieldKey = GlobalKey();
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: Autocomplete<String>(
            optionsBuilder: (TextEditingValue textEditingValue) {
              return kOptions.where((String option) {
                return option.contains(textEditingValue.text.toLowerCase());
              });
            },
            fieldViewBuilder:
                (
                  BuildContext context,
                  TextEditingController textEditingController,
                  FocusNode focusNode,
                  VoidCallback onFieldSubmitted,
                ) {
                  return Container(key: fieldKey);
                },
          ),
        ),
      ),
    );

    // The custom field is rendered and not the default TextFormField.
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byType(TextFormField), findsNothing);
  });

  testWidgets('can build custom options', (WidgetTester tester) async {
    final GlobalKey optionsKey = GlobalKey();
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: Autocomplete<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);
                },
          ),
        ),
      ),
    );

    // The default field is rendered but not the options, yet.
    expect(find.byKey(optionsKey), findsNothing);
    expect(find.byType(TextFormField), findsOneWidget);

    // Focus the empty field. The custom options is displayed.
    await tester.tap(find.byType(TextFormField));
    await tester.pump();
    expect(find.byKey(optionsKey), findsOneWidget);
  });

  testWidgets('the default Autocomplete options widget has a maximum height of 200', (
    WidgetTester tester,
  ) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: Autocomplete<String>(
            optionsBuilder: (TextEditingValue textEditingValue) {
              return kOptions.where((String option) {
                return option.contains(textEditingValue.text.toLowerCase());
              });
            },
          ),
        ),
      ),
    );

    final Finder listFinder = find.byType(ListView);
    final Finder inputFinder = find.byType(TextFormField);
    await tester.tap(inputFinder);
    await tester.enterText(inputFinder, '');
    await tester.pump();
    final Size baseSize = tester.getSize(listFinder);
    final double resultingHeight = baseSize.height;
    expect(resultingHeight, equals(200));
  });

  testWidgets('the options height restricts to max desired height', (WidgetTester tester) async {
    const desiredHeight = 150.0;
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: Autocomplete<String>(
            optionsMaxHeight: desiredHeight,
            optionsBuilder: (TextEditingValue textEditingValue) {
              return kOptions.where((String option) {
                return option.contains(textEditingValue.text.toLowerCase());
              });
            },
          ),
        ),
      ),
    );

    /// entering "a" returns 9 items from kOptions so basically the
    /// height of 9 options would be beyond `desiredHeight=150`,
    /// so height gets restricted to desiredHeight.
    final Finder listFinder = find.byType(ListView);
    final Finder inputFinder = find.byType(TextFormField);
    await tester.tap(inputFinder);
    await tester.enterText(inputFinder, 'a');
    await tester.pump();
    final Size baseSize = tester.getSize(listFinder);
    final double resultingHeight = baseSize.height;

    /// expected desired Height =150.0
    expect(resultingHeight, equals(desiredHeight));
  });

  testWidgets(
    'The height of options shrinks to height of resulting items, if less than maxHeight',
    (WidgetTester tester) async {
      // Returns a Future with the height of the default [Autocomplete] options widget
      // after the provided text had been entered into the [Autocomplete] field.
      Future<double> getDefaultOptionsHeight(WidgetTester tester, String enteredText) async {
        final Finder listFinder = find.byType(ListView);
        final Finder inputFinder = find.byType(TextFormField);
        final field = inputFinder.evaluate().first.widget as TextFormField;
        field.controller!.clear();
        await tester.tap(inputFinder);
        await tester.enterText(inputFinder, enteredText);
        await tester.pump();
        final Size baseSize = tester.getSize(listFinder);
        return baseSize.height;
      }

      const maxOptionsHeight = 250.0;
      await tester.pumpWidget(
        MaterialApp(
          home: Scaffold(
            body: Autocomplete<String>(
              optionsMaxHeight: maxOptionsHeight,
              optionsBuilder: (TextEditingValue textEditingValue) {
                return kOptions.where((String option) {
                  return option.contains(textEditingValue.text.toLowerCase());
                });
              },
            ),
          ),
        ),
      );

      final Finder listFinder = find.byType(ListView);
      expect(listFinder, findsNothing);

      // Entering `a` returns 9 items(height > `maxOptionsHeight`) from the kOptions
      // so height gets restricted to `maxOptionsHeight =250`.
      final double nineItemsHeight = await getDefaultOptionsHeight(tester, 'a');
      expect(nineItemsHeight, equals(maxOptionsHeight));

      // Returns 2 Items (height < `maxOptionsHeight`)
      // so options height shrinks to 2 Items combined height.
      final double twoItemsHeight = await getDefaultOptionsHeight(tester, 'el');
      expect(twoItemsHeight, lessThan(maxOptionsHeight));

      // Returns 1 item (height < `maxOptionsHeight`) from `kOptions`
      // so options height shrinks to 1 items height.
      final double oneItemsHeight = await getDefaultOptionsHeight(tester, 'elep');
      expect(oneItemsHeight, lessThan(twoItemsHeight));
    },
  );

  testWidgets('initialValue sets initial text field value', (WidgetTester tester) async {
    late String lastSelection;
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: Autocomplete<String>(
            initialValue: const TextEditingValue(text: 'lem'),
            onSelected: (String selection) {
              lastSelection = selection;
            },
            optionsBuilder: (TextEditingValue textEditingValue) {
              return kOptions.where((String option) {
                return option.contains(textEditingValue.text.toLowerCase());
              });
            },
          ),
        ),
      ),
    );

    // The field is always rendered, but the options are not unless needed.
    expect(find.byType(TextFormField), findsOneWidget);
    expect(find.byType(ListView), findsNothing);
    expect(tester.widget<TextFormField>(find.byType(TextFormField)).controller!.text, 'lem');

    // Focus the empty field. All the options are displayed.
    await tester.tap(find.byType(TextFormField));
    await tester.pump();
    expect(find.byType(ListView), findsOneWidget);
    final list = find.byType(ListView).evaluate().first.widget as ListView;
    // Displays just one option ('lemur').
    expect(list.semanticChildCount, 1);

    // Select a option. The options hide and the field updates to show the
    // selection.
    await tester.tap(find.byType(InkWell).first);
    await tester.pump();
    expect(find.byType(TextFormField), findsOneWidget);
    expect(find.byType(ListView), findsNothing);
    final field = find.byType(TextFormField).evaluate().first.widget as TextFormField;
    expect(field.controller!.text, 'lemur');
    expect(lastSelection, 'lemur');
  });

  // Ensures that the option with the given label has a given background color
  // if given, or no background if color is null.
  void checkOptionHighlight(WidgetTester tester, String label, Color? color) {
    final RenderBox renderBox = tester.renderObject<RenderBox>(
      find.ancestor(matching: find.byType(Container), of: find.text(label)),
    );
    if (color != null) {
      // Check to see that the container is painted with the highlighted background color.
      expect(renderBox, paints..rect(color: color));
    } else {
      // There should only be a paragraph painted.
      expect(renderBox, paintsExactlyCountTimes(const Symbol('drawRect'), 0));
      expect(renderBox, paints..paragraph());
    }
  }

  testWidgets('keyboard navigation of the options properly highlights the option', (
    WidgetTester tester,
  ) async {
    const highlightColor = Color(0xFF112233);
    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(focusColor: highlightColor),
        home: Scaffold(
          body: Autocomplete<String>(
            optionsBuilder: (TextEditingValue textEditingValue) {
              return kOptions.where((String option) {
                return option.contains(textEditingValue.text.toLowerCase());
              });
            },
          ),
        ),
      ),
    );

    await tester.tap(find.byType(TextFormField));
    await tester.enterText(find.byType(TextFormField), 'el');
    await tester.pump();
    expect(find.byType(ListView), findsOneWidget);
    final list = find.byType(ListView).evaluate().first.widget as ListView;
    expect(list.semanticChildCount, 2);

    // Initially the first option should be highlighted
    checkOptionHighlight(tester, 'chameleon', highlightColor);
    checkOptionHighlight(tester, 'elephant', null);

    // Move the selection down
    await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
    await tester.pump();

    // Highlight should be moved to the second item
    checkOptionHighlight(tester, 'chameleon', null);
    checkOptionHighlight(tester, 'elephant', highlightColor);
  });

  testWidgets('keyboard navigation keeps the highlighted option scrolled into view', (
    WidgetTester tester,
  ) async {
    const highlightColor = Color(0xFF112233);
    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(focusColor: highlightColor),
        home: Scaffold(
          body: Autocomplete<String>(
            optionsBuilder: (TextEditingValue textEditingValue) {
              return kOptions.where((String option) {
                return option.contains(textEditingValue.text.toLowerCase());
              });
            },
          ),
        ),
      ),
    );

    await tester.tap(find.byType(TextFormField));
    await tester.enterText(find.byType(TextFormField), 'e');
    await tester.pump();
    expect(find.byType(ListView), findsOneWidget);
    final list = find.byType(ListView).evaluate().first.widget as ListView;
    expect(list.semanticChildCount, 6);

    final Rect optionsGroupRect = tester.getRect(find.byType(ListView));
    const optionsGroupPadding = 16.0;

    // Highlighted item should be at the top.
    checkOptionHighlight(tester, 'chameleon', highlightColor);
    expect(
      tester.getTopLeft(find.text('chameleon')).dy,
      equals(optionsGroupRect.top + optionsGroupPadding),
    );

    // Move down the list of options.
    await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown); // Select 'elephant'.
    await tester.pumpAndSettle();
    await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown); // Select 'goose'.
    await tester.pumpAndSettle();
    await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown); // Select 'lemur'.
    await tester.pumpAndSettle();

    // Highlighted item 'lemur' should be centered in the options popup.
    checkOptionHighlight(tester, 'lemur', highlightColor);
    expect(tester.getCenter(find.text('lemur')).dy, equals(optionsGroupRect.center.dy));

    await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown); // Select 'mouse'.
    await tester.pumpAndSettle();

    checkOptionHighlight(tester, 'mouse', highlightColor);

    // First item should have scrolled off the top, and not be selected.
    expect(find.text('chameleon'), findsNothing);

    // The other items on screen should not be selected.
    checkOptionHighlight(tester, 'goose', null);
    checkOptionHighlight(tester, 'lemur', null);
    checkOptionHighlight(tester, 'northern white rhinoceros', null);
  });

  group('optionsViewOpenDirection', () {
    testWidgets('default (down)', (WidgetTester tester) async {
      await tester.pumpWidget(
        MaterialApp(
          home: Scaffold(
            body: Autocomplete<String>(
              optionsBuilder: (TextEditingValue textEditingValue) => <String>['a'],
            ),
          ),
        ),
      );
      final OptionsViewOpenDirection actual = tester
          .widget<RawAutocomplete<String>>(find.byType(RawAutocomplete<String>))
          .optionsViewOpenDirection;
      expect(actual, equals(OptionsViewOpenDirection.down));
    });

    testWidgets('down', (WidgetTester tester) async {
      await tester.pumpWidget(
        MaterialApp(
          home: Scaffold(
            body: Autocomplete<String>(
              // ignore: avoid_redundant_argument_values
              optionsViewOpenDirection: OptionsViewOpenDirection.down,
              optionsBuilder: (TextEditingValue textEditingValue) => <String>['a'],
            ),
          ),
        ),
      );
      final OptionsViewOpenDirection actual = tester
          .widget<RawAutocomplete<String>>(find.byType(RawAutocomplete<String>))
          .optionsViewOpenDirection;
      expect(actual, equals(OptionsViewOpenDirection.down));
    });

    testWidgets('up', (WidgetTester tester) async {
      await tester.pumpWidget(
        MaterialApp(
          home: Scaffold(
            body: Center(
              child: Autocomplete<String>(
                optionsViewOpenDirection: OptionsViewOpenDirection.up,
                optionsBuilder: (TextEditingValue textEditingValue) => <String>['aa'],
              ),
            ),
          ),
        ),
      );
      final OptionsViewOpenDirection actual = tester
          .widget<RawAutocomplete<String>>(find.byType(RawAutocomplete<String>))
          .optionsViewOpenDirection;
      expect(actual, equals(OptionsViewOpenDirection.up));

      await tester.tap(find.byType(RawAutocomplete<String>));
      await tester.enterText(find.byType(RawAutocomplete<String>), 'a');
      await tester.pump();
      expect(find.text('aa').hitTestable(), findsOneWidget);
    });

    testWidgets('automatic: 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(
        MaterialApp(
          home: Scaffold(
            body: StatefulBuilder(
              builder: (BuildContext context, StateSetter setter) {
                setState = setter;
                return Align(
                  alignment: alignment,
                  child: Autocomplete<String>(
                    optionsViewOpenDirection: OptionsViewOpenDirection.mostSpace,
                    optionsBuilder: (TextEditingValue textEditingValue) => <String>['a', 'b', 'c'],
                    fieldViewBuilder:
                        (
                          BuildContext context,
                          TextEditingController controller,
                          FocusNode focusNode,
                          VoidCallback onFieldSubmitted,
                        ) {
                          return TextField(
                            key: fieldKey,
                            controller: controller,
                            focusNode: focusNode,
                          );
                        },
                    optionsViewBuilder:
                        (
                          BuildContext context,
                          AutocompleteOnSelected<String> onSelected,
                          Iterable<String> options,
                        ) {
                          return Material(
                            child: 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.byKey(fieldKey));
      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))),
      );

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

      // Show the options. It should open downwards since there is more space.
      expect(
        tester.getBottomLeft(find.byKey(fieldKey)),
        offsetMoreOrLessEquals(tester.getTopLeft(find.byKey(optionsKey))),
      );
    });
  });

  testWidgets('can jump to options that are not yet built', (WidgetTester tester) async {
    const highlightColor = Color(0xFF112233);
    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(focusColor: highlightColor),
        home: Scaffold(
          body: Autocomplete<String>(
            optionsBuilder: (TextEditingValue textEditingValue) {
              return kOptions.where((String option) {
                return option.contains(textEditingValue.text.toLowerCase());
              });
            },
          ),
        ),
      ),
    );

    await tester.tap(find.byType(TextFormField));
    await tester.pump();
    expect(find.byType(ListView), findsOneWidget);
    final list = find.byType(ListView).evaluate().first.widget as ListView;
    expect(list.semanticChildCount, kOptions.length);

    Finder optionFinder(int index) {
      return find.ancestor(
        matching: find.byType(Container),
        of: find.text(kOptions.elementAt(index)),
      );
    }

    expect(optionFinder(0), findsOneWidget);
    expect(optionFinder(kOptions.length - 1), findsNothing);

    // Jump to the bottom.
    await tester.sendKeyDownEvent(LogicalKeyboardKey.control);
    await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
    await tester.sendKeyUpEvent(LogicalKeyboardKey.control);
    await tester.pumpAndSettle();
    expect(optionFinder(0), findsNothing);
    expect(optionFinder(kOptions.length - 1), findsOneWidget);
    checkOptionHighlight(tester, kOptions.last, highlightColor);

    // Jump to the top.
    await tester.sendKeyDownEvent(LogicalKeyboardKey.control);
    await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
    await tester.sendKeyUpEvent(LogicalKeyboardKey.control);
    await tester.pumpAndSettle();
    expect(optionFinder(0), findsOneWidget);
    expect(optionFinder(kOptions.length - 1), findsNothing);
    checkOptionHighlight(tester, kOptions.first, highlightColor);
  });

  testWidgets(
    'passes textEditingController, focusNode to textEditingController, focusNode RawAutocomplete',
    (WidgetTester tester) async {
      final textEditingController = TextEditingController();
      final focusNode = FocusNode();
      addTearDown(textEditingController.dispose);
      addTearDown(focusNode.dispose);

      await tester.pumpWidget(
        MaterialApp(
          home: Material(
            child: Center(
              child: Autocomplete<String>(
                focusNode: focusNode,
                textEditingController: textEditingController,
                optionsBuilder: (TextEditingValue textEditingValue) => <String>['a'],
              ),
            ),
          ),
        ),
      );

      final RawAutocomplete<String> rawAutocomplete = tester.widget(
        find.byType(RawAutocomplete<String>),
      );
      expect(rawAutocomplete.textEditingController, textEditingController);
      expect(rawAutocomplete.focusNode, focusNode);
    },
  );

  testWidgets('when field scrolled offscreen, reshown selected value when scrolled back', (
    WidgetTester tester,
  ) async {
    final scrollController = ScrollController();
    final textEditingController = TextEditingController();
    final focusNode = FocusNode();
    addTearDown(textEditingController.dispose);
    addTearDown(focusNode.dispose);
    addTearDown(scrollController.dispose);

    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: ListView(
            controller: scrollController,
            children: <Widget>[
              Autocomplete<String>(
                focusNode: focusNode,
                textEditingController: textEditingController,
                optionsBuilder: (TextEditingValue textEditingValue) {
                  return kOptions.where((String option) {
                    return option.contains(textEditingValue.text.toLowerCase());
                  });
                },
              ),
              const SizedBox(height: 1000.0),
            ],
          ),
        ),
      ),
    );

    /// Select an option.
    await tester.tap(find.byType(TextField));
    await tester.pump();
    const textSelection = 'chameleon';
    await tester.tap(find.text(textSelection));

    // Unfocus and scroll to deconstruct the widge
    final field = find.byType(TextField).evaluate().first.widget as TextField;
    field.focusNode?.unfocus();
    scrollController.jumpTo(2000.0);
    await tester.pumpAndSettle();

    /// Scroll to go back to the widget.
    scrollController.jumpTo(0.0);
    await tester.pumpAndSettle();

    /// Checks that the option selected is still present.
    final field2 = find.byType(TextField).evaluate().first.widget as TextField;
    expect(field2.controller!.text, textSelection);
  });

  testWidgets('Autocomplete suggestions are hit-tested before ListTiles', (
    WidgetTester tester,
  ) async {
    final semantics = SemanticsTester(tester);

    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: Column(
            children: <Widget>[
              Autocomplete<String>(
                optionsBuilder: (TextEditingValue textEditingValue) {
                  const options = <String>['Apple', 'Banana', 'Cherry'];
                  return options.where(
                    (String option) => option.toLowerCase().contains(textEditingValue.text),
                  );
                },
              ),
              for (int i = 0; i < 3; i++) ListTile(title: Text('Item $i'), onTap: () {}),
            ],
          ),
        ),
      ),
    );

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

    final Finder cherryFinder = find.text('Cherry');
    expect(cherryFinder, findsOneWidget);

    await tester.tap(cherryFinder);
    await tester.pump();

    expect(find.widgetWithText(TextField, 'Cherry'), findsOneWidget);
    semantics.dispose();
  });

  testWidgets('Autocomplete renders at zero area', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Center(
          child: SizedBox.shrink(
            child: Scaffold(
              body: Autocomplete<String>(
                initialValue: const TextEditingValue(text: 'X'),
                optionsBuilder: (TextEditingValue textEditingValue) => <String>['Y'],
              ),
            ),
          ),
        ),
      ),
    );
    final Finder xText = find.text('X');
    expect(tester.getSize(xText), Size.zero);
  });

  testWidgets('autocomplete options have button semantics', (WidgetTester tester) async {
    const highlightColor = Color(0xFF112233);
    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(focusColor: highlightColor),
        home: Scaffold(
          body: Autocomplete<String>(
            optionsBuilder: (TextEditingValue textEditingValue) {
              return kOptions.where((String option) {
                return option.contains(textEditingValue.text.toLowerCase());
              });
            },
          ),
        ),
      ),
    );
    await tester.tap(find.byType(TextField));
    await tester.pump();
    await tester.enterText(find.byType(TextField), 'aa');
    await tester.pump();
    expect(
      tester.getSemantics(find.text('aardvark')),
      matchesSemantics(
        isButton: true,
        isFocusable: true,
        hasTapAction: true,
        hasFocusAction: true,
        label: 'aardvark',
      ),
    );
  });
}
