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

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

@TestOn('!chrome')
import 'dart:ui' as ui show BoxHeightStyle, BoxWidthStyle;
import 'dart:ui';

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

import '../widgets/clipboard_utils.dart';
import '../widgets/editable_text_utils.dart' show textOffsetToPosition;
import '../widgets/semantics_tester.dart';

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

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

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

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

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

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

Widget overlay({ Widget? child }) {
  final OverlayEntry entry = OverlayEntry(
    builder: (BuildContext context) {
      return Center(
        child: Material(
          child: child,
        ),
      );
    },
  );
  return overlayWithEntry(entry);
}

Widget overlayWithEntry(OverlayEntry entry) {
  return Localizations(
    locale: const Locale('en', 'US'),
    delegates: <LocalizationsDelegate<dynamic>>[
      WidgetsLocalizationsDelegate(),
      MaterialLocalizationsDelegate(),
    ],
    child: Directionality(
      textDirection: TextDirection.ltr,
      child: MediaQuery(
        data: const MediaQueryData(size: Size(800.0, 600.0)),
        child: Overlay(
          initialEntries: <OverlayEntry>[
            entry,
          ],
        ),
      ),
    ),
  );
}

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

Future<void> skipPastScrollingAnimation(WidgetTester tester) async {
  await tester.pump();
  await tester.pump(const Duration(milliseconds: 200));
}

void main() {
  TestWidgetsFlutterBinding.ensureInitialized();
  final MockClipboard mockClipboard = MockClipboard();

  const String kThreeLines =
      'First line of text is\n'
      'Second line goes until\n'
      'Third line of stuff';
  const String kMoreThanFourLines =
      '$kThreeLines\n'
      "Fourth line won't display and ends at";

  // Returns the first RenderEditable.
  RenderEditable findRenderEditable(WidgetTester tester) {
    final RenderObject root = tester.renderObject(find.byType(EditableText));
    expect(root, isNotNull);

    late RenderEditable renderEditable;
    void recursiveFinder(RenderObject child) {
      if (child is RenderEditable) {
        renderEditable = child;
        return;
      }
      child.visitChildren(recursiveFinder);
    }
    root.visitChildren(recursiveFinder);
    expect(renderEditable, isNotNull);
    return renderEditable;
  }

  List<TextSelectionPoint> globalize(Iterable<TextSelectionPoint> points, RenderBox box) {
    return points.map<TextSelectionPoint>((TextSelectionPoint point) {
      return TextSelectionPoint(
        box.localToGlobal(point.point),
        point.direction,
      );
    }).toList();
  }

  setUp(() async {
    debugResetSemanticsIdCounter();
    TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(
      SystemChannels.platform,
      mockClipboard.handleMethodCall,
    );
    // Fill the clipboard so that the Paste option is available in the text
    // selection menu.
    await Clipboard.setData(const ClipboardData(text: 'Clipboard data'));
  });

  tearDown(() {
    TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(
      SystemChannels.platform,
      null,
    );
  });

  Widget selectableTextBuilder({
    String text = '',
    int? maxLines = 1,
    int? minLines,
  }) {
    return boilerplate(
      child: SelectableText(
        text,
        style: const TextStyle(color: Colors.black, fontSize: 34.0),
        maxLines: maxLines,
        minLines: minLines,
      ),
    );
  }

  testWidgets('throw if no Overlay widget exists above', (WidgetTester tester) async {
    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: MediaQuery(
          data: MediaQueryData(size: Size(800.0, 600.0)),
          child: Center(
            child: Material(
              child: SelectableText('I love Flutter!'),
            ),
          ),
        ),
      ),
    );

    final Offset textFieldStart = tester.getTopLeft(find.byType(SelectableText));
    final TestGesture gesture = await tester.startGesture(textFieldStart, kind: PointerDeviceKind.mouse);
    await tester.pump(const Duration(seconds: 2));
    await gesture.up();
    await tester.pumpAndSettle();

    final FlutterError error = tester.takeException() as FlutterError;
    expect(
      error.message,
      contains('EditableText widgets require an Overlay widget ancestor'),
    );

    await tester.pumpWidget(const SizedBox.shrink());
    expect(tester.takeException(), isNotNull);  // side effect exception
  });

  testWidgets('Do not crash when remove SelectableText during handle drag', (WidgetTester tester) async {
    // Regression test https://github.com/flutter/flutter/issues/108242
    bool isShow = true;
    late StateSetter setter;
    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              setter = setState;
              if (isShow) {
                return const SelectableText(
                  'abc def ghi',
                  dragStartBehavior: DragStartBehavior.down,
                );
              } else {
                return const SizedBox.shrink();
              }
            },
          ),
        ),
      ),
    );

    final EditableText editableTextWidget = tester.widget(find.byType(EditableText));
    final TextEditingController controller = editableTextWidget.controller;

    // Long press the 'e' to select 'def'.
    final Offset ePos = textOffsetToPosition(tester, 5);
    TestGesture gesture = await tester.startGesture(ePos, pointer: 7);
    await tester.pump(const Duration(seconds: 2));
    await gesture.up();
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 200)); // skip past the frame where the opacity is zero

    final TextSelection selection = controller.selection;
    expect(selection.baseOffset, 4);
    expect(selection.extentOffset, 7);

    final RenderEditable renderEditable = findRenderEditable(tester);
    final List<TextSelectionPoint> endpoints = globalize(
      renderEditable.getEndpointsForSelection(selection),
      renderEditable,
    );
    expect(endpoints.length, 2);

    // Drag the left handle to the left.
    final Offset handlePos = endpoints[0].point + const Offset(-1.0, 1.0);
    final Offset newHandlePos = textOffsetToPosition(tester, 1);
    final Offset newHandlePos1 = textOffsetToPosition(tester, 0);
    gesture = await tester.startGesture(handlePos, pointer: 7);
    await tester.pump();
    await gesture.moveTo(newHandlePos);
    await tester.pump();

    // Unmount the SelectableText during handle drag
    setter(() {
      isShow = false;
    });
    await tester.pump();

    await gesture.moveTo(newHandlePos1);
    await tester.pump(); // Do not crash here

    await gesture.up();
    await tester.pump();
  });

  testWidgets('has expected defaults', (WidgetTester tester) async {
    await tester.pumpWidget(
      boilerplate(
          child: const SelectableText('selectable text'),
      ),
    );

    final SelectableText selectableText = tester.firstWidget(find.byType(SelectableText));
    expect(selectableText.showCursor, false);
    expect(selectableText.autofocus, false);
    expect(selectableText.dragStartBehavior, DragStartBehavior.start);
    expect(selectableText.cursorWidth, 2.0);
    expect(selectableText.cursorHeight, isNull);
    expect(selectableText.enableInteractiveSelection, true);
  });

  testWidgets('Rich selectable text has expected defaults', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MediaQuery(
        data: MediaQueryData(),
        child: Directionality(
          textDirection: TextDirection.ltr,
          child: SelectableText.rich(
              TextSpan(
                text: 'First line!',
                style: TextStyle(
                    fontSize: 14,
                    fontFamily: 'Roboto',
                ),
                children: <TextSpan>[
                  TextSpan(
                    text: 'Second line!\n',
                    style: TextStyle(
                      fontSize: 30,
                      fontFamily: 'Roboto',
                    ),
                  ),
                  TextSpan(
                    text: 'Third line!\n',
                    style: TextStyle(
                      fontSize: 14,
                      fontFamily: 'Roboto',
                    ),
                  ),
                ],
              ),
          ),
        ),
      ),
    );

    final SelectableText selectableText =
    tester.firstWidget(find.byType(SelectableText));
    expect(selectableText.showCursor, false);
    expect(selectableText.autofocus, false);
    expect(selectableText.dragStartBehavior, DragStartBehavior.start);
    expect(selectableText.cursorWidth, 2.0);
    expect(selectableText.cursorHeight, isNull);
    expect(selectableText.enableInteractiveSelection, true);
  });

  testWidgets('Rich selectable text supports WidgetSpan', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MediaQuery(
        data: MediaQueryData(),
        child: Directionality(
          textDirection: TextDirection.ltr,
          child: SelectableText.rich(
              TextSpan(
                text: 'First line!',
                style: TextStyle(
                    fontSize: 14,
                    fontFamily: 'Roboto',
                ),
                children: <InlineSpan>[
                  WidgetSpan(
                      child: SizedBox(
                        width: 120,
                        height: 50,
                        child: Card(
                            child: Center(
                                child: Text('Hello World!'),
                            ),
                        ),
                      ),
                  ),
                  TextSpan(
                    text: 'Third line!\n',
                    style: TextStyle(
                      fontSize: 14,
                      fontFamily: 'Roboto',
                    ),
                  ),
                ],
              ),
          ),
        ),
      ),
    );
    expect(tester.takeException(), isNull);
  });

  testWidgets('no text keyboard when widget is focused', (WidgetTester tester) async {
    await tester.pumpWidget(
        overlay(
          child: const SelectableText('selectable text'),
        ),
    );
    await tester.tap(find.byType(SelectableText));
    await tester.idle();
    expect(tester.testTextInput.hasAnyClients, false);
  });

  testWidgets('uses DefaultSelectionStyle for selection and cursor colors if provided', (WidgetTester tester) async {
    const Color selectionColor = Colors.orange;
    const Color cursorColor = Colors.red;

    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: DefaultSelectionStyle(
            selectionColor: selectionColor,
            cursorColor: cursorColor,
            child: SelectableText('text'),
          ),
        ),
      ),
    );
    await tester.pump();
    final EditableTextState state = tester.state<EditableTextState>(find.byType(EditableText));
    expect(state.widget.selectionColor, selectionColor);
    expect(state.widget.cursorColor, cursorColor);
  });

  testWidgets('Selectable Text has adaptive size', (WidgetTester tester) async {
    await tester.pumpWidget(
        boilerplate(
          child: const SelectableText('s'),
        ),
    );

    RenderBox findSelectableTextBox() => tester.renderObject(find.byType(SelectableText));

    final RenderBox textBox = findSelectableTextBox();
    expect(textBox.size, const Size(17.0, 14.0));

    await tester.pumpWidget(
        boilerplate(
          child: const SelectableText('very very long'),
        ),
    );

    final RenderBox longtextBox = findSelectableTextBox();
    expect(longtextBox.size, const Size(199.0, 14.0));
  });

  testWidgets('can scale with textScaleFactor', (WidgetTester tester) async {
    await tester.pumpWidget(
      boilerplate(
        child: const SelectableText('selectable text'),
      ),
    );

    final RenderBox renderBox = tester.renderObject(find.byType(SelectableText));
    expect(renderBox.size.height, 14.0);

    await tester.pumpWidget(
      boilerplate(
        child: const SelectableText(
          'selectable text',
          textScaleFactor: 1.9,
        ),
      ),
    );

    final RenderBox scaledBox = tester.renderObject(find.byType(SelectableText));
    expect(scaledBox.size.height, 27.0);
  });

  testWidgets('can switch between textWidthBasis', (WidgetTester tester) async {
    RenderBox findTextBox() => tester.renderObject(find.byType(SelectableText));
    const String text = 'I can face roll keyboardkeyboardaszzaaaaszzaaaaszzaaaaszzaaaa';
    await tester.pumpWidget(
      boilerplate(
        child: const SelectableText(
          text,
          textWidthBasis: TextWidthBasis.parent,
        ),
      ),
    );
    RenderBox textBox = findTextBox();
    expect(textBox.size, const Size(800.0, 28.0));

    await tester.pumpWidget(
      boilerplate(
        child: const SelectableText(
          text,
          textWidthBasis: TextWidthBasis.longestLine,
        ),
      ),
    );
    textBox = findTextBox();
    expect(textBox.size, const Size(633.0, 28.0));
  });

  testWidgets('can switch between textHeightBehavior', (WidgetTester tester) async {
    const String text = 'selectable text';
    const TextHeightBehavior textHeightBehavior = TextHeightBehavior(
      applyHeightToFirstAscent: false,
      applyHeightToLastDescent: false,
    );
    await tester.pumpWidget(
      boilerplate(
        child: const SelectableText(text),
      ),
    );
    expect(findRenderEditable(tester).textHeightBehavior, isNull);

    await tester.pumpWidget(
      boilerplate(
        child: const SelectableText(
          text,
          textHeightBehavior: textHeightBehavior,
        ),
      ),
    );
    expect(findRenderEditable(tester).textHeightBehavior, textHeightBehavior);
  });

  testWidgets('Cursor blinks when showCursor is true', (WidgetTester tester) async {
    await tester.pumpWidget(
      overlay(
        child: const SelectableText(
          'some text',
          showCursor: true,
        ),
      ),
    );
    await tester.tap(find.byType(SelectableText));
    await tester.idle();

    final EditableTextState editableText = tester.state(find.byType(EditableText));

    // Check that the cursor visibility toggles after each blink interval.
    final bool initialShowCursor = editableText.cursorCurrentlyVisible;
    await tester.pump(editableText.cursorBlinkInterval);
    expect(editableText.cursorCurrentlyVisible, equals(!initialShowCursor));
    await tester.pump(editableText.cursorBlinkInterval);
    expect(editableText.cursorCurrentlyVisible, equals(initialShowCursor));
    await tester.pump(editableText.cursorBlinkInterval ~/ 10);
    expect(editableText.cursorCurrentlyVisible, equals(initialShowCursor));
    await tester.pump(editableText.cursorBlinkInterval);
    expect(editableText.cursorCurrentlyVisible, equals(!initialShowCursor));
    await tester.pump(editableText.cursorBlinkInterval);
    expect(editableText.cursorCurrentlyVisible, equals(initialShowCursor));
  });

  testWidgets('selectable text selection toolbar renders correctly inside opacity', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        home: Scaffold(
          body: Center(
            child: SizedBox(
              width: 100,
              height: 100,
              child: Opacity(
                opacity: 0.5,
                child: SelectableText('selectable text'),
              ),
            ),
          ),
        ),
      ),
    );

    // The selectWordsInRange with SelectionChangedCause.tap seems to be needed to show the toolbar.
    final EditableTextState state = tester.state<EditableTextState>(find.byType(EditableText));
    state.renderEditable.selectWordsInRange(from: Offset.zero, cause: SelectionChangedCause.tap);

    expect(state.showToolbar(), true);

    // This is needed for the AnimatedOpacity to turn from 0 to 1 so the toolbar is visible.
    await tester.pumpAndSettle();
    await tester.pump(const Duration(seconds: 1));

    expect(find.text('Select all'), findsOneWidget);
  });

  testWidgets('Caret position is updated on tap', (WidgetTester tester) async {
    await tester.pumpWidget(
        overlay(
          child: const SelectableText('abc def ghi'),
        ),
    );
    final EditableText editableText = tester.widget(find.byType(EditableText));
    expect(editableText.controller.selection.baseOffset, -1);
    expect(editableText.controller.selection.extentOffset, -1);

    // Tap to reposition the caret.
    const int tapIndex = 4;
    final Offset ePos = textOffsetToPosition(tester, tapIndex);
    await tester.tapAt(ePos);
    await tester.pump();

    expect(editableText.controller.selection.baseOffset, tapIndex);
    expect(editableText.controller.selection.extentOffset, tapIndex);
  });

  testWidgets('enableInteractiveSelection = false, tap', (WidgetTester tester) async {
    await tester.pumpWidget(
        overlay(
          child: const SelectableText(
            'abc def ghi',
            enableInteractiveSelection: false,
          ),
        ),
    );
    final EditableText editableText = tester.widget(find.byType(EditableText));
    expect(editableText.controller.selection.baseOffset, -1);
    expect(editableText.controller.selection.extentOffset, -1);

    // Tap would ordinarily reposition the caret.
    const int tapIndex = 4;
    final Offset ePos = textOffsetToPosition(tester, tapIndex);
    await tester.tapAt(ePos);
    await tester.pump();

    expect(editableText.controller.selection.baseOffset, -1);
    expect(editableText.controller.selection.extentOffset, -1);
  });

  testWidgets('enableInteractiveSelection = false, long-press', (WidgetTester tester) async {
    await tester.pumpWidget(
        overlay(
          child: const SelectableText(
            'abc def ghi',
            enableInteractiveSelection: false,
          ),
        ),
    );
    final EditableText editableText = tester.widget(find.byType(EditableText));
    expect(editableText.controller.selection.baseOffset, -1);
    expect(editableText.controller.selection.extentOffset, -1);

    // Long press the 'e' to select 'def'.
    final Offset ePos = textOffsetToPosition(tester, 5);
    final TestGesture gesture = await tester.startGesture(ePos, pointer: 7);
    await tester.pump(const Duration(seconds: 2));
    await gesture.up();
    await tester.pump();

    expect(editableText.controller.selection.isCollapsed, true);
    expect(editableText.controller.selection.baseOffset, -1);
    expect(editableText.controller.selection.extentOffset, -1);
  });

  testWidgets('Can long press to select', (WidgetTester tester) async {
    await tester.pumpWidget(
        overlay(
          child: const SelectableText('abc def ghi'),
        ),
    );

    final EditableText editableText = tester.widget(find.byType(EditableText));

    expect(editableText.controller.selection.isCollapsed, true);

    // Long press the 'e' to select 'def'.
    const int tapIndex = 5;
    final Offset ePos = textOffsetToPosition(tester, tapIndex);
    await tester.longPressAt(ePos);
    await tester.pump();

    // 'def' is selected.
    expect(editableText.controller.selection.baseOffset, 4);
    expect(editableText.controller.selection.extentOffset, 7);

    // Tapping elsewhere immediately collapses and moves the cursor.
    await tester.tapAt(textOffsetToPosition(tester, 9));
    await tester.pump();

    expect(editableText.controller.selection.isCollapsed, true);
    expect(editableText.controller.selection.baseOffset, 9);
  });

  testWidgets("Slight movements in longpress don't hide/show handles", (WidgetTester tester) async {
    await tester.pumpWidget(
        overlay(
          child: const SelectableText('abc def ghi'),
        ),
    );
    // Long press the 'e' to select 'def', but don't release the gesture.
    final Offset ePos = textOffsetToPosition(tester, 5);
    final TestGesture gesture = await tester.startGesture(ePos, pointer: 7);
    await tester.pump(const Duration(seconds: 2));
    await tester.pumpAndSettle();

    // Handles are shown
    final Finder fadeFinder = find.byType(FadeTransition);
    expect(fadeFinder, findsNWidgets(2)); // 2 handles, 1 toolbar
    FadeTransition handle = tester.widget(fadeFinder.at(0));
    expect(handle.opacity.value, equals(1.0));

    // Move the gesture very slightly
    await gesture.moveBy(const Offset(1.0, 1.0));
    await tester.pump(SelectionOverlay.fadeDuration * 0.5);
    handle = tester.widget(fadeFinder.at(0));

    // The handle should still be fully opaque.
    expect(handle.opacity.value, equals(1.0));
  });

  testWidgets('Mouse long press is just like a tap', (WidgetTester tester) async {
    await tester.pumpWidget(
        overlay(
          child: const SelectableText('abc def ghi'),
        ),
    );

    final EditableText editableText = tester.widget(find.byType(EditableText));

    // Long press the 'e' using a mouse device.
    const int eIndex = 5;
    final Offset ePos = textOffsetToPosition(tester, eIndex);
    final TestGesture gesture = await tester.startGesture(ePos, kind: PointerDeviceKind.mouse);
    await tester.pump(const Duration(seconds: 2));
    await gesture.up();
    await tester.pump();

    // The cursor is placed just like a regular tap.
    expect(editableText.controller.selection.baseOffset, eIndex);
    expect(editableText.controller.selection.extentOffset, eIndex);
  });

  testWidgets('selectable text basic', (WidgetTester tester) async {
    await tester.pumpWidget(
        overlay(
          child: const SelectableText('selectable'),
        ),
    );
    final EditableText editableTextWidget = tester.widget(find.byType(EditableText));
    // selectable text cannot open keyboard.
    await tester.showKeyboard(find.byType(SelectableText));
    expect(tester.testTextInput.hasAnyClients, false);
    await skipPastScrollingAnimation(tester);

    expect(editableTextWidget.controller.selection.isCollapsed, true);

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

    final EditableTextState editableText = tester.state(find.byType(EditableText));
    // Collapse selection should not paint.
    expect(editableText.selectionOverlay!.handlesAreVisible, isFalse);
    // Long press on the 't' character of text 'selectable' to show context menu.
    const int dIndex = 5;
    final Offset dPos = textOffsetToPosition(tester, dIndex);
    await tester.longPressAt(dPos);
    await tester.pump();

    // Context menu should not have paste and cut.
    expect(find.text('Copy'), findsOneWidget);
    expect(find.text('Paste'), findsNothing);
    expect(find.text('Cut'), findsNothing);
  });

  testWidgets('selectable text can disable toolbar options', (WidgetTester tester) async {
    await tester.pumpWidget(
      overlay(
        child: const SelectableText(
          'a selectable text',
          toolbarOptions: ToolbarOptions(
            selectAll: true,
          ),
        ),
      ),
    );
    const int dIndex = 5;
    final Offset dPos = textOffsetToPosition(tester, dIndex);
    await tester.longPressAt(dPos);
    await tester.pump();
    // Context menu should not have copy.
    expect(find.text('Copy'), findsNothing);
    expect(find.text('Select all'), findsOneWidget);
  });

  testWidgets('Can select text by dragging with a mouse', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: SelectableText(
            'abc def ghi',
            dragStartBehavior: DragStartBehavior.down,
          ),
        ),
      ),
    );
    final EditableText editableTextWidget = tester.widget(find.byType(EditableText));
    final TextEditingController controller = editableTextWidget.controller;

    final Offset ePos = textOffsetToPosition(tester, 5);
    final Offset gPos = textOffsetToPosition(tester, 8);

    final TestGesture gesture = await tester.startGesture(ePos, kind: PointerDeviceKind.mouse);
    await tester.pump();
    await gesture.moveTo(gPos);
    await tester.pump();
    await gesture.up();
    await tester.pumpAndSettle();

    expect(controller.selection.baseOffset, 5);
    expect(controller.selection.extentOffset, 8);
  });

  testWidgets('Continuous dragging does not cause flickering', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: SelectableText(
            'abc def ghi',
            dragStartBehavior: DragStartBehavior.down,
            style: TextStyle(fontFamily: 'Ahem', fontSize: 10.0),
          ),
        ),
      ),
    );
    final EditableText editableTextWidget = tester.widget(find.byType(EditableText));
    final TextEditingController controller = editableTextWidget.controller;

    int selectionChangedCount = 0;

    controller.addListener(() {
      selectionChangedCount++;
    });

    final Offset cPos = textOffsetToPosition(tester, 2); // Index of 'c'.
    final Offset gPos = textOffsetToPosition(tester, 8); // Index of 'g'.
    final Offset hPos = textOffsetToPosition(tester, 9); // Index of 'h'.

    // Drag from 'c' to 'g'.
    final TestGesture gesture = await tester.startGesture(cPos, kind: PointerDeviceKind.mouse);
    await tester.pump();
    await gesture.moveTo(gPos);
    await tester.pumpAndSettle();

    expect(selectionChangedCount, isNonZero);
    selectionChangedCount = 0;
    expect(controller.selection.baseOffset, 2);
    expect(controller.selection.extentOffset, 8);

    // Tiny movement shouldn't cause text selection to change.
    await gesture.moveTo(gPos + const Offset(4.0, 0.0));
    await tester.pumpAndSettle();
    expect(selectionChangedCount, 0);

    // Now a text selection change will occur after a significant movement.
    await gesture.moveTo(hPos);
    await tester.pump();
    await gesture.up();
    await tester.pumpAndSettle();

    expect(selectionChangedCount, 1);
    expect(controller.selection.baseOffset, 2);
    expect(controller.selection.extentOffset, 9);
  });

  testWidgets('Dragging in opposite direction also works', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: SelectableText(
            'abc def ghi',
            dragStartBehavior: DragStartBehavior.down,
          ),
        ),
      ),
    );
    final EditableText editableTextWidget = tester.widget(find.byType(EditableText));
    final TextEditingController controller = editableTextWidget.controller;

    final Offset ePos = textOffsetToPosition(tester, 5);
    final Offset gPos = textOffsetToPosition(tester, 8);

    final TestGesture gesture = await tester.startGesture(gPos, kind: PointerDeviceKind.mouse);
    await tester.pump();
    await gesture.moveTo(ePos);
    await tester.pump();
    await gesture.up();
    await tester.pumpAndSettle();

    expect(controller.selection.baseOffset, 8);
    expect(controller.selection.extentOffset, 5);
  });

  testWidgets('Slow mouse dragging also selects text', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: SelectableText(
            'abc def ghi',
            dragStartBehavior: DragStartBehavior.down,
          ),
        ),
      ),
    );
    final EditableText editableTextWidget = tester.widget(find.byType(EditableText));
    final TextEditingController controller = editableTextWidget.controller;

    final Offset ePos = textOffsetToPosition(tester, 5);
    final Offset gPos = textOffsetToPosition(tester,8);

    final TestGesture gesture = await tester.startGesture(ePos, kind: PointerDeviceKind.mouse);
    await tester.pump(const Duration(seconds: 2));
    await gesture.moveTo(gPos);
    await tester.pump();
    await gesture.up();

    expect(controller.selection.baseOffset, 5);
    expect(controller.selection.extentOffset,8);
  });

  testWidgets('Can drag handles to change selection', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: SelectableText(
            'abc def ghi',
            dragStartBehavior: DragStartBehavior.down,
          ),
        ),
      ),
    );
    final EditableText editableTextWidget = tester.widget(find.byType(EditableText));
    final TextEditingController controller = editableTextWidget.controller;

    // Long press the 'e' to select 'def'.
    final Offset ePos = textOffsetToPosition(tester, 5);
    TestGesture gesture = await tester.startGesture(ePos, pointer: 7);
    await tester.pump(const Duration(seconds: 2));
    await gesture.up();
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 200)); // skip past the frame where the opacity is zero

    final TextSelection selection = controller.selection;
    expect(selection.baseOffset, 4);
    expect(selection.extentOffset, 7);

    final RenderEditable renderEditable = findRenderEditable(tester);
    final List<TextSelectionPoint> endpoints = globalize(
      renderEditable.getEndpointsForSelection(selection),
      renderEditable,
    );
    expect(endpoints.length, 2);

    // Drag the right handle 2 letters to the right.
    // We use a small offset because the endpoint is on the very corner
    // of the handle.
    Offset handlePos = endpoints[1].point + const Offset(1.0, 1.0);
    Offset newHandlePos = textOffsetToPosition(tester, 11);
    gesture = await tester.startGesture(handlePos, pointer: 7);
    await tester.pump();
    await gesture.moveTo(newHandlePos);
    await tester.pump();
    await gesture.up();
    await tester.pump();

    expect(controller.selection.baseOffset, 4);
    expect(controller.selection.extentOffset, 11);

    // Drag the left handle 2 letters to the left.
    handlePos = endpoints[0].point + const Offset(-1.0, 1.0);
    newHandlePos = textOffsetToPosition(tester, 0);
    gesture = await tester.startGesture(handlePos, pointer: 7);
    await tester.pump();
    await gesture.moveTo(newHandlePos);
    await tester.pump();
    await gesture.up();
    await tester.pump();

    expect(controller.selection.baseOffset, 0);
    expect(controller.selection.extentOffset, 11);
  });

  testWidgets('Dragging handles calls onSelectionChanged', (WidgetTester tester) async {
    TextSelection? newSelection;
    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: SelectableText(
            'abc def ghi',
            dragStartBehavior: DragStartBehavior.down,
            onSelectionChanged: (TextSelection selection, SelectionChangedCause? cause) {
              expect(newSelection, isNull);
              newSelection = selection;
            },
          ),
        ),
      ),
    );

    // Long press the 'e' to select 'def'.
    final Offset ePos = textOffsetToPosition(tester, 5);
    TestGesture gesture = await tester.startGesture(ePos, pointer: 7);
    await tester.pump(const Duration(seconds: 2));
    await gesture.up();
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 200)); // skip past the frame where the opacity is zero

    expect(newSelection!.baseOffset, 4);
    expect(newSelection!.extentOffset, 7);

    final RenderEditable renderEditable = findRenderEditable(tester);
    final List<TextSelectionPoint> endpoints = globalize(
      renderEditable.getEndpointsForSelection(newSelection!),
      renderEditable,
    );
    expect(endpoints.length, 2);
    newSelection = null;

    // Drag the right handle 2 letters to the right.
    // We use a small offset because the endpoint is on the very corner
    // of the handle.
    final Offset handlePos = endpoints[1].point + const Offset(1.0, 1.0);
    final Offset newHandlePos = textOffsetToPosition(tester, 9);
    gesture = await tester.startGesture(handlePos, pointer: 7);
    await tester.pump();
    await gesture.moveTo(newHandlePos);
    await tester.pump();
    await gesture.up();
    await tester.pump();

    expect(newSelection!.baseOffset, 4);
    expect(newSelection!.extentOffset, 9);
  });

  testWidgets('Cannot drag one handle past the other', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: SelectableText(
            'abc def ghi',
            dragStartBehavior: DragStartBehavior.down,
          ),
        ),
      ),
    );
    final EditableText editableTextWidget = tester.widget(find.byType(EditableText));
    final TextEditingController controller = editableTextWidget.controller;

    // Long press the 'e' to select 'def'.
    final Offset ePos = textOffsetToPosition(tester, 5); // Position before 'e'.
    TestGesture gesture = await tester.startGesture(ePos, pointer: 7);
    await tester.pump(const Duration(seconds: 2));
    await gesture.up();
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 200)); // skip past the frame where the opacity is zero

    final TextSelection selection = controller.selection;
    expect(selection.baseOffset, 4);
    expect(selection.extentOffset, 7);

    final RenderEditable renderEditable = findRenderEditable(tester);
    final List<TextSelectionPoint> endpoints = globalize(
      renderEditable.getEndpointsForSelection(selection),
      renderEditable,
    );
    expect(endpoints.length, 2);

    // Drag the right handle until there's only 1 char selected.
    // We use a small offset because the endpoint is on the very corner
    // of the handle.
    final Offset handlePos = endpoints[1].point + const Offset(4.0, 0.0);
    Offset newHandlePos = textOffsetToPosition(tester, 5); // Position before 'e'.
    gesture = await tester.startGesture(handlePos, pointer: 7);
    await tester.pump();
    await gesture.moveTo(newHandlePos);
    await tester.pump();

    expect(controller.selection.baseOffset, 4);
    expect(controller.selection.extentOffset, 5);

    newHandlePos = textOffsetToPosition(tester, 2); // Position before 'c'.
    await gesture.moveTo(newHandlePos);
    await tester.pump();
    await gesture.up();
    await tester.pump();

    expect(controller.selection.baseOffset, 4);
    // The selection doesn't move beyond the left handle. There's always at
    // least 1 char selected.
    expect(controller.selection.extentOffset, 5);
  });

  testWidgets('Can use selection toolbar', (WidgetTester tester) async {
    const String testValue = 'abc def ghi';
    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: SelectableText(
            testValue,
          ),
        ),
      ),
    );
    final EditableText editableTextWidget = tester.widget(find.byType(EditableText));
    final TextEditingController controller = editableTextWidget.controller;

    // Tap the selection handle to bring up the "paste / select all" menu.
    await tester.tapAt(textOffsetToPosition(tester, testValue.indexOf('e')));
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 200)); // skip past the frame where the opacity is zero
    final RenderEditable renderEditable = findRenderEditable(tester);
    final List<TextSelectionPoint> endpoints = globalize(
      renderEditable.getEndpointsForSelection(controller.selection),
      renderEditable,
    );
    // Tapping on the part of the handle's GestureDetector where it overlaps
    // with the text itself does not show the menu, so add a small vertical
    // offset to tap below the text.
    await tester.tapAt(endpoints[0].point + const Offset(1.0, 13.0));
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 200)); // skip past the frame where the opacity is zero

    // Select all should select all the text.
    await tester.tap(find.text('Select all'));
    await tester.pump();
    expect(controller.selection.baseOffset, 0);
    expect(controller.selection.extentOffset, testValue.length);

    // Copy should reset the selection.
    await tester.tap(find.text('Copy'));
    await skipPastScrollingAnimation(tester);
    expect(controller.selection.isCollapsed, true);
  });

  testWidgets('Selectable height with maxLine', (WidgetTester tester) async {
    await tester.pumpWidget(selectableTextBuilder());

    RenderBox findTextBox() => tester.renderObject(find.byType(SelectableText));

    final RenderBox textBox = findTextBox();
    final Size emptyInputSize = textBox.size;

    await tester.pumpWidget(selectableTextBuilder(text: 'No wrapping here.'));
    expect(findTextBox(), equals(textBox));
    expect(textBox.size.height, emptyInputSize.height);

    // Even when entering multiline text, SelectableText doesn't grow. It's a single
    // line input.
    await tester.pumpWidget(selectableTextBuilder(text: kThreeLines));
    expect(findTextBox(), equals(textBox));
    expect(textBox.size.height, emptyInputSize.height);

    // maxLines: 3 makes the SelectableText 3 lines tall
    await tester.pumpWidget(selectableTextBuilder(maxLines: 3));
    expect(findTextBox(), equals(textBox));
    expect(textBox.size.height, greaterThan(emptyInputSize.height));

    final Size threeLineInputSize = textBox.size;

    // Filling with 3 lines of text stays the same size
    await tester.pumpWidget(selectableTextBuilder(text: kThreeLines, maxLines: 3));
    expect(findTextBox(), equals(textBox));
    expect(textBox.size.height, threeLineInputSize.height);

    // An extra line won't increase the size because we max at 3.
    await tester.pumpWidget(selectableTextBuilder(text: kMoreThanFourLines, maxLines: 3));
    expect(findTextBox(), equals(textBox));
    expect(textBox.size.height, threeLineInputSize.height);

    // But now it will... but it will max at four
    await tester.pumpWidget(selectableTextBuilder(text: kMoreThanFourLines, maxLines: 4));
    expect(findTextBox(), equals(textBox));
    expect(textBox.size.height, greaterThan(threeLineInputSize.height));

    final Size fourLineInputSize = textBox.size;

    // Now it won't max out until the end
    await tester.pumpWidget(selectableTextBuilder(maxLines: null));
    expect(findTextBox(), equals(textBox));
    expect(textBox.size, equals(emptyInputSize));
    await tester.pumpWidget(selectableTextBuilder(text: kThreeLines, maxLines: null));
    expect(textBox.size.height, equals(threeLineInputSize.height));
    await tester.pumpWidget(selectableTextBuilder(text: kMoreThanFourLines, maxLines: null));
    expect(textBox.size.height, greaterThan(fourLineInputSize.height));
  });

  testWidgets('Can drag handles to change selection in multiline', (WidgetTester tester) async {
    const String testValue = kThreeLines;
    await tester.pumpWidget(
      overlay(
        child: const SelectableText(
          testValue,
          dragStartBehavior: DragStartBehavior.down,
          style: TextStyle(color: Colors.black, fontSize: 34.0),
          maxLines: 3,
        ),
      ),
    );

    final EditableText editableTextWidget = tester.widget(find.byType(EditableText));
    final TextEditingController controller = editableTextWidget.controller;

    // Check that the text spans multiple lines.
    final Offset firstPos = textOffsetToPosition(tester, testValue.indexOf('First'));
    final Offset secondPos = textOffsetToPosition(tester, testValue.indexOf('Second'));
    final Offset thirdPos = textOffsetToPosition(tester, testValue.indexOf('Third'));
    final Offset middleStringPos = textOffsetToPosition(tester, testValue.indexOf('irst'));

    expect(firstPos.dx, 24.5);
    expect(secondPos.dx, 24.5);
    expect(thirdPos.dx, 24.5);
    expect(middleStringPos.dx, 58.5);
    expect(firstPos.dx, secondPos.dx);
    expect(firstPos.dx, thirdPos.dx);
    expect(firstPos.dy, lessThan(secondPos.dy));
    expect(secondPos.dy, lessThan(thirdPos.dy));

    // Long press the 'n' in 'until' to select the word.
    final Offset untilPos = textOffsetToPosition(tester, testValue.indexOf('until')+1);
    TestGesture gesture = await tester.startGesture(untilPos, pointer: 7);
    await tester.pump(const Duration(seconds: 2));
    await gesture.up();
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 200)); // skip past the frame where the opacity is zero

    expect(controller.selection.baseOffset, 39);
    expect(controller.selection.extentOffset, 44);

    final RenderEditable renderEditable = findRenderEditable(tester);
    final List<TextSelectionPoint> endpoints = globalize(
      renderEditable.getEndpointsForSelection(controller.selection),
      renderEditable,
    );
    expect(endpoints.length, 2);

    // Drag the right handle to the third line, just after 'Third'.
    Offset handlePos = endpoints[1].point + const Offset(1.0, 1.0);
    // The distance below the y value returned by textOffsetToPosition required
    // to register a full vertical line drag.
    const Offset downLineOffset = Offset(0.0, 3.0);
    Offset newHandlePos =
        textOffsetToPosition(tester, testValue.indexOf('Third') + 5) + downLineOffset;
    gesture = await tester.startGesture(handlePos, pointer: 7);
    await tester.pump();
    await gesture.moveTo(newHandlePos);
    await tester.pump();
    await gesture.up();
    await tester.pump();

    expect(
      controller.selection,
      const TextSelection(
        baseOffset: 39,
        extentOffset: 50,
      ),
    );

    // Drag the left handle to the first line, just after 'First'.
    handlePos = endpoints[0].point + const Offset(-1.0, 1.0);
    newHandlePos = textOffsetToPosition(tester, testValue.indexOf('First') + 5);
    gesture = await tester.startGesture(handlePos, pointer: 7);
    await tester.pump();
    await gesture.moveTo(newHandlePos);
    await tester.pump();
    await gesture.up();
    await tester.pump();

    expect(controller.selection.baseOffset, 5);
    expect(controller.selection.extentOffset, 50);
    await tester.tap(find.text('Copy'));
    await tester.pump();
    expect(controller.selection.isCollapsed, true);
  });

  testWidgets('Can scroll multiline input', (WidgetTester tester) async {
    await tester.pumpWidget(
      overlay(
        child: const SelectableText(
          kMoreThanFourLines,
          dragStartBehavior: DragStartBehavior.down,
          style: TextStyle(color: Colors.black, fontSize: 34.0),
          maxLines: 2,
        ),
      ),
    );

    final EditableText editableTextWidget = tester.widget(find.byType(EditableText));
    final TextEditingController controller = editableTextWidget.controller;
    RenderBox findInputBox() => tester.renderObject(find.byType(SelectableText));
    final RenderBox inputBox = findInputBox();

    // Check that the last line of text is not displayed.
    final Offset firstPos = textOffsetToPosition(tester, kMoreThanFourLines.indexOf('First'));
    final Offset fourthPos = textOffsetToPosition(tester, kMoreThanFourLines.indexOf('Fourth'));
    expect(firstPos.dx, 0.0);
    expect(fourthPos.dx, 0.0);
    expect(firstPos.dx, fourthPos.dx);
    expect(firstPos.dy, lessThan(fourthPos.dy));
    expect(inputBox.hitTest(BoxHitTestResult(), position: inputBox.globalToLocal(firstPos)), isTrue);
    expect(inputBox.hitTest(BoxHitTestResult(), position: inputBox.globalToLocal(fourthPos)), isFalse);

    TestGesture gesture = await tester.startGesture(firstPos, pointer: 7);
    await tester.pump();
    await gesture.moveBy(const Offset(0.0, -1000.0));
    await tester.pump(const Duration(seconds: 1));
    // Wait and drag again to trigger https://github.com/flutter/flutter/issues/6329
    // (No idea why this is necessary, but the bug wouldn't repro without it.)
    await gesture.moveBy(const Offset(0.0, -1000.0));
    await tester.pump(const Duration(seconds: 1));
    await gesture.up();
    await tester.pump();
    await tester.pump(const Duration(seconds: 1));

    // Now the first line is scrolled up, and the fourth line is visible.
    Offset newFirstPos = textOffsetToPosition(tester, kMoreThanFourLines.indexOf('First'));
    Offset newFourthPos = textOffsetToPosition(tester, kMoreThanFourLines.indexOf('Fourth'));

    expect(newFirstPos.dy, lessThan(firstPos.dy));
    expect(inputBox.hitTest(BoxHitTestResult(), position: inputBox.globalToLocal(newFirstPos)), isFalse);
    expect(inputBox.hitTest(BoxHitTestResult(), position: inputBox.globalToLocal(newFourthPos)), isTrue);

    // Now try scrolling by dragging the selection handle.
    // Long press the middle of the word "won't" in the fourth line.
    final Offset selectedWordPos = textOffsetToPosition(
      tester,
      kMoreThanFourLines.indexOf('Fourth line') + 14,
    );

    gesture = await tester.startGesture(selectedWordPos, pointer: 7);
    await tester.pump(const Duration(seconds: 1));
    await gesture.up();
    await tester.pump();
    await tester.pump(const Duration(seconds: 1));

    expect(controller.selection.base.offset, 77);
    expect(controller.selection.extent.offset, 82);
    // Sanity check for the word selected is the intended one.
    expect(
      controller.text.substring(controller.selection.baseOffset, controller.selection.extentOffset),
      "won't",
    );

    final RenderEditable renderEditable = findRenderEditable(tester);
    final List<TextSelectionPoint> endpoints = globalize(
      renderEditable.getEndpointsForSelection(controller.selection),
      renderEditable,
    );
    expect(endpoints.length, 2);

    // Drag the left handle to the first line, just after 'First'.
    final Offset handlePos = endpoints[0].point + const Offset(-1, 1);
    final Offset newHandlePos = textOffsetToPosition(tester, kMoreThanFourLines.indexOf('First') + 5);
    gesture = await tester.startGesture(handlePos, pointer: 7);
    await tester.pump(const Duration(seconds: 1));
    await gesture.moveTo(newHandlePos + const Offset(0.0, -10.0));
    await tester.pump(const Duration(seconds: 1));
    await gesture.up();
    await tester.pump(const Duration(seconds: 1));

    // The text should have scrolled up with the handle to keep the active
    // cursor visible, back to its original position.
    newFirstPos = textOffsetToPosition(tester, kMoreThanFourLines.indexOf('First'));
    newFourthPos = textOffsetToPosition(tester, kMoreThanFourLines.indexOf('Fourth'));
    expect(newFirstPos.dy, firstPos.dy);
    expect(inputBox.hitTest(BoxHitTestResult(), position: inputBox.globalToLocal(newFirstPos)), isTrue);
    expect(inputBox.hitTest(BoxHitTestResult(), position: inputBox.globalToLocal(newFourthPos)), isFalse);
  });

  testWidgets('minLines cannot be greater than maxLines', (WidgetTester tester) async {
    expect(
      () async {
        await tester.pumpWidget(
          overlay(
            child: SizedBox(
              width: 300.0,
              child: SelectableText(
                'abcd',
                minLines: 4,
                maxLines: 3,
              ),
            ),
          ),
        );
      },
      throwsA(isA<AssertionError>().having(
        (AssertionError error) => error.toString(),
        '.toString()',
        contains("minLines can't be greater than maxLines"),
      )),
    );
  });

  testWidgets('Selectable height with minLine', (WidgetTester tester) async {
    await tester.pumpWidget(selectableTextBuilder());

    RenderBox findTextBox() => tester.renderObject(find.byType(SelectableText));

    final RenderBox textBox = findTextBox();
    final Size emptyInputSize = textBox.size;

    // Even if the text is a one liner, minimum height of SelectableText will determined by minLines
    await tester.pumpWidget(selectableTextBuilder(text: 'No wrapping here.', minLines: 2, maxLines: 3));
    expect(findTextBox(), equals(textBox));
    expect(textBox.size.height, emptyInputSize.height * 2);
  });

  testWidgets('Can align to center', (WidgetTester tester) async {
    await tester.pumpWidget(
      overlay(
        child: const SizedBox(
          width: 300.0,
          child: SelectableText(
            'abcd',
            textAlign: TextAlign.center,
          ),
        ),
      ),
    );

    final RenderEditable editable = findRenderEditable(tester);

    final Offset topLeft = editable.localToGlobal(
      editable.getLocalRectForCaret(const TextPosition(offset: 2)).topLeft,
    );

    expect(topLeft.dx, equals(399.0));
  });

  testWidgets('Can align to center within center', (WidgetTester tester) async {
    await tester.pumpWidget(
      overlay(
        child: const SizedBox(
          width: 300.0,
          child: Center(
            child: SelectableText(
              'abcd',
              textAlign: TextAlign.center,
            ),
          ),
        ),
      ),
    );

    final RenderEditable editable = findRenderEditable(tester);

    final Offset topLeft = editable.localToGlobal(
      editable.getLocalRectForCaret(const TextPosition(offset: 2)).topLeft,
    );

    expect(topLeft.dx, equals(399.0));
  });

  testWidgets('Selectable text is skipped during focus traversal', (WidgetTester tester) async {
    final FocusNode firstFieldFocus = FocusNode();
    final FocusNode lastFieldFocus = FocusNode();

    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: Center(
            child: Column(
              children: <Widget>[
                TextField(
                  focusNode: firstFieldFocus,
                  autofocus: true,
                ),
                const SelectableText('some text'),
                TextField(
                  focusNode: lastFieldFocus,
                ),
              ],
            ),
          ),
        ),
      ),
    );

    await tester.pump();

    expect(firstFieldFocus.hasFocus, isTrue);
    expect(lastFieldFocus.hasFocus, isFalse);

    firstFieldFocus.nextFocus();
    await tester.pump();

    // expecting focus to skip straight to the second field
    expect(firstFieldFocus.hasFocus, isFalse);
    expect(lastFieldFocus.hasFocus, isTrue);
  });

  testWidgets('Selectable text identifies as text field in semantics', (WidgetTester tester) async {
    final SemanticsTester semantics = SemanticsTester(tester);

    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: Center(
            child: SelectableText('some text'),
          ),
        ),
      ),
    );

    expect(
      semantics,
      includesNodeWith(
        flags: <SemanticsFlag>[
          SemanticsFlag.isTextField,
          SemanticsFlag.isReadOnly,
          SemanticsFlag.isMultiline,
        ],
      ),
    );

    semantics.dispose();
  });

  testWidgets('Selectable text rich text with spell out in semantics', (WidgetTester tester) async {
    final SemanticsTester semantics = SemanticsTester(tester);

    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: Center(
            child: SelectableText.rich(TextSpan(text: 'some text', spellOut: true)),
          ),
        ),
      ),
    );

    expect(
      semantics,
      includesNodeWith(
        attributedValue: AttributedString(
          'some text',
          attributes: <StringAttribute>[
            SpellOutStringAttribute(range: const TextRange(start: 0, end:9)),
          ],
        ),
        flags: <SemanticsFlag>[
          SemanticsFlag.isTextField,
          SemanticsFlag.isReadOnly,
          SemanticsFlag.isMultiline,
        ],
      ),
    );

    semantics.dispose();
  });

  testWidgets('Selectable text rich text with locale in semantics', (WidgetTester tester) async {
    final SemanticsTester semantics = SemanticsTester(tester);

    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: Center(
            child: SelectableText.rich(TextSpan(text: 'some text', locale: Locale('es', 'MX'))),
          ),
        ),
      ),
    );

    expect(
      semantics,
      includesNodeWith(
        attributedValue: AttributedString(
          'some text',
          attributes: <StringAttribute>[
            LocaleStringAttribute(range: const TextRange(start: 0, end:9), locale: const Locale('es', 'MX')),
          ],
        ),
        flags: <SemanticsFlag>[
          SemanticsFlag.isTextField,
          SemanticsFlag.isReadOnly,
          SemanticsFlag.isMultiline,
        ],
      ),
    );

    semantics.dispose();
  });

  testWidgets('Selectable rich text with gesture recognizer has correct semantics', (WidgetTester tester) async {
    final SemanticsTester semantics = SemanticsTester(tester);
    await tester.pumpWidget(
      overlay(
        child: SelectableText.rich(
          TextSpan(
            children: <TextSpan>[
              const TextSpan(text: 'text'),
              TextSpan(
                text: 'link',
                recognizer: TapGestureRecognizer()
                  ..onTap = () { },
              ),
            ],
          ),
        ),
      ),
    );

    expect(semantics, hasSemantics(TestSemantics.root(
      children: <TestSemantics>[
        TestSemantics.rootChild(
          id: 1,
          actions: <SemanticsAction>[SemanticsAction.longPress],
          textDirection: TextDirection.ltr,
          children: <TestSemantics>[
            TestSemantics(
              id: 2,
              children: <TestSemantics>[
                TestSemantics(
                  id: 3,
                  label: 'text',
                  textDirection: TextDirection.ltr,
                ),
                TestSemantics(
                  id: 4,
                  flags: <SemanticsFlag>[SemanticsFlag.isLink],
                  actions: <SemanticsAction>[SemanticsAction.tap],
                  label: 'link',
                  textDirection: TextDirection.ltr,
                ),
              ],
            ),
          ],
        ),
      ],
    ), ignoreTransform: true, ignoreRect: true));

    semantics.dispose();
  });

  group('Keyboard Tests', () {
    late TextEditingController controller;

    Future<void> setupWidget(WidgetTester tester, String text) async {
      final FocusNode focusNode = FocusNode();
      await tester.pumpWidget(
        MaterialApp(
          home: Material(
            child: RawKeyboardListener(
              focusNode: focusNode,
              child: SelectableText(
                text,
                maxLines: 3,
              ),
            ),
          ),
        ),
      );
      await tester.tap(find.byType(SelectableText));
      await tester.pumpAndSettle();
      final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
      controller = editableTextWidget.controller;
    }

    testWidgets('Shift test 1', (WidgetTester tester) async {
      await setupWidget(tester, 'a big house');

      await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
      await tester.sendKeyDownEvent(LogicalKeyboardKey.arrowLeft);
      expect(controller.selection.extentOffset - controller.selection.baseOffset, -1);
    }, variant: KeySimulatorTransitModeVariant.all());

    testWidgets('Shift test 2', (WidgetTester tester) async {
      await setupWidget(tester, 'abcdefghi');

      controller.selection = const TextSelection.collapsed(offset: 3);
      await tester.pump();

      await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
      await tester.sendKeyDownEvent(LogicalKeyboardKey.arrowRight);
      await tester.pumpAndSettle();
      expect(controller.selection.extentOffset - controller.selection.baseOffset, 1);
    }, variant: KeySimulatorTransitModeVariant.all());

    testWidgets('Control Shift test', (WidgetTester tester) async {
      await setupWidget(tester, 'their big house');

      await tester.sendKeyDownEvent(LogicalKeyboardKey.control);
      await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
      await tester.sendKeyDownEvent(LogicalKeyboardKey.arrowLeft);

      await tester.pumpAndSettle();

      expect(controller.selection.extentOffset - controller.selection.baseOffset, -5);
    }, variant: KeySimulatorTransitModeVariant.all());

    testWidgets('Down and up test', (WidgetTester tester) async {
      await setupWidget(tester, 'a big house');

      await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
      await tester.sendKeyDownEvent(LogicalKeyboardKey.arrowUp);
      await tester.pumpAndSettle();

      expect(controller.selection.extentOffset - controller.selection.baseOffset, -11);

      await tester.sendKeyUpEvent(LogicalKeyboardKey.arrowUp);
      await tester.sendKeyUpEvent(LogicalKeyboardKey.shift);
      await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
      await tester.sendKeyDownEvent(LogicalKeyboardKey.arrowDown);
      await tester.pumpAndSettle();

      expect(controller.selection.extentOffset - controller.selection.baseOffset, 0);
    }, variant: KeySimulatorTransitModeVariant.all());

    testWidgets('Down and up test 2', (WidgetTester tester) async {
      await setupWidget(tester, 'a big house\njumped over a mouse\nOne more line yay');

      controller.selection = const TextSelection.collapsed(offset: 0);
      await tester.pump();

      for (int i = 0; i < 5; i += 1) {
        await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
        await tester.pumpAndSettle();
      }
      await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
      await tester.pumpAndSettle();
      await tester.sendKeyUpEvent(LogicalKeyboardKey.shift);
      await tester.pumpAndSettle();

      expect(controller.selection.extentOffset - controller.selection.baseOffset, 12);

      await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
      await tester.pumpAndSettle();
      await tester.sendKeyUpEvent(LogicalKeyboardKey.shift);
      await tester.pumpAndSettle();

      expect(controller.selection.extentOffset - controller.selection.baseOffset, 32);

      await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
      await tester.pumpAndSettle();
      await tester.sendKeyUpEvent(LogicalKeyboardKey.shift);
      await tester.pumpAndSettle();

      expect(controller.selection.extentOffset - controller.selection.baseOffset, 12);

      await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
      await tester.pumpAndSettle();
      await tester.sendKeyUpEvent(LogicalKeyboardKey.shift);
      await tester.pumpAndSettle();

      expect(controller.selection.extentOffset - controller.selection.baseOffset, 0);

      await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp);
      await tester.pumpAndSettle();
      await tester.sendKeyUpEvent(LogicalKeyboardKey.shift);
      await tester.pumpAndSettle();

      expect(controller.selection.extentOffset - controller.selection.baseOffset, -5);
    }, variant: KeySimulatorTransitModeVariant.all());
  });

  testWidgets('Copy test', (WidgetTester tester) async {
    final FocusNode focusNode = FocusNode();

    String clipboardContent = '';
    tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
      if (methodCall.method == 'Clipboard.setData') {
        clipboardContent = (methodCall.arguments as Map<String, dynamic>)['text'] as String;
      } else if (methodCall.method == 'Clipboard.getData') {
        return <String, dynamic>{'text': clipboardContent};
      }
      return null;
    });
    const String testValue = 'a big house\njumped over a mouse';
    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: RawKeyboardListener(
            focusNode: focusNode,
            child: const SelectableText(
              testValue,
              maxLines: 3,
            ),
          ),
        ),
      ),
    );
    final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
    final TextEditingController controller = editableTextWidget.controller;
    focusNode.requestFocus();
    await tester.pump();

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

    controller.selection = const TextSelection.collapsed(offset: 0);
    await tester.pump();

    // Select the first 5 characters
    await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
    for (int i = 0; i < 5; i += 1) {
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
      await tester.pumpAndSettle();
    }
    await tester.sendKeyUpEvent(LogicalKeyboardKey.shift);

    // Copy them
    await tester.sendKeyDownEvent(LogicalKeyboardKey.controlRight);
    await tester.sendKeyDownEvent(LogicalKeyboardKey.keyC);
    await tester.sendKeyUpEvent(LogicalKeyboardKey.keyC);
    await tester.sendKeyUpEvent(LogicalKeyboardKey.controlRight);
    await tester.pumpAndSettle();

    expect(clipboardContent, 'a big');

    await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
    await tester.pumpAndSettle();
  }, variant: KeySimulatorTransitModeVariant.all());

  testWidgets('Select all test', (WidgetTester tester) async {
    final FocusNode focusNode = FocusNode();
    const String testValue = 'a big house\njumped over a mouse';
    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: RawKeyboardListener(
            focusNode: focusNode,
            child: const SelectableText(
              testValue,
              maxLines: 3,
            ),
          ),
        ),
      ),
    );
    final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
    final TextEditingController controller = editableTextWidget.controller;
    focusNode.requestFocus();
    await tester.pump();

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

    // Select All
    await tester.sendKeyDownEvent(LogicalKeyboardKey.control);
    await tester.sendKeyEvent(LogicalKeyboardKey.keyA);
    await tester.sendKeyUpEvent(LogicalKeyboardKey.control);
    await tester.pumpAndSettle();

    expect(controller.selection.baseOffset, 0);
    expect(controller.selection.extentOffset, 31);
  }, variant: KeySimulatorTransitModeVariant.all());

  testWidgets('keyboard selection should call onSelectionChanged', (WidgetTester tester) async {
    final FocusNode focusNode = FocusNode();
    TextSelection? newSelection;
    const String testValue = 'a big house\njumped over a mouse';
    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: RawKeyboardListener(
            focusNode: focusNode,
            child: SelectableText(
              testValue,
              maxLines: 3,
              onSelectionChanged: (TextSelection selection, SelectionChangedCause? cause) {
                expect(newSelection, isNull);
                newSelection = selection;
              },
            ),
          ),
        ),
      ),
    );
    final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
    final TextEditingController controller = editableTextWidget.controller;
    focusNode.requestFocus();
    await tester.pump();

    await tester.tap(find.byType(SelectableText));
    await tester.pumpAndSettle();
    expect(newSelection!.baseOffset, 31);
    expect(newSelection!.extentOffset, 31);
    newSelection = null;

    controller.selection = const TextSelection.collapsed(offset: 0);
    await tester.pump();

    // Select the first 5 characters
    await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
    for (int i = 0; i < 5; i += 1) {
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowRight);
      await tester.pumpAndSettle();
      expect(newSelection!.baseOffset, 0);
      expect(newSelection!.extentOffset, i + 1);
      newSelection = null;
    }
  }, variant: KeySimulatorTransitModeVariant.all());

  testWidgets('Changing positions of selectable text', (WidgetTester tester) async {
    final FocusNode focusNode = FocusNode();
    final List<RawKeyEvent> events = <RawKeyEvent>[];

    final Key key1 = UniqueKey();
    final Key key2 = UniqueKey();

    await tester.pumpWidget(
      MaterialApp(
        home:
        Material(
          child: RawKeyboardListener(
            focusNode: focusNode,
            onKey: events.add,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: <Widget>[
                SelectableText(
                  'a big house',
                  key: key1,
                  maxLines: 3,
                ),
                SelectableText(
                  'another big house',
                  key: key2,
                  maxLines: 3,
                ),
              ],
            ),
          ),
        ),
      ),
    );

    EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
    TextEditingController c1 = editableTextWidget.controller;

    await tester.tap(find.byType(EditableText).first);
    await tester.pumpAndSettle();

    await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
    for (int i = 0; i < 5; i += 1) {
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowLeft);
      await tester.pumpAndSettle();
    }
    await tester.sendKeyUpEvent(LogicalKeyboardKey.shift);
    await tester.pumpAndSettle();

    expect(c1.selection.extentOffset - c1.selection.baseOffset, -5);

    await tester.pumpWidget(
      MaterialApp(
        home:
        Material(
          child: RawKeyboardListener(
            focusNode: focusNode,
            onKey: events.add,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: <Widget>[
                SelectableText(
                  'another big house',
                  key: key2,
                  maxLines: 3,
                ),
                SelectableText(
                  'a big house',
                  key: key1,
                  maxLines: 3,
                ),
              ],
            ),
          ),
        ),
      ),
    );

    await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
    for (int i = 0; i < 5; i += 1) {
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowLeft);
    }
    await tester.sendKeyUpEvent(LogicalKeyboardKey.shift);
    await tester.pumpAndSettle();

    editableTextWidget = tester.widget(find.byType(EditableText).last);
    c1 = editableTextWidget.controller;

    expect(c1.selection.extentOffset - c1.selection.baseOffset, -10);
  }, variant: KeySimulatorTransitModeVariant.all());

  testWidgets('Changing focus test', (WidgetTester tester) async {
    final FocusNode focusNode = FocusNode();
    final List<RawKeyEvent> events = <RawKeyEvent>[];

    final Key key1 = UniqueKey();
    final Key key2 = UniqueKey();

    await tester.pumpWidget(
      MaterialApp(
        home:
        Material(
          child: RawKeyboardListener(
            focusNode: focusNode,
            onKey: events.add,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: <Widget>[
                SelectableText(
                  'a big house',
                  key: key1,
                  maxLines: 3,
                ),
                SelectableText(
                  'another big house',
                  key: key2,
                  maxLines: 3,
                ),
              ],
            ),
          ),
        ),
      ),
    );

    final EditableText editableTextWidget1 = tester.widget(find.byType(EditableText).first);
    final TextEditingController c1 = editableTextWidget1.controller;

    final EditableText editableTextWidget2 = tester.widget(find.byType(EditableText).last);
    final TextEditingController c2 = editableTextWidget2.controller;

    await tester.tap(find.byType(SelectableText).first);
    await tester.pumpAndSettle();

    await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
    for (int i = 0; i < 5; i += 1) {
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowLeft);
      await tester.pumpAndSettle();
    }
    await tester.sendKeyUpEvent(LogicalKeyboardKey.shift);
    await tester.pumpAndSettle();

    expect(c1.selection.extentOffset - c1.selection.baseOffset, -5);
    expect(c2.selection.extentOffset - c2.selection.baseOffset, 0);

    await tester.tap(find.byType(SelectableText).last);
    await tester.pumpAndSettle();

    await tester.sendKeyDownEvent(LogicalKeyboardKey.shift);
    for (int i = 0; i < 5; i += 1) {
      await tester.sendKeyEvent(LogicalKeyboardKey.arrowLeft);
      await tester.pumpAndSettle();
    }
    await tester.sendKeyUpEvent(LogicalKeyboardKey.shift);
    await tester.pumpAndSettle();

    expect(c1.selection.extentOffset - c1.selection.baseOffset, -5);
    expect(c2.selection.extentOffset - c2.selection.baseOffset, -5);
  }, variant: KeySimulatorTransitModeVariant.all());

  testWidgets('Caret works when maxLines is null', (WidgetTester tester) async {
    await tester.pumpWidget(
        overlay(
          child: const SelectableText(
            'x',
          ),
        ),
    );

    final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
    final TextEditingController controller = editableTextWidget.controller;

    expect(controller.selection.baseOffset, -1);

    // Tap the selection handle to bring up the "paste / select all" menu.
    await tester.tapAt(textOffsetToPosition(tester, 0));
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 200)); // skip past the frame where the opacity is

    // Confirm that the selection was updated.
    expect(controller.selection.baseOffset, 0);
  });

  testWidgets('SelectableText baseline alignment no-strut', (WidgetTester tester) async {
    final Key keyA = UniqueKey();
    final Key keyB = UniqueKey();

    await tester.pumpWidget(
      overlay(
        child: Row(
          crossAxisAlignment: CrossAxisAlignment.baseline,
          textBaseline: TextBaseline.alphabetic,
          children: <Widget>[
            Expanded(
              child: SelectableText(
                'A',
                key: keyA,
                style: const TextStyle(fontSize: 10.0),
                strutStyle: StrutStyle.disabled,
              ),
            ),
            const Text(
              'abc',
              style: TextStyle(fontSize: 20.0),
            ),
            Expanded(
              child: SelectableText(
                'B',
                key: keyB,
                style: const TextStyle(fontSize: 30.0),
                strutStyle: StrutStyle.disabled,
              ),
            ),
          ],
        ),
      ),
    );

    // The Ahem font extends 0.2 * fontSize below the baseline.
    // So the three row elements line up like this:
    //
    //  A  abc  B
    //  ---------   baseline
    //  2  4    6   space below the baseline = 0.2 * fontSize
    //  ---------   rowBottomY

    final double rowBottomY = tester.getBottomLeft(find.byType(Row)).dy;
    expect(tester.getBottomLeft(find.byKey(keyA)).dy, moreOrLessEquals(rowBottomY - 4.0, epsilon: 1e-3));
    expect(tester.getBottomLeft(find.text('abc')).dy, moreOrLessEquals(rowBottomY - 2.0, epsilon: 1e-3));
    expect(tester.getBottomLeft(find.byKey(keyB)).dy, rowBottomY);
  });

  testWidgets('SelectableText baseline alignment', (WidgetTester tester) async {
    final Key keyA = UniqueKey();
    final Key keyB = UniqueKey();

    await tester.pumpWidget(
      overlay(
        child: Row(
          crossAxisAlignment: CrossAxisAlignment.baseline,
          textBaseline: TextBaseline.alphabetic,
          children: <Widget>[
            Expanded(
              child: SelectableText(
                'A',
                key: keyA,
                style: const TextStyle(fontSize: 10.0),
              ),
            ),
            const Text(
              'abc',
              style: TextStyle(fontSize: 20.0),
            ),
            Expanded(
              child: SelectableText(
                'B',
                key: keyB,
                style: const TextStyle(fontSize: 30.0),
              ),
            ),
          ],
        ),
      ),
    );

    // The Ahem font extends 0.2 * fontSize below the baseline.
    // So the three row elements line up like this:
    //
    //  A  abc  B
    //  ---------   baseline
    //  2  4    6   space below the baseline = 0.2 * fontSize
    //  ---------   rowBottomY

    final double rowBottomY = tester.getBottomLeft(find.byType(Row)).dy;
    expect(tester.getBottomLeft(find.byKey(keyA)).dy, moreOrLessEquals(rowBottomY - 4.0, epsilon: 1e-3));
    expect(tester.getBottomLeft(find.text('abc')).dy, moreOrLessEquals(rowBottomY - 2.0, epsilon: 1e-3));
    expect(tester.getBottomLeft(find.byKey(keyB)).dy, rowBottomY);
  });

  testWidgets('SelectableText semantics', (WidgetTester tester) async {
    final SemanticsTester semantics = SemanticsTester(tester);
    final Key key = UniqueKey();

    await tester.pumpWidget(
      overlay(
        child: SelectableText(
          'Guten Tag',
          key: key,
        ),
      ),
    );

    final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
    final TextEditingController controller = editableTextWidget.controller;

    expect(semantics, hasSemantics(TestSemantics.root(
      children: <TestSemantics>[
        TestSemantics.rootChild(
          id: 1,
          textDirection: TextDirection.ltr,
          value: 'Guten Tag',
          actions: <SemanticsAction>[
            SemanticsAction.longPress,
          ],
          flags: <SemanticsFlag>[
            SemanticsFlag.isTextField,
            SemanticsFlag.isReadOnly,
            SemanticsFlag.isMultiline,
          ],
        ),
      ],
    ), ignoreTransform: true, ignoreRect: true));

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

    controller.selection = const TextSelection.collapsed(offset: 9);
    await tester.pump();

    expect(semantics, hasSemantics(TestSemantics.root(
      children: <TestSemantics>[
        TestSemantics.rootChild(
          id: 1,
          textDirection: TextDirection.ltr,
          value: 'Guten Tag',
          textSelection: const TextSelection.collapsed(offset: 9),
          actions: <SemanticsAction>[
            SemanticsAction.longPress,
            SemanticsAction.moveCursorBackwardByCharacter,
            SemanticsAction.moveCursorBackwardByWord,
            SemanticsAction.setSelection,
          ],
          flags: <SemanticsFlag>[
            SemanticsFlag.isReadOnly,
            SemanticsFlag.isTextField,
            SemanticsFlag.isMultiline,
            SemanticsFlag.isFocused,
          ],
        ),
      ],
    ), ignoreTransform: true, ignoreRect: true));

    controller.selection = const TextSelection.collapsed(offset: 4);
    await tester.pump();

    expect(semantics, hasSemantics(TestSemantics.root(
      children: <TestSemantics>[
        TestSemantics.rootChild(
          id: 1,
          textDirection: TextDirection.ltr,
          textSelection: const TextSelection.collapsed(offset: 4),
          value: 'Guten Tag',
          actions: <SemanticsAction>[
            SemanticsAction.longPress,
            SemanticsAction.moveCursorBackwardByCharacter,
            SemanticsAction.moveCursorForwardByCharacter,
            SemanticsAction.moveCursorBackwardByWord,
            SemanticsAction.moveCursorForwardByWord,
            SemanticsAction.setSelection,
          ],
          flags: <SemanticsFlag>[
            SemanticsFlag.isReadOnly,
            SemanticsFlag.isTextField,
            SemanticsFlag.isMultiline,
            SemanticsFlag.isFocused,
          ],
        ),
      ],
    ), ignoreTransform: true, ignoreRect: true));

    controller.selection = const TextSelection.collapsed(offset: 0);
    await tester.pump();

    expect(semantics, hasSemantics(TestSemantics.root(
      children: <TestSemantics>[
        TestSemantics.rootChild(
          id: 1,
          textDirection: TextDirection.ltr,
          textSelection: const TextSelection.collapsed(offset: 0),
          value: 'Guten Tag',
          actions: <SemanticsAction>[
            SemanticsAction.longPress,
            SemanticsAction.moveCursorForwardByCharacter,
            SemanticsAction.moveCursorForwardByWord,
            SemanticsAction.setSelection,
          ],
          flags: <SemanticsFlag>[
            SemanticsFlag.isReadOnly,
            SemanticsFlag.isTextField,
            SemanticsFlag.isMultiline,
            SemanticsFlag.isFocused,
          ],
        ),
      ],
    ), ignoreTransform: true, ignoreRect: true));

    semantics.dispose();
  });

  testWidgets('SelectableText semantics, with semanticsLabel', (WidgetTester tester) async {
    final SemanticsTester semantics = SemanticsTester(tester);
    final Key key = UniqueKey();

    await tester.pumpWidget(
      overlay(
        child: SelectableText(
          'Guten Tag',
          semanticsLabel: 'German greeting for good day',
          key: key,
        ),
      ),
    );

    expect(semantics, hasSemantics(TestSemantics.root(
      children: <TestSemantics>[
        TestSemantics(
          id: 1,
          actions: <SemanticsAction>[SemanticsAction.longPress],
          label: 'German greeting for good day',
          textDirection: TextDirection.ltr,
        ),
      ],
    ), ignoreTransform: true, ignoreRect: true));
  });

  testWidgets('SelectableText semantics, enableInteractiveSelection = false', (WidgetTester tester) async {
    final SemanticsTester semantics = SemanticsTester(tester);
    final Key key = UniqueKey();

    await tester.pumpWidget(
      overlay(
        child: SelectableText(
          'Guten Tag',
          key: key,
          enableInteractiveSelection: false,
        ),
      ),
    );

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

    expect(semantics, hasSemantics(TestSemantics.root(
      children: <TestSemantics>[
        TestSemantics.rootChild(
          id: 1,
          value: 'Guten Tag',
          textDirection: TextDirection.ltr,
          actions: <SemanticsAction>[
            SemanticsAction.longPress,
            // Absent the following because enableInteractiveSelection: false
            // SemanticsAction.moveCursorBackwardByCharacter,
            // SemanticsAction.moveCursorBackwardByWord,
            // SemanticsAction.setSelection,
            // SemanticsAction.paste,
          ],
          flags: <SemanticsFlag>[
            SemanticsFlag.isReadOnly,
            SemanticsFlag.isTextField,
            SemanticsFlag.isMultiline,
            // SelectableText act like a text widget when enableInteractiveSelection
            // is false. It will not respond to any pointer event.
            // SemanticsFlag.isFocused,
          ],
        ),
      ],
    ), ignoreTransform: true, ignoreRect: true));

    semantics.dispose();
  });

  testWidgets('SelectableText semantics for selections', (WidgetTester tester) async {
    final SemanticsTester semantics = SemanticsTester(tester);
    final Key key = UniqueKey();

    await tester.pumpWidget(
      overlay(
        child: SelectableText(
          'Hello',
          key: key,
        ),
      ),
    );

    final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
    final TextEditingController controller = editableTextWidget.controller;

    expect(semantics, hasSemantics(TestSemantics.root(
      children: <TestSemantics>[
        TestSemantics.rootChild(
          id: 1,
          value: 'Hello',
          textDirection: TextDirection.ltr,
          actions: <SemanticsAction>[
            SemanticsAction.longPress,
          ],
          flags: <SemanticsFlag>[
            SemanticsFlag.isReadOnly,
            SemanticsFlag.isTextField,
            SemanticsFlag.isMultiline,
          ],
        ),
      ],
    ), ignoreTransform: true, ignoreRect: true));

    // Focus the selectable text
    await tester.tap(find.byKey(key));
    await tester.pump();

    controller.selection = const TextSelection.collapsed(offset: 5);
    await tester.pump();

    expect(semantics, hasSemantics(TestSemantics.root(
      children: <TestSemantics>[
        TestSemantics.rootChild(
          id: 1,
          value: 'Hello',
          textSelection: const TextSelection.collapsed(offset: 5),
          textDirection: TextDirection.ltr,
          actions: <SemanticsAction>[
            SemanticsAction.longPress,
            SemanticsAction.moveCursorBackwardByCharacter,
            SemanticsAction.moveCursorBackwardByWord,
            SemanticsAction.setSelection,
          ],
          flags: <SemanticsFlag>[
            SemanticsFlag.isReadOnly,
            SemanticsFlag.isTextField,
            SemanticsFlag.isMultiline,
            SemanticsFlag.isFocused,
          ],
        ),
      ],
    ), ignoreTransform: true, ignoreRect: true));

    controller.selection = const TextSelection(baseOffset: 5, extentOffset: 3);
    await tester.pump();

    expect(semantics, hasSemantics(TestSemantics.root(
      children: <TestSemantics>[
        TestSemantics.rootChild(
          id: 1,
          value: 'Hello',
          textSelection: const TextSelection(baseOffset: 5, extentOffset: 3),
          textDirection: TextDirection.ltr,
          actions: <SemanticsAction>[
            SemanticsAction.longPress,
            SemanticsAction.moveCursorBackwardByCharacter,
            SemanticsAction.moveCursorForwardByCharacter,
            SemanticsAction.moveCursorBackwardByWord,
            SemanticsAction.moveCursorForwardByWord,
            SemanticsAction.setSelection,
            SemanticsAction.copy,
          ],
          flags: <SemanticsFlag>[
            SemanticsFlag.isReadOnly,
            SemanticsFlag.isTextField,
            SemanticsFlag.isMultiline,
            SemanticsFlag.isFocused,
          ],
        ),
      ],
    ), ignoreTransform: true, ignoreRect: true));

    semantics.dispose();
  });

  testWidgets('semantic nodes of offscreen recognizers are marked hidden', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/100395.
    final SemanticsTester semantics = SemanticsTester(tester);
    const TextStyle textStyle = TextStyle(fontFamily: 'Ahem', fontSize: 200);
    const String onScreenText = 'onscreen\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n';
    const String offScreenText = 'off screen';
    final ScrollController controller = ScrollController();
    await tester.pumpWidget(
      MaterialApp(
        home: SingleChildScrollView(
          controller: controller,
          child: SelectableText.rich(
            TextSpan(
              children: <TextSpan>[
                const TextSpan(text: onScreenText),
                TextSpan(
                  text: offScreenText,
                  recognizer: TapGestureRecognizer()..onTap = () { },
                ),
              ],
              style: textStyle,
            ),
            textDirection: TextDirection.ltr,
          ),
        )
      ),
    );

    final TestSemantics expectedSemantics = TestSemantics.root(
      children: <TestSemantics>[
        TestSemantics(
          textDirection: TextDirection.ltr,
          children: <TestSemantics>[
            TestSemantics(
              children: <TestSemantics>[
                TestSemantics(
                  flags: <SemanticsFlag>[SemanticsFlag.scopesRoute],
                  children: <TestSemantics>[
                    TestSemantics(
                      flags: <SemanticsFlag>[SemanticsFlag.hasImplicitScrolling],
                      actions: <SemanticsAction>[SemanticsAction.scrollUp],
                      children: <TestSemantics>[
                        TestSemantics(
                          actions: <SemanticsAction>[SemanticsAction.longPress],
                          children: <TestSemantics>[
                            TestSemantics(
                              children: <TestSemantics>[
                                TestSemantics(
                                  label: 'onscreen\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n',
                                  textDirection: TextDirection.ltr,
                                ),
                                TestSemantics(
                                  flags: <SemanticsFlag>[
                                    SemanticsFlag.isHidden,
                                    SemanticsFlag.isLink,
                                  ],
                                  actions: <SemanticsAction>[SemanticsAction.tap],
                                  label: 'off screen',
                                  textDirection: TextDirection.ltr,
                                ),
                              ],
                            ),
                          ],
                        ),
                      ],
                    ),
                  ],
                ),
              ],
            ),
          ],
        ),
      ],
    );
    expect(
      semantics,
      hasSemantics(
        expectedSemantics,
        ignoreTransform: true,
        ignoreId: true,
        ignoreRect: true,
      ),
    );

    // Test show on screen.
    expect(controller.offset, 0.0);
    tester.binding.pipelineOwner.semanticsOwner!.performAction(8, SemanticsAction.showOnScreen);
    await tester.pumpAndSettle();
    expect(controller.offset != 0.0, isTrue);

    semantics.dispose();
  });

  testWidgets('SelectableText change selection with semantics', (WidgetTester tester) async {
    final SemanticsTester semantics = SemanticsTester(tester);
    final SemanticsOwner semanticsOwner = tester.binding.pipelineOwner.semanticsOwner!;
    final Key key = UniqueKey();

    await tester.pumpWidget(
      overlay(
        child: SelectableText(
          'Hello',
          key: key,
        ),
      ),
    );

    final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
    final TextEditingController controller = editableTextWidget.controller;

    // Focus the selectable text
    await tester.tap(find.byKey(key));
    await tester.pump();

    controller.selection = const TextSelection(baseOffset: 5, extentOffset: 5);
    await tester.pump();

    const int inputFieldId = 1;

    expect(semantics, hasSemantics(TestSemantics.root(
      children: <TestSemantics>[
        TestSemantics.rootChild(
          id: inputFieldId,
          value: 'Hello',
          textSelection: const TextSelection.collapsed(offset: 5),
          textDirection: TextDirection.ltr,
          actions: <SemanticsAction>[
            SemanticsAction.longPress,
            SemanticsAction.moveCursorBackwardByCharacter,
            SemanticsAction.moveCursorBackwardByWord,
            SemanticsAction.setSelection,
          ],
          flags: <SemanticsFlag>[
            SemanticsFlag.isReadOnly,
            SemanticsFlag.isTextField,
            SemanticsFlag.isMultiline,
            SemanticsFlag.isFocused,
          ],
        ),
      ],
    ), ignoreTransform: true, ignoreRect: true));

    // move cursor back once
    semanticsOwner.performAction(inputFieldId, SemanticsAction.setSelection, <dynamic, dynamic>{
      'base': 4,
      'extent': 4,
    });
    await tester.pump();
    expect(controller.selection, const TextSelection.collapsed(offset: 4));

    // move cursor to front
    semanticsOwner.performAction(inputFieldId, SemanticsAction.setSelection, <dynamic, dynamic>{
      'base': 0,
      'extent': 0,
    });
    await tester.pump();
    expect(controller.selection, const TextSelection.collapsed(offset: 0));

    // select all
    semanticsOwner.performAction(inputFieldId, SemanticsAction.setSelection, <dynamic, dynamic>{
      'base': 0,
      'extent': 5,
    });
    await tester.pump();
    expect(controller.selection, const TextSelection(baseOffset: 0, extentOffset: 5));
    expect(semantics, hasSemantics(TestSemantics.root(
      children: <TestSemantics>[
        TestSemantics.rootChild(
          id: inputFieldId,
          value: 'Hello',
          textSelection: const TextSelection(baseOffset: 0, extentOffset: 5),
          textDirection: TextDirection.ltr,
          actions: <SemanticsAction>[
            SemanticsAction.longPress,
            SemanticsAction.moveCursorBackwardByCharacter,
            SemanticsAction.moveCursorBackwardByWord,
            SemanticsAction.setSelection,
            SemanticsAction.copy,
          ],
          flags: <SemanticsFlag>[
            SemanticsFlag.isReadOnly,
            SemanticsFlag.isTextField,
            SemanticsFlag.isMultiline,
            SemanticsFlag.isFocused,
          ],
        ),
      ],
    ), ignoreTransform: true, ignoreRect: true));

    semantics.dispose();
  });

  testWidgets('Can activate SelectableText with explicit controller via semantics', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/17801

    const String testValue = 'Hello';

    final SemanticsTester semantics = SemanticsTester(tester);
    final SemanticsOwner semanticsOwner = tester.binding.pipelineOwner.semanticsOwner!;
    final Key key = UniqueKey();

    await tester.pumpWidget(
      overlay(
        child: SelectableText(
          testValue,
          key: key,
        ),
      ),
    );

    const int inputFieldId = 1;

    expect(semantics, hasSemantics(
      TestSemantics.root(
        children: <TestSemantics>[
          TestSemantics(
            id: inputFieldId,
            flags: <SemanticsFlag>[
              SemanticsFlag.isReadOnly,
              SemanticsFlag.isTextField,
              SemanticsFlag.isMultiline,
            ],
            actions: <SemanticsAction>[SemanticsAction.longPress],
            value: testValue,
            textDirection: TextDirection.ltr,
          ),
        ],
      ),
      ignoreRect: true, ignoreTransform: true,
    ));

    semanticsOwner.performAction(inputFieldId, SemanticsAction.longPress);
    await tester.pump();

    expect(semantics, hasSemantics(
      TestSemantics.root(
        children: <TestSemantics>[
          TestSemantics(
            id: inputFieldId,
            flags: <SemanticsFlag>[
              SemanticsFlag.isReadOnly,
              SemanticsFlag.isTextField,
              SemanticsFlag.isMultiline,
              SemanticsFlag.isFocused,
            ],
            actions: <SemanticsAction>[
              SemanticsAction.longPress,
              SemanticsAction.moveCursorBackwardByCharacter,
              SemanticsAction.moveCursorBackwardByWord,
              SemanticsAction.setSelection,
            ],
            value: testValue,
            textDirection: TextDirection.ltr,
            textSelection: const TextSelection(
              baseOffset: testValue.length,
              extentOffset: testValue.length,
            ),
          ),
        ],
      ),
      ignoreRect: true, ignoreTransform: true,
    ));

    semantics.dispose();
  });

  testWidgets('SelectableText throws when not descended from a MediaQuery widget', (WidgetTester tester) async {
    const Widget selectableText = SelectableText('something');
    await tester.pumpWidget(selectableText);
    final dynamic exception = tester.takeException();
    expect(exception, isFlutterError);
    expect(exception.toString(), startsWith('No MediaQuery widget ancestor found.\nSelectableText widgets require a MediaQuery widget ancestor.'));
  });

  testWidgets('onTap is called upon tap', (WidgetTester tester) async {
    int tapCount = 0;
    await tester.pumpWidget(
      overlay(
        child: SelectableText(
          'something',
          onTap: () {
            tapCount += 1;
          },
        ),
      ),
    );

    expect(tapCount, 0);
    await tester.tap(find.byType(SelectableText));
    // Wait a bit so they're all single taps and not double taps.
    await tester.pump(const Duration(milliseconds: 300));
    await tester.tap(find.byType(SelectableText));
    await tester.pump(const Duration(milliseconds: 300));
    await tester.tap(find.byType(SelectableText));
    await tester.pump(const Duration(milliseconds: 300));
    expect(tapCount, 3);
  });

  testWidgets('SelectableText style is merged with default text style', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/23994
    final TextStyle defaultStyle = TextStyle(
      color: Colors.blue[500],
    );
    Widget buildFrame(TextStyle style) {
      return MaterialApp(
        home: Material(
          child: DefaultTextStyle (
            style: defaultStyle,
            child: Center(
              child: SelectableText(
                'something',
                style: style,
              ),
            ),
          ),
        ),
      );
    }

    // Empty TextStyle is overridden by theme
    await tester.pumpWidget(buildFrame(const TextStyle()));
    EditableText editableText = tester.widget(find.byType(EditableText));
    expect(editableText.style.color, defaultStyle.color);
    expect(editableText.style.background, defaultStyle.background);
    expect(editableText.style.shadows, defaultStyle.shadows);
    expect(editableText.style.decoration, defaultStyle.decoration);
    expect(editableText.style.locale, defaultStyle.locale);
    expect(editableText.style.wordSpacing, defaultStyle.wordSpacing);

    // Properties set on TextStyle override theme
    const Color setColor = Colors.red;
    await tester.pumpWidget(buildFrame(const TextStyle(color: setColor)));
    editableText = tester.widget(find.byType(EditableText));
    expect(editableText.style.color, setColor);

    // inherit: false causes nothing to be merged in from theme
    await tester.pumpWidget(buildFrame(const TextStyle(
      fontSize: 24.0,
      textBaseline: TextBaseline.alphabetic,
      inherit: false,
    )));
    editableText = tester.widget(find.byType(EditableText));
    expect(editableText.style.color, isNull);
  });

  testWidgets('style enforces required fields', (WidgetTester tester) async {
    Widget buildFrame(TextStyle style) {
      return MaterialApp(
        home: Material(
          child: SelectableText(
            'something',
            style: style,
          ),
        ),
      );
    }

    await tester.pumpWidget(buildFrame(const TextStyle(
      inherit: false,
      fontSize: 12.0,
      textBaseline: TextBaseline.alphabetic,
    )));
    expect(tester.takeException(), isNull);

    // With inherit not set to false, will pickup required fields from theme
    await tester.pumpWidget(buildFrame(const TextStyle(
      fontSize: 12.0,
    )));
    expect(tester.takeException(), isNull);

    await tester.pumpWidget(buildFrame(const TextStyle(
      inherit: false,
      fontSize: 12.0,
    )));
    expect(tester.takeException(), isNotNull);
  });

  testWidgets(
    'tap moves cursor to the edge of the word it tapped',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        const MaterialApp(
          home: Material(
            child: Center(
              child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
            ),
          ),
        ),
      );

      final Offset selectableTextStart = tester.getTopLeft(find.byType(SelectableText));

      await tester.tapAt(selectableTextStart + const Offset(50.0, 5.0));
      await tester.pump();

      final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
      final TextEditingController controller = editableTextWidget.controller;
      // We moved the cursor.
      expect(
        controller.selection,
        const TextSelection.collapsed(offset: 7, affinity: TextAffinity.upstream),
      );

      // But don't trigger the toolbar.
      expect(find.byType(CupertinoButton), findsNothing);
    },
    variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }),
  );

  testWidgets(
    'tap moves cursor to the position tapped (Android)',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        const MaterialApp(
          home: Material(
            child: Center(
              child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
            ),
          ),
        ),
      );

      final Offset selectableTextStart = tester.getTopLeft(find.byType(SelectableText));

      await tester.tapAt(selectableTextStart + const Offset(50.0, 5.0));
      await tester.pump();

      final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
      final TextEditingController controller = editableTextWidget.controller;

      // We moved the cursor.
      expect(
        controller.selection,
        const TextSelection.collapsed(offset: 4, affinity: TextAffinity.upstream),
      );

      // But don't trigger the toolbar.
      expect(find.byType(TextButton), findsNothing);
    },
  );

  testWidgets(
    'two slow taps do not trigger a word selection',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        const MaterialApp(
          home: Material(
            child: Center(
              child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
            ),
          ),
        ),
      );

      final Offset selectableTextStart = tester.getTopLeft(find.byType(SelectableText));

      await tester.tapAt(selectableTextStart + const Offset(50.0, 5.0));
      await tester.pump(const Duration(milliseconds: 500));
      await tester.tapAt(selectableTextStart + const Offset(50.0, 5.0));
      await tester.pump();

      final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
      final TextEditingController controller = editableTextWidget.controller;

      // Plain collapsed selection.
      expect(
        controller.selection,
        const TextSelection.collapsed(offset: 7, affinity: TextAffinity.upstream),
      );

      // No toolbar.
      expect(find.byType(CupertinoButton), findsNothing);
    },
    variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }),
  );

  testWidgets(
    'double tap selects word and first tap of double tap moves cursor',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        const MaterialApp(
          home: Material(
            child: Center(
              child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
            ),
          ),
        ),
      );

      final Offset selectableTextStart = tester.getTopLeft(find.byType(SelectableText));

      // This tap just puts the cursor somewhere different than where the double
      // tap will occur to test that the double tap moves the existing cursor first.
      await tester.tapAt(selectableTextStart + const Offset(50.0, 5.0));
      await tester.pump(const Duration(milliseconds: 500));

      await tester.tapAt(selectableTextStart + const Offset(150.0, 5.0));
      await tester.pump(const Duration(milliseconds: 50));

      final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
      final TextEditingController controller = editableTextWidget.controller;

      // First tap moved the cursor.
      expect(
        controller.selection,
        const TextSelection.collapsed(offset: 12, affinity: TextAffinity.upstream),
      );
      await tester.tapAt(selectableTextStart + const Offset(150.0, 5.0));
      await tester.pump();

      // Second tap selects the word around the cursor.
      expect(
        controller.selection,
        const TextSelection(baseOffset: 8, extentOffset: 12),
      );

      // Selected text shows 1 toolbar buttons.
      expect(find.byType(CupertinoButton), findsNWidgets(1));
    },
    variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }),
  );

  testWidgets(
    'double tap selects word and first tap of double tap moves cursor and shows toolbar (Android)',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        const MaterialApp(
          home: Material(
            child: Center(
              child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
            ),
          ),
        ),
      );

      final Offset selectableTextStart = tester.getTopLeft(find.byType(SelectableText));

      // This tap just puts the cursor somewhere different than where the double
      // tap will occur to test that the double tap moves the existing cursor first.
      await tester.tapAt(selectableTextStart + const Offset(50.0, 5.0));
      await tester.pump(const Duration(milliseconds: 500));

      await tester.tapAt(selectableTextStart + const Offset(150.0, 5.0));
      await tester.pump(const Duration(milliseconds: 50));

      final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
      final TextEditingController controller = editableTextWidget.controller;

      // First tap moved the cursor.
      expect(
        controller.selection,
        const TextSelection.collapsed(offset: 11, affinity: TextAffinity.upstream),
      );
      await tester.tapAt(selectableTextStart + const Offset(150.0, 5.0));
      await tester.pump();

      // Second tap selects the word around the cursor.
      expect(
        controller.selection,
        const TextSelection(baseOffset: 8, extentOffset: 12),
      );

      // Selected text shows 2 toolbar buttons: copy, select all
      expect(find.byType(TextButton), findsNWidgets(2));
    },
  );

  testWidgets(
    'double tap on top of cursor also selects word (Android)',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        const MaterialApp(
          home: Material(
            child: Center(
              child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
            ),
          ),
        ),
      );

      // Tap to put the cursor after the "w".
      const int index = 3;
      await tester.tapAt(textOffsetToPosition(tester, index));
      await tester.pump(const Duration(milliseconds: 500));

      final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
      final TextEditingController controller = editableTextWidget.controller;

      expect(
        controller.selection,
        const TextSelection.collapsed(offset: index),
      );

      // Double tap on the same location.
      await tester.tapAt(textOffsetToPosition(tester, index));
      await tester.pump(const Duration(milliseconds: 50));

      // First tap doesn't change the selection
      expect(
        controller.selection,
        const TextSelection.collapsed(offset: index),
      );

      // Second tap selects the word around the cursor.
      await tester.tapAt(textOffsetToPosition(tester, index));
      await tester.pump();
      expect(
        controller.selection,
        const TextSelection(baseOffset: 0, extentOffset: 7),
      );

      // Selected text shows 2 toolbar buttons: copy, select all
      expect(find.byType(TextButton), findsNWidgets(2));
    },
  );

  testWidgets(
    'double tap hold selects word',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        const MaterialApp(
          home: Material(
            child: Center(
              child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
            ),
          ),
        ),
      );

      final Offset selectableTextStart = tester.getTopLeft(find.byType(SelectableText));

      await tester.tapAt(selectableTextStart + const Offset(150.0, 5.0));
      await tester.pump(const Duration(milliseconds: 50));
      final TestGesture gesture =
      await tester.startGesture(selectableTextStart + const Offset(150.0, 5.0));
      // Hold the press.
      await tester.pump(const Duration(milliseconds: 500));

      final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
      final TextEditingController controller = editableTextWidget.controller;

      expect(
        controller.selection,
        const TextSelection(baseOffset: 8, extentOffset: 12),
      );

      // Selected text shows 1 toolbar buttons.
      expect(find.byType(CupertinoButton), findsNWidgets(1));

      await gesture.up();
      await tester.pump();

      // Still selected.
      expect(
        controller.selection,
        const TextSelection(baseOffset: 8, extentOffset: 12),
      );
      // The toolbar is still showing.
      expect(find.byType(CupertinoButton), findsNWidgets(1));
    },
    variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }),
  );

  testWidgets(
    'double tap selects word with semantics label',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        const MaterialApp(
          home: Material(
            child: Center(
              child: SelectableText.rich(
                TextSpan(text: 'Atwater Peel Sherbrooke Bonaventure', semanticsLabel: ''),
              ),
            ),
          ),
        ),
      );

      final Offset selectableTextStart = tester.getTopLeft(find.byType(SelectableText));

      await tester.tapAt(selectableTextStart + const Offset(220.0, 5.0));
      await tester.pump(const Duration(milliseconds: 50));
      await tester.tapAt(selectableTextStart + const Offset(220.0, 5.0));
      await tester.pump();

      final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
      final TextEditingController controller = editableTextWidget.controller;

      expect(
        controller.selection,
        const TextSelection(baseOffset: 13, extentOffset: 23),
      );
    },
    variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }),
  );

  testWidgets(
    'tap after a double tap select is not affected (iOS)',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        const MaterialApp(
          home: Material(
            child: Center(
              child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
            ),
          ),
        ),
      );

      final Offset selectableTextStart = tester.getTopLeft(find.byType(SelectableText));

      await tester.tapAt(selectableTextStart + const Offset(150.0, 5.0));
      await tester.pump(const Duration(milliseconds: 50));

      final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
      final TextEditingController controller = editableTextWidget.controller;

      // First tap moved the cursor.
      expect(
        controller.selection,
        const TextSelection.collapsed(offset: 12, affinity: TextAffinity.upstream),
      );
      await tester.tapAt(selectableTextStart + const Offset(150.0, 5.0));
      await tester.pump(const Duration(milliseconds: 500));

      await tester.tapAt(selectableTextStart + const Offset(100.0, 5.0));
      await tester.pump();

      // Plain collapsed selection at the edge of first word. In iOS 12, the
      // first tap after a double tap ends up putting the cursor at where
      // you tapped instead of the edge like every other single tap. This is
      // likely a bug in iOS 12 and not present in other versions.
      expect(
        controller.selection,
        const TextSelection.collapsed(offset: 7),
      );

      // No toolbar.
      expect(find.byType(CupertinoButton), findsNothing);
    },
    variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }),
  );

  testWidgets(
    'long press selects word and shows toolbar (iOS)',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        const MaterialApp(
          home: Material(
            child: Center(
              child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
            ),
          ),
        ),
      );

      final Offset selectableTextStart = tester.getTopLeft(find.byType(SelectableText));

      await tester.longPressAt(selectableTextStart + const Offset(50.0, 5.0));
      await tester.pump();

      final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
      final TextEditingController controller = editableTextWidget.controller;

      // The longpressed word is selected.
      expect(
        controller.selection,
        const TextSelection(
          baseOffset: 0,
          extentOffset: 7,
        ),
      );

      // Toolbar shows one button.
      expect(find.byType(CupertinoButton), findsNWidgets(1));
    },
    variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }),
  );

  testWidgets(
    'long press selects word and shows toolbar (Android)',
    (WidgetTester tester) async {

      await tester.pumpWidget(
        const MaterialApp(
          home: Material(
            child: Center(
              child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
            ),
          ),
        ),
      );

      final Offset selectableTextStart = tester.getTopLeft(find.byType(SelectableText));

      await tester.longPressAt(selectableTextStart + const Offset(50.0, 5.0));
      await tester.pump();

      final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
      final TextEditingController controller = editableTextWidget.controller;

      expect(
        controller.selection,
        const TextSelection(baseOffset: 0, extentOffset: 7),
      );

      // Collapsed toolbar shows 2 buttons: copy, select all
      expect(find.byType(TextButton), findsNWidgets(2));
    },
  );

  testWidgets(
    'long press selects word and shows custom toolbar (Android)',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        MaterialApp(
          home: Material(
            child: Center(
              child: SelectableText('Atwater Peel Sherbrooke Bonaventure',
              selectionControls: cupertinoTextSelectionControls,
              ),
            ),
          ),
        ),
      );

      final Offset selectableTextStart = tester.getTopLeft(find.byType(SelectableText));

      await tester.longPressAt(selectableTextStart + const Offset(50.0, 5.0));
      await tester.pump();

      final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
      final TextEditingController controller = editableTextWidget.controller;

      // The longpressed word is selected.
      expect(
        controller.selection,
        const TextSelection(
          baseOffset: 0,
          extentOffset: 7,
        ),
      );

      // Toolbar shows one button.
      expect(find.byType(CupertinoButton), findsNWidgets(1));
    },
    variant: TargetPlatformVariant.all(),
  );

  testWidgets(
    'long press selects word and shows custom toolbar (iOS)',
    (WidgetTester tester) async {

      await tester.pumpWidget(
        MaterialApp(
          home: Material(
            child: Center(
              child: SelectableText('Atwater Peel Sherbrooke Bonaventure',
              selectionControls: materialTextSelectionControls,
              ),
            ),
          ),
        ),
      );

      final Offset selectableTextStart = tester.getTopLeft(find.byType(SelectableText));

      await tester.longPressAt(selectableTextStart + const Offset(50.0, 5.0));
      await tester.pump();

      final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
      final TextEditingController controller = editableTextWidget.controller;

      expect(
        controller.selection,
        const TextSelection(baseOffset: 0, extentOffset: 7),
      );

      // Collapsed toolbar shows 2 buttons: copy, select all
      expect(find.byType(TextButton), findsNWidgets(2));
    },
    variant: TargetPlatformVariant.all(),
  );

  testWidgets(
    'textSelectionControls is passed to EditableText',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        MaterialApp(
          home: Material(
            child: Scaffold(
              body: SelectableText('Atwater Peel Sherbrooke Bonaventure',
                selectionControls: materialTextSelectionControls,
              ),
            ),
          ),
        ),
      );

      final EditableText widget = tester.widget(find.byType(EditableText));
      expect(widget.selectionControls, equals(materialTextSelectionControls));
    },
  );

  testWidgets(
    'long press tap cannot initiate a double tap',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        const MaterialApp(
          home: Material(
            child: Center(
              child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
            ),
          ),
        ),
      );

      final Offset selectableTextStart = tester.getTopLeft(find.byType(SelectableText));

      await tester.longPressAt(selectableTextStart + const Offset(50.0, 5.0));
      await tester.pump(const Duration(milliseconds: 50));

      // Hide the toolbar so it doesn't interfere with taps on the text.
      final EditableTextState editableTextState =
          tester.state<EditableTextState>(find.byType(EditableText));
      editableTextState.hideToolbar();
      await tester.pumpAndSettle();

      await tester.tapAt(selectableTextStart + const Offset(50.0, 5.0));
      await tester.pump();

      final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
      final TextEditingController controller = editableTextWidget.controller;

      // We ended up moving the cursor to the edge of the same word and dismissed
      // the toolbar.
      expect(
        controller.selection,
        const TextSelection.collapsed(offset: 7, affinity: TextAffinity.upstream),
      );

      expect(find.byType(CupertinoButton), findsNothing);
    },
    variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }),
  );

  testWidgets(
    'long press drag extends the selection to the word under the drag and shows toolbar on lift on non-Apple platforms',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        const MaterialApp(
          home: Material(
            child: Center(
              child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
            ),
          ),
        ),
      );

      final TestGesture gesture =
          await tester.startGesture(textOffsetToPosition(tester, 18));
      await tester.pump(const Duration(milliseconds: 500));

      final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
      final TextEditingController controller = editableTextWidget.controller;

      // Long press selects the word at the long presses position.
      expect(
        controller.selection,
        const TextSelection(baseOffset: 13, extentOffset: 23),
      );
      // Cursor move doesn't trigger a toolbar initially.
      expect(find.byType(TextButton), findsNothing);

      await gesture.moveBy(const Offset(100, 0));
      await tester.pump();

      // The selection is now moved with the drag.
      expect(
        controller.selection,
        const TextSelection(baseOffset: 13, extentOffset: 35),
      );
      // Still no toolbar.
      expect(find.byType(TextButton), findsNothing);

      // The selection is moved on a backwards drag.
      await gesture.moveBy(const Offset(-200, 0));
      await tester.pump();

      // The selection is now moved with the drag.
      expect(
        controller.selection,
        const TextSelection(baseOffset: 23, extentOffset: 8),
      );
      // Still no toolbar.
      expect(find.byType(TextButton), findsNothing);

      await gesture.moveBy(const Offset(-100, 0));
      await tester.pump();

      // The selection is now moved with the drag.
      expect(
        controller.selection,
        const TextSelection(baseOffset: 23, extentOffset: 0),
      );
      // Still no toolbar.
      expect(find.byType(TextButton), findsNothing);

      await gesture.up();
      await tester.pumpAndSettle();

      // The selection isn't affected by the gesture lift.
      expect(
        controller.selection,
        const TextSelection(baseOffset: 23, extentOffset: 0),
      );
      // The toolbar now shows up.
      expect(find.byType(TextButton), findsNWidgets(2));
    },
    variant: TargetPlatformVariant.all(excluding: <TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }),
  );

  testWidgets(
    'long press drag extends the selection to the word under the drag and shows toolbar on lift (iOS)',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        const MaterialApp(
          home: Material(
            child: Center(
              child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
            ),
          ),
        ),
      );

      final TestGesture gesture =
          await tester.startGesture(textOffsetToPosition(tester, 18));
      await tester.pump(const Duration(milliseconds: 500));

      final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
      final TextEditingController controller = editableTextWidget.controller;

      // The longpressed word is selected.
      expect(
        controller.selection,
        const TextSelection(
          baseOffset: 13,
          extentOffset: 23,
        ),
      );
      // Word select doesn't trigger a toolbar initially.
      expect(find.byType(CupertinoButton), findsNothing);

      await gesture.moveBy(const Offset(100, 0));
      await tester.pump();

      // The selection is now moved with the drag.
      expect(
        controller.selection,
        const TextSelection(
          baseOffset: 13,
          extentOffset: 35,
        ),
      );
      // Still no toolbar.
      expect(find.byType(CupertinoButton), findsNothing);

      // The selection is moved with a backwards drag.
      await gesture.moveBy(const Offset(-200, 0));
      await tester.pump();

      // The selection is now moved with the drag.
      expect(
        controller.selection,
        const TextSelection(
          baseOffset: 23,
          extentOffset: 8,
        ),
      );
      // Still no toolbar.
      expect(find.byType(CupertinoButton), findsNothing);

      // The selection is moved with a backwards drag.
      await gesture.moveBy(const Offset(-100, 0));
      await tester.pump();

      // The selection is now moved with the drag.
      expect(
        controller.selection,
        const TextSelection(
          baseOffset: 23,
          extentOffset: 0,
        ),
      );
      // Still no toolbar.
      expect(find.byType(CupertinoButton), findsNothing);

      await gesture.up();
      await tester.pump();

      // The selection isn't affected by the gesture lift.
      expect(
        controller.selection,
        const TextSelection(
          baseOffset: 23,
          extentOffset: 0,
        ),
      );
      // The toolbar now shows up.
      expect(find.byType(CupertinoButton), findsNWidgets(1));
    },
    variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }),
  );

  testWidgets(
    'long press drag moves the cursor under the drag and shows toolbar on lift (macOS)',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        const MaterialApp(
          home: Material(
            child: Center(
              child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
            ),
          ),
        ),
      );

      final Offset selectableTextStart = tester.getTopLeft(find.byType(SelectableText));

      final TestGesture gesture =
      await tester.startGesture(selectableTextStart + const Offset(50.0, 5.0));
      await tester.pump(const Duration(milliseconds: 500));

      final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
      final TextEditingController controller = editableTextWidget.controller;

      // The longpressed word is selected.
      expect(
        controller.selection,
        const TextSelection(
          baseOffset: 0,
          extentOffset: 7,
        ),
      );
      // Cursor move doesn't trigger a toolbar initially.
      expect(find.byType(CupertinoButton), findsNothing);

      await gesture.moveBy(const Offset(50, 0));
      await tester.pump();

      // The selection position is now moved with the drag.
      expect(
        controller.selection,
        const TextSelection(
          baseOffset: 0,
          extentOffset: 8,
        ),
      );
      // Still no toolbar.
      expect(find.byType(CupertinoButton), findsNothing);

      await gesture.moveBy(const Offset(50, 0));
      await tester.pump();

      // The selection position is now moved with the drag.
      expect(
        controller.selection,
        const TextSelection(
          baseOffset: 0,
          extentOffset: 12,
        ),
      );
      // Still no toolbar.
      expect(find.byType(CupertinoButton), findsNothing);

      await gesture.up();
      await tester.pump();

      // The selection isn't affected by the gesture lift.
      expect(
        controller.selection,
        const TextSelection(
          baseOffset: 0,
          extentOffset: 12,
        ),
      );
      // The toolbar now shows up.
      expect(find.byType(CupertinoButton), findsNWidgets(1));
    },
    variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.macOS }),
  );

  testWidgets('long press drag can edge scroll', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: Center(
            child: SelectableText(
              'Atwater Peel Sherbrooke Bonaventure Angrignon Peel Côte-des-Neiges',
              maxLines: 1,
            ),
          ),
        ),
      ),
    );

    final RenderEditable renderEditable = findRenderEditable(tester);

    List<TextSelectionPoint> lastCharEndpoint = renderEditable.getEndpointsForSelection(
      const TextSelection.collapsed(offset: 66), // Last character's position.
    );

    expect(lastCharEndpoint.length, 1);
    // Just testing the test and making sure that the last character is off
    // the right side of the screen.
    expect(lastCharEndpoint[0].point.dx, 924.0);

    final Offset selectableTextStart = tester.getTopLeft(find.byType(SelectableText));

    final TestGesture gesture =
    await tester.startGesture(selectableTextStart + const Offset(300, 5));
    await tester.pump(const Duration(milliseconds: 500));

    final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
    final TextEditingController controller = editableTextWidget.controller;

    expect(
      controller.selection,
      const TextSelection(baseOffset: 13, extentOffset: 23),
    );
    expect(find.byType(CupertinoButton), findsNothing);

    await gesture.moveBy(const Offset(600, 0));
    // To the edge of the screen basically.
    await tester.pump();
    expect(
      controller.selection,
      const TextSelection(
        baseOffset: 13,
        extentOffset: 66,
      ),
    );
    // Keep moving out.
    await gesture.moveBy(const Offset(1, 0));
    await tester.pump();
    expect(
      controller.selection,
      const TextSelection(
        baseOffset: 13,
        extentOffset: 66,
      ),
    );
    await gesture.moveBy(const Offset(1, 0));
    await tester.pump();
    expect(
      controller.selection,
      const TextSelection(
        baseOffset: 13,
        extentOffset: 66,
      ),
    );
    expect(find.byType(CupertinoButton), findsNothing);

    await gesture.up();
    await tester.pump();

    // The selection isn't affected by the gesture lift.
    expect(
      controller.selection,
      const TextSelection(
        baseOffset: 13,
        extentOffset: 66,
      ),
    );
    // The toolbar now shows up.
    expect(find.byType(CupertinoButton), findsNWidgets(1));

    lastCharEndpoint = renderEditable.getEndpointsForSelection(
      const TextSelection.collapsed(offset: 66), // Last character's position.
    );

    expect(lastCharEndpoint.length, 1);
    // The last character is now on screen near the right edge.
    expect(lastCharEndpoint[0].point.dx, moreOrLessEquals(798, epsilon: 1));

    final List<TextSelectionPoint> firstCharEndpoint = renderEditable.getEndpointsForSelection(
      const TextSelection.collapsed(offset: 0), // First character's position.
    );
    expect(firstCharEndpoint.length, 1);
    // The first character is now offscreen to the left.
    expect(firstCharEndpoint[0].point.dx, moreOrLessEquals(-125, epsilon: 1));
  },
    variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }),
    skip: true, // https://github.com/flutter/flutter/issues/64059
  );

  testWidgets(
    'long tap still selects after a double tap select (iOS)',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        const MaterialApp(
          home: Material(
            child: Center(
              child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
            ),
          ),
        ),
      );

      final Offset selectableTextStart = tester.getTopLeft(find.byType(SelectableText));

      await tester.tapAt(selectableTextStart + const Offset(150.0, 5.0));
      await tester.pump(const Duration(milliseconds: 50));

      final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
      final TextEditingController controller = editableTextWidget.controller;

      // First tap moved the cursor to the beginning of the second word.
      expect(
        controller.selection,
        const TextSelection.collapsed(offset: 12, affinity: TextAffinity.upstream),
      );
      await tester.tapAt(selectableTextStart + const Offset(150.0, 5.0));
      await tester.pump(const Duration(milliseconds: 500));

      await tester.longPressAt(selectableTextStart + const Offset(100.0, 5.0));
      await tester.pump();

      // Selected the "word" where the tap happened, which is the first space.
      // Because the "word" is a whitespace, the selection will shift to the
      // previous "word" that is not a whitespace.
      expect(
        controller.selection,
        const TextSelection(baseOffset: 0, extentOffset: 7),
      );

      // Long press toolbar.
      expect(find.byType(CupertinoButton), findsNWidgets(1));
    },
    variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }),
  );

  testWidgets(
    'long tap still selects after a double tap select (macOS)',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        const MaterialApp(
          home: Material(
            child: Center(
              child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
            ),
          ),
        ),
      );

      final Offset selectableTextStart = tester.getTopLeft(find.byType(SelectableText));

      await tester.tapAt(selectableTextStart + const Offset(150.0, 5.0));
      await tester.pump(const Duration(milliseconds: 50));

      final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
      final TextEditingController controller = editableTextWidget.controller;

      // First tap moved the cursor to the beginning of the second word.
      expect(
        controller.selection,
        const TextSelection.collapsed(offset: 12, affinity: TextAffinity.upstream),
      );
      await tester.tapAt(selectableTextStart + const Offset(150.0, 5.0));
      await tester.pump(const Duration(milliseconds: 500));

      await tester.longPressAt(selectableTextStart + const Offset(100.0, 5.0));
      await tester.pump();

      // Selected the "word" where the tap happened, which is the first space.
      expect(
        controller.selection,
        const TextSelection(baseOffset: 7, extentOffset: 8),
      );

      // Long press toolbar.
      expect(find.byType(CupertinoButton), findsNWidgets(1));
    },
    variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.macOS }),
  );
//convert
  testWidgets(
    'double tap after a long tap is not affected',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        const MaterialApp(
          home: Material(
            child: Center(
              child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
            ),
          ),
        ),
      );

      final Offset selectableTextStart = tester.getTopLeft(find.byType(SelectableText));

      await tester.longPressAt(selectableTextStart + const Offset(50.0, 5.0));
      await tester.pump(const Duration(milliseconds: 50));

      // Hide the toolbar so it doesn't interfere with taps on the text.
      final EditableTextState editableTextState =
          tester.state<EditableTextState>(find.byType(EditableText));
      editableTextState.hideToolbar();
      await tester.pumpAndSettle();

      await tester.tapAt(selectableTextStart + const Offset(150.0, 5.0));
      await tester.pump(const Duration(milliseconds: 50));

      final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
      final TextEditingController controller = editableTextWidget.controller;

      // First tap moved the cursor.
      expect(
        controller.selection,
        const TextSelection.collapsed(offset: 12, affinity: TextAffinity.upstream),
      );
      await tester.tapAt(selectableTextStart + const Offset(150.0, 5.0));
      await tester.pump();

      // Double tap selection.
      expect(
        controller.selection,
        const TextSelection(baseOffset: 8, extentOffset: 12),
      );
      expect(find.byType(CupertinoButton), findsNWidgets(1));
    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }),
  );

  testWidgets(
    'double tap chains work',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        const MaterialApp(
          home: Material(
            child: Center(
              child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
            ),
          ),
        ),
      );

      final Offset selectableTextStart = tester.getTopLeft(find.byType(SelectableText));

      await tester.tapAt(selectableTextStart + const Offset(50.0, 5.0));
      await tester.pump(const Duration(milliseconds: 50));

      final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
      final TextEditingController controller = editableTextWidget.controller;

      expect(
        controller.selection,
        const TextSelection.collapsed(offset: 7, affinity: TextAffinity.upstream),
      );
      await tester.tapAt(selectableTextStart + const Offset(50.0, 5.0));
      await tester.pump(const Duration(milliseconds: 50));
      expect(
        controller.selection,
        const TextSelection(baseOffset: 0, extentOffset: 7),
      );
      expect(find.byType(CupertinoButton), findsNWidgets(1));

      // Double tap selecting the same word somewhere else is fine.
      await tester.tapAt(selectableTextStart + const Offset(10.0, 5.0));
      await tester.pump(const Duration(milliseconds: 50));
      // First tap moved the cursor.
      expect(
        controller.selection,
        const TextSelection.collapsed(offset: 0),
      );
      await tester.tapAt(selectableTextStart + const Offset(10.0, 5.0));
      await tester.pump(const Duration(milliseconds: 50));
      expect(
        controller.selection,
        const TextSelection(baseOffset: 0, extentOffset: 7),
      );
      expect(find.byType(CupertinoButton), findsNWidgets(1));

      // Hide the toolbar so it doesn't interfere with taps on the text.
      final EditableTextState editableTextState =
          tester.state<EditableTextState>(find.byType(EditableText));
      editableTextState.hideToolbar();
      await tester.pumpAndSettle();

      await tester.tapAt(selectableTextStart + const Offset(150.0, 5.0));
      await tester.pump(const Duration(milliseconds: 50));
      // First tap moved the cursor.
      expect(
        controller.selection,
        const TextSelection.collapsed(offset: 12, affinity: TextAffinity.upstream),
      );
      await tester.tapAt(selectableTextStart + const Offset(150.0, 5.0));
      await tester.pump(const Duration(milliseconds: 50));
      expect(
        controller.selection,
        const TextSelection(baseOffset: 8, extentOffset: 12),
      );
      expect(find.byType(CupertinoButton), findsNWidgets(1));
    },
    variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }),
  );

  testWidgets('force press does not select a word on (android)', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
        ),
      ),
    );

    final Offset offset = tester.getTopLeft(find.byType(SelectableText)) + const Offset(150.0, 5.0);

    final int pointerValue = tester.nextPointer;
    final TestGesture gesture = await tester.createGesture();
    await gesture.downWithCustomEvent(
      offset,
      PointerDownEvent(
        pointer: pointerValue,
        position: offset,
        pressure: 0.0,
        pressureMax: 6.0,
        pressureMin: 0.0,
      ),
    );
    await gesture.updateWithCustomEvent(PointerMoveEvent(pointer: pointerValue, position: offset + const Offset(150.0, 5.0), pressure: 0.5, pressureMin: 0));

    final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
    final TextEditingController controller = editableTextWidget.controller;

    // We don't want this gesture to select any word on Android.
    expect(controller.selection, const TextSelection.collapsed(offset: -1));

    await gesture.up();
    await tester.pump();
    expect(find.byType(TextButton), findsNothing);
  });

  testWidgets('force press selects word', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
        ),
      ),
    );

    final Offset selectableTextStart = tester.getTopLeft(find.byType(SelectableText));

    final int pointerValue = tester.nextPointer;
    final Offset offset = selectableTextStart + const Offset(150.0, 5.0);
    final TestGesture gesture = await tester.createGesture();
    await gesture.downWithCustomEvent(
      offset,
      PointerDownEvent(
        pointer: pointerValue,
        position: offset,
        pressure: 0.0,
        pressureMax: 6.0,
        pressureMin: 0.0,
      ),
    );

    await gesture.updateWithCustomEvent(PointerMoveEvent(pointer: pointerValue, position: selectableTextStart + const Offset(150.0, 5.0), pressure: 0.5, pressureMin: 0));

    final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
    final TextEditingController controller = editableTextWidget.controller;

    // We expect the force press to select a word at the given location.
    expect(
      controller.selection,
      const TextSelection(baseOffset: 8, extentOffset: 12),
    );

    await gesture.up();
    await tester.pump();
    expect(find.byType(CupertinoButton), findsNWidgets(1));
  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }));

  testWidgets('tap on non-force-press-supported devices work', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
        ),
      ),
    );

    final Offset selectableTextStart = tester.getTopLeft(find.byType(SelectableText));

    final int pointerValue = tester.nextPointer;
    final Offset offset = selectableTextStart + const Offset(150.0, 5.0);
    final TestGesture gesture = await tester.createGesture();
    await gesture.downWithCustomEvent(
      offset,
      PointerDownEvent(
        pointer: pointerValue,
        position: offset,
        // iPhone 6 and below report 0 across the board.
        pressure: 0,
        pressureMax: 0,
        pressureMin: 0,
      ),
    );

    await gesture.updateWithCustomEvent(PointerMoveEvent(pointer: pointerValue, position: selectableTextStart + const Offset(150.0, 5.0), pressure: 0.5, pressureMin: 0));
    await gesture.up();

    final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
    final TextEditingController controller = editableTextWidget.controller;

    // The event should fallback to a normal tap and move the cursor.
    // Single taps selects the edge of the word.
    expect(
      controller.selection,
      const TextSelection.collapsed(offset: 12, affinity: TextAffinity.upstream),
    );

    await tester.pump();
    // Single taps shouldn't trigger the toolbar.
    expect(find.byType(CupertinoButton), findsNothing);

    // TODO(gspencergoog): Add in TargetPlatform.macOS in the line below when we
    // figure out what global state is leaking.
    // https://github.com/flutter/flutter/issues/43445
  }, variant: TargetPlatformVariant.only(TargetPlatform.iOS));

  testWidgets('default SelectableText debugFillProperties', (WidgetTester tester) async {
    final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();

    const SelectableText('something').debugFillProperties(builder);

    final List<String> description = builder.properties
        .where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
        .map((DiagnosticsNode node) => node.toString()).toList();

    expect(description, <String>['data: something']);
  });

  testWidgets('SelectableText implements debugFillProperties', (WidgetTester tester) async {
    final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();

    // Not checking controller, inputFormatters, focusNode
    const SelectableText(
      'something',
      style: TextStyle(color: Color(0xff00ff00)),
      textAlign: TextAlign.end,
      textDirection: TextDirection.ltr,
      textScaleFactor: 1.0,
      autofocus: true,
      showCursor: true,
      minLines: 2,
      maxLines: 10,
      cursorWidth: 1.0,
      cursorHeight: 1.0,
      cursorRadius: Radius.zero,
      cursorColor: Color(0xff00ff00),
      scrollPhysics: ClampingScrollPhysics(),
      semanticsLabel: 'something else',
      enableInteractiveSelection: false,
    ).debugFillProperties(builder);

    final List<String> description = builder.properties
        .where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
        .map((DiagnosticsNode node) => node.toString()).toList();

    expect(description, <String>[
      'data: something',
      'semanticsLabel: something else',
      'style: TextStyle(inherit: true, color: Color(0xff00ff00))',
      'autofocus: true',
      'showCursor: true',
      'minLines: 2',
      'maxLines: 10',
      'textAlign: end',
      'textDirection: ltr',
      'textScaleFactor: 1.0',
      'cursorWidth: 1.0',
      'cursorHeight: 1.0',
      'cursorRadius: Radius.circular(0.0)',
      'cursorColor: Color(0xff00ff00)',
      'selection disabled',
      'scrollPhysics: ClampingScrollPhysics',
    ]);
  });

  testWidgets(
    'strut basic single line',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        MaterialApp(
          theme: ThemeData(platform: TargetPlatform.android),
          home: const Material(
            child: Center(
              child: SelectableText('something'),
            ),
          ),
        ),
      );

      expect(
        tester.getSize(find.byType(SelectableText)),
        // This is the height of the decoration (24) plus the metrics from the default
        // TextStyle of the theme (16).
        const Size(129.0, 14.0),
      );
    },
  );

  testWidgets(
    'strut TextStyle increases height',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        MaterialApp(
          theme: ThemeData(platform: TargetPlatform.android),
          home: const Material(
            child: Center(
              child: SelectableText(
                'something',
                style: TextStyle(fontSize: 20),
              ),
            ),
          ),
        ),
      );

      expect(
        tester.getSize(find.byType(SelectableText)),
        // Strut should inherit the TextStyle.fontSize by default and produce the
        // same height as if it were disabled.
        const Size(183.0, 20.0),
      );

      await tester.pumpWidget(
        MaterialApp(
          theme: ThemeData(platform: TargetPlatform.android),
          home: const Material(
            child: Center(
              child: SelectableText(
                'something',
                style: TextStyle(fontSize: 20),
                strutStyle: StrutStyle.disabled,
              ),
            ),
          ),
        ),
      );

      expect(
        tester.getSize(find.byType(SelectableText)),
        // The height here should match the previous version with strut enabled.
        const Size(183.0, 20.0),
      );
    },
  );

  testWidgets(
    'strut basic multi line',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        MaterialApp(
          theme: ThemeData(platform: TargetPlatform.android),
          home: const Material(
            child: Center(
              child: SelectableText(
                'something',
                maxLines: 6,
              ),
            ),
          ),
        ),
      );

      expect(
        tester.getSize(find.byType(SelectableText)),
        const Size(129.0, 84.0),
      );
    },
  );

  testWidgets(
    'strut no force small strut',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        MaterialApp(
          theme: ThemeData(platform: TargetPlatform.android),
          home: const Material(
            child: Center(
              child: SelectableText(
                'something',
                maxLines: 6,
                strutStyle: StrutStyle(
                  // The small strut is overtaken by the larger
                  // TextStyle fontSize.
                  fontSize: 5,
                ),
              ),
            ),
          ),
        ),
      );

      expect(
        tester.getSize(find.byType(SelectableText)),
        // When the strut's height is smaller than TextStyle's and forceStrutHeight
        // is disabled, then the TextStyle takes precedence. Should be the same height
        // as 'strut basic multi line'.
        const Size(129.0, 84.0),
      );
    },
  );

  testWidgets(
    'strut no force large strut',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        MaterialApp(
          theme: ThemeData(platform: TargetPlatform.android),
          home: const Material(
            child: Center(
              child: SelectableText(
                'something',
                maxLines: 6,
                strutStyle: StrutStyle(
                  fontSize: 25,
                ),
              ),
            ),
          ),
        ),
      );

      expect(
        tester.getSize(find.byType(SelectableText)),
        // When the strut's height is larger than TextStyle's and forceStrutHeight
        // is disabled, then the StrutStyle takes precedence.
        const Size(129.0, 150.0),
      );
    },
  );

  testWidgets(
    'strut height override',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        MaterialApp(
          theme: ThemeData(platform: TargetPlatform.android),
          home: const Material(
            child: Center(
              child: SelectableText(
                'something',
                maxLines: 3,
                strutStyle: StrutStyle(
                  fontSize: 8,
                  forceStrutHeight: true,
                ),
              ),
            ),
          ),
        ),
      );

      expect(
        tester.getSize(find.byType(SelectableText)),
        // The smaller font size of strut make the field shorter than normal.
        const Size(129.0, 24.0),
      );
    },
  );

  testWidgets(
    'strut forces field taller',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        MaterialApp(
          theme: ThemeData(platform: TargetPlatform.android),
          home: const Material(
            child: Center(
              child: SelectableText(
                'something',
                maxLines: 3,
                style: TextStyle(fontSize: 10),
                strutStyle: StrutStyle(
                  fontSize: 18,
                  forceStrutHeight: true,
                ),
              ),
            ),
          ),
        ),
      );

      expect(
        tester.getSize(find.byType(SelectableText)),
        // When the strut fontSize is larger than a provided TextStyle, the
        // strut's height takes precedence.
        const Size(93.0, 54.0),
      );
    },
  );

  testWidgets('Caret center position', (WidgetTester tester) async {
    await tester.pumpWidget(
      overlay(
        child: const SizedBox(
          width: 300.0,
          child: SelectableText(
            'abcd',
            textAlign: TextAlign.center,
          ),
        ),
      ),
    );

    final RenderEditable editable = findRenderEditable(tester);

    Offset topLeft = editable.localToGlobal(
      editable.getLocalRectForCaret(const TextPosition(offset: 4)).topLeft,
    );
    expect(topLeft.dx, equals(427));

    topLeft = editable.localToGlobal(
      editable.getLocalRectForCaret(const TextPosition(offset: 3)).topLeft,
    );
    expect(topLeft.dx, equals(413));

    topLeft = editable.localToGlobal(
      editable.getLocalRectForCaret(const TextPosition(offset: 2)).topLeft,
    );
    expect(topLeft.dx, equals(399));

    topLeft = editable.localToGlobal(
      editable.getLocalRectForCaret(const TextPosition(offset: 1)).topLeft,
    );
    expect(topLeft.dx, equals(385));
  });

  testWidgets('Caret indexes into trailing whitespace center align', (WidgetTester tester) async {
    await tester.pumpWidget(
      overlay(
        child: const SizedBox(
          width: 300.0,
          child: SelectableText(
            'abcd    ',
            textAlign: TextAlign.center,
          ),
        ),
      ),
    );

    final RenderEditable editable = findRenderEditable(tester);

    Offset topLeft = editable.localToGlobal(
      editable.getLocalRectForCaret(const TextPosition(offset: 7)).topLeft,
    );
    expect(topLeft.dx, equals(469));

    topLeft = editable.localToGlobal(
      editable.getLocalRectForCaret(const TextPosition(offset: 8)).topLeft,
    );
    expect(topLeft.dx, equals(483));

    topLeft = editable.localToGlobal(
      editable.getLocalRectForCaret(const TextPosition(offset: 4)).topLeft,
    );
    expect(topLeft.dx, equals(427));

    topLeft = editable.localToGlobal(
      editable.getLocalRectForCaret(const TextPosition(offset: 3)).topLeft,
    );
    expect(topLeft.dx, equals(413));

    topLeft = editable.localToGlobal(
      editable.getLocalRectForCaret(const TextPosition(offset: 2)).topLeft,
    );
    expect(topLeft.dx, equals(399));

    topLeft = editable.localToGlobal(
      editable.getLocalRectForCaret(const TextPosition(offset: 1)).topLeft,
    );
    expect(topLeft.dx, equals(385));
  });

  testWidgets('selection handles are rendered and not faded away', (WidgetTester tester) async {
    const String testText = 'lorem ipsum';
    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: SelectableText(testText),
        ),
      ),
    );

    final EditableTextState state =
        tester.state<EditableTextState>(find.byType(EditableText));
    final RenderEditable renderEditable = state.renderEditable;

    await tester.tapAt(const Offset(20, 10));
    renderEditable.selectWord(cause: SelectionChangedCause.longPress);
    await tester.pumpAndSettle();

    final List<FadeTransition> transitions = find.descendant(
      of: find.byWidgetPredicate((Widget w) => '${w.runtimeType}' == '_SelectionHandleOverlay'),
      matching: find.byType(FadeTransition),
    ).evaluate().map((Element e) => e.widget).cast<FadeTransition>().toList();
    expect(transitions.length, 2);
    final FadeTransition left = transitions[0];
    final FadeTransition right = transitions[1];

    expect(left.opacity.value, equals(1.0));
    expect(right.opacity.value, equals(1.0));
  });

  testWidgets('selection handles are rendered and not faded away', (WidgetTester tester) async {
    const String testText = 'lorem ipsum';

    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: SelectableText(testText),
        ),
      ),
    );

    final RenderEditable renderEditable =
        tester.state<EditableTextState>(find.byType(EditableText)).renderEditable;

    await tester.tapAt(const Offset(20, 10));
    renderEditable.selectWord(cause: SelectionChangedCause.longPress);
    await tester.pumpAndSettle();

    final List<Widget> transitions =
    find.byType(FadeTransition).evaluate().map((Element e) => e.widget).toList();
    expect(transitions.length, 2);
    final FadeTransition left = transitions[0] as FadeTransition;
    final FadeTransition right = transitions[1] as FadeTransition;

    expect(left.opacity.value, equals(1.0));
    expect(right.opacity.value, equals(1.0));
  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));

  testWidgets('Long press shows handles and toolbar', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: SelectableText('abc def ghi'),
        ),
      ),
    );

    // Long press at 'e' in 'def'.
    final Offset ePos = textOffsetToPosition(tester, 5);
    await tester.longPressAt(ePos);
    await tester.pumpAndSettle();

    final EditableTextState editableText = tester.state(find.byType(EditableText));
    expect(editableText.selectionOverlay!.handlesAreVisible, isTrue);
    expect(editableText.selectionOverlay!.toolbarIsVisible, isTrue);
  });

  testWidgets('Double tap shows handles and toolbar', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: SelectableText('abc def ghi'),
        ),
      ),
    );

    // Double tap at 'e' in 'def'.
    final Offset ePos = textOffsetToPosition(tester, 5);
    await tester.tapAt(ePos);
    await tester.pump(const Duration(milliseconds: 50));
    await tester.tapAt(ePos);
    await tester.pump();

    final EditableTextState editableText = tester.state(find.byType(EditableText));
    expect(editableText.selectionOverlay!.handlesAreVisible, isTrue);
    expect(editableText.selectionOverlay!.toolbarIsVisible, isTrue);
  });

  testWidgets(
    'Mouse tap does not show handles nor toolbar',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        const MaterialApp(
          home: Material(
            child: SelectableText('abc def ghi'),
          ),
        ),
      );

      // Long press to trigger the selectable text.
      final Offset ePos = textOffsetToPosition(tester, 5);
      final TestGesture gesture = await tester.startGesture(
        ePos,
        pointer: 7,
        kind: PointerDeviceKind.mouse,
      );
      await tester.pump();
      await gesture.up();
      await tester.pump();

      final EditableTextState editableText = tester.state(find.byType(EditableText));
      expect(editableText.selectionOverlay!.toolbarIsVisible, isFalse);
      expect(editableText.selectionOverlay!.handlesAreVisible, isFalse);
    },
  );

  testWidgets(
    'Mouse long press does not show handles nor toolbar',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        const MaterialApp(
          home: Material(
            child: SelectableText('abc def ghi'),
          ),
        ),
      );

      // Long press to trigger the selectable text.
      final Offset ePos = textOffsetToPosition(tester, 5);
      final TestGesture gesture = await tester.startGesture(
        ePos,
        pointer: 7,
        kind: PointerDeviceKind.mouse,
      );
      await tester.pump(const Duration(seconds: 2));
      await gesture.up();
      await tester.pump();

      final EditableTextState editableText = tester.state(find.byType(EditableText));
      expect(editableText.selectionOverlay!.toolbarIsVisible, isFalse);
      expect(editableText.selectionOverlay!.handlesAreVisible, isFalse);
    },
  );

  testWidgets(
    'Mouse double tap does not show handles nor toolbar',
    (WidgetTester tester) async {
      await tester.pumpWidget(
        const MaterialApp(
          home: Material(
            child: SelectableText('abc def ghi'),
          ),
        ),
      );

      // Double tap to trigger the selectable text.
      final Offset selectableTextPos = tester.getCenter(find.byType(SelectableText));
      final TestGesture gesture = await tester.startGesture(
        selectableTextPos,
        pointer: 7,
        kind: PointerDeviceKind.mouse,
      );
      await tester.pump(const Duration(milliseconds: 50));
      await gesture.up();
      await tester.pump();
      await gesture.down(selectableTextPos);
      await tester.pump();
      await gesture.up();
      await tester.pump();

      final EditableTextState editableText = tester.state(find.byType(EditableText));
      expect(editableText.selectionOverlay!.toolbarIsVisible, isFalse);
      expect(editableText.selectionOverlay!.handlesAreVisible, isFalse);
    },
  );

  testWidgets('text span with tap gesture recognizer works in selectable rich text', (WidgetTester tester) async {
    int spyTaps = 0;
    final TapGestureRecognizer spyRecognizer = TapGestureRecognizer()
      ..onTap = () {
        spyTaps += 1;
      };
    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: Center(
            child: SelectableText.rich(
              TextSpan(
                children: <TextSpan>[
                  const TextSpan(text: 'Atwater '),
                  TextSpan(text: 'Peel', recognizer: spyRecognizer),
                  const TextSpan(text: ' Sherbrooke Bonaventure'),
                ],
              ),
            ),
          ),
        ),
      ),
    );
    expect(spyTaps, 0);
    final Offset selectableTextStart = tester.getTopLeft(find.byType(SelectableText));

    await tester.tapAt(selectableTextStart + const Offset(150.0, 5.0));
    expect(spyTaps, 1);

    // Waits for a while to avoid double taps.
    await tester.pump(const Duration(seconds: 1));

    // Starts a long press.
    final TestGesture gesture =
      await tester.startGesture(selectableTextStart + const Offset(150.0, 5.0));
    await tester.pump(const Duration(milliseconds: 500));
    await gesture.up();
    await tester.pump();
    final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);

    final TextEditingController controller = editableTextWidget.controller;
    // Long press still triggers selection.
    expect(
      controller.selection,
      const TextSelection(baseOffset: 8, extentOffset: 12),
    );
    // Long press does not trigger gesture recognizer.
    expect(spyTaps, 1);
  });

  testWidgets('text span with long press gesture recognizer works in selectable rich text', (WidgetTester tester) async {
    int spyLongPress = 0;
    final LongPressGestureRecognizer spyRecognizer = LongPressGestureRecognizer()
      ..onLongPress = () {
        spyLongPress += 1;
      };
    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: Center(
            child: SelectableText.rich(
              TextSpan(
                children: <TextSpan>[
                  const TextSpan(text: 'Atwater '),
                  TextSpan(text: 'Peel', recognizer: spyRecognizer),
                  const TextSpan(text: ' Sherbrooke Bonaventure'),
                ],
              ),
            ),
          ),
        ),
      ),
    );
    expect(spyLongPress, 0);
    final Offset selectableTextStart = tester.getTopLeft(find.byType(SelectableText));

    await tester.tapAt(selectableTextStart + const Offset(150.0, 5.0));
    expect(spyLongPress, 0);

    // Waits for a while to avoid double taps.
    await tester.pump(const Duration(seconds: 1));

    // Starts a long press.
    final TestGesture gesture =
    await tester.startGesture(selectableTextStart + const Offset(150.0, 5.0));
    await tester.pump(const Duration(milliseconds: 500));
    await gesture.up();
    await tester.pump();
    final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);

    final TextEditingController controller = editableTextWidget.controller;
    // Long press does not trigger selection if there is text span with long
    // press recognizer.
    expect(
      controller.selection,
      const TextSelection(baseOffset: 11, extentOffset: 11, affinity: TextAffinity.upstream),
    );
    // Long press triggers gesture recognizer.
    expect(spyLongPress, 1);
  });

  testWidgets('SelectableText changes mouse cursor when hovered', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: Center(
            child: SelectableText('test'),
          ),
        ),
      ),
    );

    final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse, pointer: 1);
    await gesture.addPointer(location: tester.getCenter(find.text('test')));

    await tester.pump();

    expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text);
  });

  testWidgets('The handles show after pressing Select All', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: SelectableText('abc def ghi'),
        ),
      ),
    );

    // Long press at 'e' in 'def'.
    final Offset ePos = textOffsetToPosition(tester, 5);
    await tester.longPressAt(ePos);
    await tester.pumpAndSettle();

    expect(find.text('Select all'), findsOneWidget);
    expect(find.text('Copy'), findsOneWidget);
    expect(find.text('Paste'), findsNothing);
    expect(find.text('Cut'), findsNothing);
    EditableTextState editableText = tester.state(find.byType(EditableText));
    expect(editableText.selectionOverlay!.handlesAreVisible, isTrue);
    expect(editableText.selectionOverlay!.toolbarIsVisible, isTrue);

    await tester.tap(find.text('Select all'));
    await tester.pump();
    expect(find.text('Copy'), findsOneWidget);
    expect(find.text('Select all'), findsNothing);
    expect(find.text('Paste'), findsNothing);
    expect(find.text('Cut'), findsNothing);
    editableText = tester.state(find.byType(EditableText));
    expect(editableText.selectionOverlay!.handlesAreVisible, isTrue);
  },
    variant: const TargetPlatformVariant(<TargetPlatform>{
      TargetPlatform.android,
      TargetPlatform.fuchsia,
    }),
  );

  testWidgets('The Select All calls on selection changed', (WidgetTester tester) async {
    TextSelection? newSelection;
    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: SelectableText(
            'abc def ghi',
            onSelectionChanged: (TextSelection selection, SelectionChangedCause? cause) {
              expect(newSelection, isNull);
              newSelection = selection;
            },
          ),
        ),
      ),
    );

    // Long press at 'e' in 'def'.
    final Offset ePos = textOffsetToPosition(tester, 5);
    await tester.longPressAt(ePos);
    await tester.pumpAndSettle();

    expect(newSelection!.baseOffset, 4);
    expect(newSelection!.extentOffset, 7);
    newSelection = null;

    await tester.tap(find.text('Select all'));
    await tester.pump();
    expect(newSelection!.baseOffset, 0);
    expect(newSelection!.extentOffset, 11);
  },
    variant: const TargetPlatformVariant(<TargetPlatform>{
      TargetPlatform.android,
      TargetPlatform.fuchsia,
    }),
  );

  testWidgets('The Select All calls on selection changed with a mouse on windows and linux', (WidgetTester tester) async {
    const String string = 'abc def ghi';
    TextSelection? newSelection;
    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: SelectableText(
            string,
            onSelectionChanged: (TextSelection selection, SelectionChangedCause? cause) {
              expect(newSelection, isNull);
              newSelection = selection;
            },
          ),
        ),
      ),
    );

    // Right-click on the 'e' in 'def'.
    final Offset ePos = textOffsetToPosition(tester, 5);
    final TestGesture gesture = await tester.startGesture(
      ePos,
      kind: PointerDeviceKind.mouse,
      buttons: kSecondaryMouseButton,
    );
    await tester.pump();
    await gesture.up();
    await tester.pumpAndSettle();
    expect(newSelection!.isCollapsed, isTrue);
    expect(newSelection!.baseOffset, 5);
    newSelection = null;

    await tester.tap(find.text('Select all'));
    await tester.pump();
    expect(newSelection!.baseOffset, 0);
    expect(newSelection!.extentOffset, 11);
  },
    variant: const TargetPlatformVariant(<TargetPlatform>{
      TargetPlatform.windows,
      TargetPlatform.linux,
    }),
  );

  testWidgets('Does not show handles when updated from the web engine', (WidgetTester tester) async {
    await tester.pumpWidget(
      const MaterialApp(
        home: Material(
          child: SelectableText('abc def ghi'),
        ),
      ),
    );

    // Interact with the selectable text to establish the input connection.
    final Offset topLeft = tester.getTopLeft(find.byType(EditableText));
    final TestGesture gesture = await tester.startGesture(
      topLeft + const Offset(0.0, 5.0),
      kind: PointerDeviceKind.mouse,
    );
    await tester.pump(const Duration(milliseconds: 50));
    await gesture.up();
    await tester.pumpAndSettle();

    final EditableTextState state = tester.state(find.byType(EditableText));
    expect(state.selectionOverlay!.handlesAreVisible, isFalse);
    expect(
      state.currentTextEditingValue.selection,
      const TextSelection.collapsed(offset: 0),
    );

    if (kIsWeb) {
      tester.testTextInput.updateEditingValue(const TextEditingValue(
        selection: TextSelection(baseOffset: 2, extentOffset: 7),
      ));
      // Wait for all the `setState` calls to be flushed.
      await tester.pumpAndSettle();
      expect(
        state.currentTextEditingValue.selection,
        const TextSelection(baseOffset: 2, extentOffset: 7),
      );
      expect(state.selectionOverlay!.handlesAreVisible, isFalse);
    }
  });

  testWidgets('onSelectionChanged is called when selection changes', (WidgetTester tester) async {
    int onSelectionChangedCallCount = 0;

    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: SelectableText(
            'abc def ghi',
            onSelectionChanged: (TextSelection selection, SelectionChangedCause? cause) {
              onSelectionChangedCallCount += 1;
            },
          ),
        ),
      ),
    );

    // Long press to select 'abc'.
    final Offset aLocation = textOffsetToPosition(tester, 1);
    await tester.longPressAt(aLocation);
    await tester.pump();
    expect(onSelectionChangedCallCount, equals(1));
    // Long press to select 'def'.
    await tester.longPressAt(textOffsetToPosition(tester, 5));
    await tester.pump();
    expect(onSelectionChangedCallCount, equals(2));
    // Tap on 'Select all' option to select the whole text.
    await tester.tap(find.text('Select all'));
    expect(onSelectionChangedCallCount, equals(3));
  });

  testWidgets('selecting a space selects the previous word on mobile', (WidgetTester tester) async {
    TextSelection? selection;

    await tester.pumpWidget(
      MaterialApp(
        home: SelectableText(
          ' blah blah',
          onSelectionChanged: (TextSelection newSelection, SelectionChangedCause? cause) {
            selection = newSelection;
          },
        ),
      ),
    );

    expect(selection, isNull);

    // Put the cursor at the end of the field.
    await tester.tapAt(textOffsetToPosition(tester, 10));
    expect(selection, isNotNull);
    expect(selection!.baseOffset, 10);
    expect(selection!.extentOffset, 10);

    // Long press on the second space and the previous word is selected.
    await tester.longPressAt(textOffsetToPosition(tester, 5));
    await tester.pumpAndSettle();
    expect(selection, isNotNull);
    expect(selection!.baseOffset, 1);
    expect(selection!.extentOffset, 5);

    // Put the cursor at the end of the field.
    await tester.tapAt(textOffsetToPosition(tester, 10));
    expect(selection, isNotNull);
    expect(selection!.baseOffset, 10);
    expect(selection!.extentOffset, 10);

    // Long press on the first space and the space is selected because there is
    // no previous word.
    await tester.longPressAt(textOffsetToPosition(tester, 0));
    await tester.pumpAndSettle();
    expect(selection, isNotNull);
    expect(selection!.baseOffset, 0);
    expect(selection!.extentOffset, 1);
  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.android }));

  testWidgets('selecting a space selects the space on non-mobile platforms', (WidgetTester tester) async {
    TextSelection? selection;

    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: Center(
            child: SelectableText(
              ' blah blah',
              onSelectionChanged: (TextSelection newSelection, SelectionChangedCause? cause) {
                selection = newSelection;
              },
            ),
          ),
        ),
      ),
    );

    expect(selection, isNull);

    // Put the cursor at the end of the field.
    await tester.tapAt(textOffsetToPosition(tester, 10));
    expect(selection, isNotNull);
    expect(selection!.baseOffset, 10);
    expect(selection!.extentOffset, 10);

    // Double tapping the second space selects it.
    await tester.pump(const Duration(milliseconds: 500));
    await tester.tapAt(textOffsetToPosition(tester, 5));
    await tester.pump(const Duration(milliseconds: 50));
    await tester.tapAt(textOffsetToPosition(tester, 5));
    await tester.pumpAndSettle();
    expect(selection, isNotNull);
    expect(selection!.baseOffset, 5);
    expect(selection!.extentOffset, 6);

    // Tap at the beginning of the text to hide the toolbar, then at the end to
    // move the cursor to the end. On some platforms, the context menu would
    // otherwise block a tap on the end of the field.
    await tester.tapAt(textOffsetToPosition(tester, 0));
    await tester.pumpAndSettle();
    await tester.tapAt(textOffsetToPosition(tester, 10));
    expect(selection, isNotNull);
    expect(selection!.baseOffset, 10);
    expect(selection!.extentOffset, 10);

    // Double tapping the first space selects it.
    await tester.pump(const Duration(milliseconds: 500));
    await tester.tapAt(textOffsetToPosition(tester, 0));
    await tester.pump(const Duration(milliseconds: 50));
    await tester.tapAt(textOffsetToPosition(tester, 0));
    await tester.pumpAndSettle();
    expect(selection, isNotNull);
    expect(selection!.baseOffset, 0);
    expect(selection!.extentOffset, 1);
  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.macOS,  TargetPlatform.windows, TargetPlatform.linux, TargetPlatform.fuchsia }));

  testWidgets('double tapping a space selects the previous word on mobile', (WidgetTester tester) async {
    TextSelection? selection;

    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: Center(
            child: SelectableText(
              ' blah blah  \n  blah',
              onSelectionChanged: (TextSelection newSelection, SelectionChangedCause? cause) {
                selection = newSelection;
              },
            ),
          ),
        ),
      ),
    );

    expect(selection, isNull);

    // Put the cursor at the end of the field.
    await tester.tapAt(textOffsetToPosition(tester, 19));
    expect(selection, isNotNull);
    expect(selection!.baseOffset, 19);
    expect(selection!.extentOffset, 19);

    // Double tapping the second space selects the previous word.
    await tester.pump(const Duration(milliseconds: 500));
    await tester.tapAt(textOffsetToPosition(tester, 5));
    await tester.pump(const Duration(milliseconds: 50));
    await tester.tapAt(textOffsetToPosition(tester, 5));
    await tester.pumpAndSettle();
    expect(selection, isNotNull);
    expect(selection!.baseOffset, 1);
    expect(selection!.extentOffset, 5);

    // Double tapping does the same thing for the first space.
    await tester.pump(const Duration(milliseconds: 500));
    await tester.tapAt(textOffsetToPosition(tester, 0));
    await tester.pump(const Duration(milliseconds: 50));
    await tester.tapAt(textOffsetToPosition(tester, 0));
    await tester.pumpAndSettle();
    expect(selection, isNotNull);
    expect(selection!.baseOffset, 0);
    expect(selection!.extentOffset, 1);

    // Put the cursor at the end of the field.
    await tester.tapAt(textOffsetToPosition(tester, 19));
    expect(selection, isNotNull);
    expect(selection!.baseOffset, 19);
    expect(selection!.extentOffset, 19);

    // Double tapping the last space selects all previous contiguous spaces on
    // both lines and the previous word.
    await tester.pump(const Duration(milliseconds: 500));
    await tester.tapAt(textOffsetToPosition(tester, 14));
    await tester.pump(const Duration(milliseconds: 50));
    await tester.tapAt(textOffsetToPosition(tester, 14));
    await tester.pumpAndSettle();
    expect(selection, isNotNull);
    expect(selection!.baseOffset, 6);
    expect(selection!.extentOffset, 14);
  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.android }));

  testWidgets('text selection style 1', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: Center(
            child: Column(
              children: const <Widget>[
                SelectableText.rich(
                  TextSpan(
                    children: <TextSpan>[
                      TextSpan(
                        text: 'Atwater Peel ',
                        style: TextStyle(
                          fontSize: 30.0,
                        ),
                      ),
                      TextSpan(
                        text: 'Sherbrooke Bonaventure ',
                        style: TextStyle(
                          fontSize: 15.0,
                        ),
                      ),
                      TextSpan(
                        text: 'hi wassup!',
                        style: TextStyle(
                          fontSize: 10.0,
                        ),
                      ),
                    ],
                  ),
                  key: Key('field0'),
                  selectionHeightStyle: ui.BoxHeightStyle.includeLineSpacingTop,
                  selectionWidthStyle: ui.BoxWidthStyle.max,
                ),
              ],
            ),
          ),
        ),
      ),
    );

    final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
    final TextEditingController controller = editableTextWidget.controller;
    controller.selection = const TextSelection(baseOffset: 0, extentOffset: 46);
    await tester.pump();

    await expectLater(
      find.byType(MaterialApp),
      matchesGoldenFile('selectable_text_golden.TextSelectionStyle.1.png'),
    );
  });

  testWidgets('text selection style 2', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: Center(
            child: Column(
              children: const <Widget>[
                SelectableText.rich(
                  TextSpan(
                    children: <TextSpan>[
                      TextSpan(
                        text: 'Atwater Peel ',
                        style: TextStyle(
                          fontSize: 30.0,
                        ),
                      ),
                      TextSpan(
                        text: 'Sherbrooke Bonaventure ',
                        style: TextStyle(
                          fontSize: 15.0,
                        ),
                      ),
                      TextSpan(
                        text: 'hi wassup!',
                        style: TextStyle(
                          fontSize: 10.0,
                        ),
                      ),
                    ],
                  ),
                  key: Key('field0'),
                  selectionHeightStyle: ui.BoxHeightStyle.includeLineSpacingBottom,
                ),
              ],
            ),
          ),
        ),
      ),
    );

    final EditableText editableTextWidget = tester.widget(find.byType(EditableText).first);
    final TextEditingController controller = editableTextWidget.controller;
    controller.selection = const TextSelection(baseOffset: 0, extentOffset: 46);
    await tester.pump();

    await expectLater(
      find.byType(MaterialApp),
      matchesGoldenFile('selectable_text_golden.TextSelectionStyle.2.png'),
    );
  });

  testWidgets('keeps alive when has focus', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: DefaultTabController(
          length: 2,
          child: Scaffold(
            body: NestedScrollView(
              headerSliverBuilder:
                (BuildContext context, bool innerBoxIsScrolled) {
                  return <Widget>[
                    SliverToBoxAdapter(
                      child: Container(
                        height: 200,
                        color: Colors.black12,
                        child: const Center(child: Text('Sliver 1')),
                      ),
                    ),
                    const SliverToBoxAdapter(
                      child: Center(
                        child: TabBar(
                          labelColor: Colors.black,
                          tabs: <Tab>[
                            Tab(text: 'Sliver Tab 1'),
                            Tab(text: 'Sliver Tab 2'),
                          ],
                        ),
                      )
                    ),
                  ];
                },
                body: const TabBarView(
                  children: <Widget>[
                    Padding(
                      padding: EdgeInsets.only(top: 100.0),
                      child: Text('Regular Text'),
                    ),
                    Padding(
                      padding: EdgeInsets.only(top: 100.0),
                      child: SelectableText('Selectable Text'),
                    ),
                  ],
                ),
            ),
          ),
        ),
      ),
    );

    // Without any selection, the offscreen widget is disposed and can't be
    // found, for both Text and SelectableText.
    expect(find.text('Regular Text', skipOffstage: false), findsOneWidget);
    expect(find.byType(SelectableText, skipOffstage: false), findsNothing);

    await tester.tap(find.text('Sliver Tab 2'));
    await tester.pumpAndSettle();
    expect(find.text('Regular Text', skipOffstage: false), findsNothing);
    expect(find.byType(SelectableText, skipOffstage: false), findsOneWidget);

    await tester.tap(find.text('Sliver Tab 1'));
    await tester.pumpAndSettle();
    expect(find.text('Regular Text', skipOffstage: false), findsOneWidget);
    expect(find.byType(SelectableText, skipOffstage: false), findsNothing);

    // Switch back to tab 2 and select some text in SelectableText.
    await tester.tap(find.text('Sliver Tab 2'));
    await tester.pumpAndSettle();
    expect(find.text('Regular Text', skipOffstage: false), findsNothing);
    expect(find.byType(SelectableText, skipOffstage: false), findsOneWidget);

    final EditableText editableText = tester.widget(find.byType(EditableText));
    expect(editableText.controller.selection.isValid, isFalse);
    await tester.tapAt(textOffsetToPosition(tester, 4));
    await tester.pump(const Duration(milliseconds: 50));
    await tester.tapAt(textOffsetToPosition(tester, 4));
    await tester.pumpAndSettle();
    expect(editableText.controller.selection.isValid, isTrue);
    expect(editableText.controller.selection.baseOffset, 0);
    expect(editableText.controller.selection.extentOffset, 'Selectable'.length);

    // Switch back to tab 1. The SelectableText remains because it is preserving
    // its selection.
    await tester.tap(find.text('Sliver Tab 1'));
    await tester.pumpAndSettle();
    expect(find.text('Regular Text', skipOffstage: false), findsOneWidget);
    expect(find.byType(SelectableText, skipOffstage: false), findsOneWidget);
  });

  group('magnifier', () {
    late ValueNotifier<MagnifierInfo> magnifierInfo;
    final Widget fakeMagnifier = Container(key: UniqueKey());

    testWidgets(
        'Can drag handles to show, unshow, and update magnifier',
        (WidgetTester tester) async {
      const String testValue = 'abc def ghi';
      final SelectableText selectableText = SelectableText(
            testValue,
            magnifierConfiguration: TextMagnifierConfiguration(
        magnifierBuilder: (
          _,
          MagnifierController controller,
          ValueNotifier<MagnifierInfo> localMagnifierInfo
        ) {
          magnifierInfo = localMagnifierInfo;
          return fakeMagnifier;
        },
      )
          );

      await tester.pumpWidget(
        overlay(
          child: selectableText,
        ),
      );

      await skipPastScrollingAnimation(tester);

      // Double tap the 'e' to select 'def'.
      await tester.tapAt(textOffsetToPosition(tester, testValue.indexOf('e')));
      await tester.pump(const Duration(milliseconds: 30));
      await tester.tapAt(textOffsetToPosition(tester, testValue.indexOf('e')));
      await tester.pump(const Duration(milliseconds: 30));

      final TextSelection selection = TextSelection(
        baseOffset: testValue.indexOf('d'),
        extentOffset: testValue.indexOf('f')
      );

      final RenderEditable renderEditable = findRenderEditable(tester);
      final List<TextSelectionPoint> endpoints = globalize(
        renderEditable.getEndpointsForSelection(selection),
        renderEditable,
      );

      // Drag the right handle 2 letters to the right.
      final Offset handlePos = endpoints.last.point + const Offset(1.0, 1.0);
      final TestGesture gesture = await tester.startGesture(handlePos, pointer: 7);

      Offset? firstDragGesturePosition;

      await gesture.moveTo(textOffsetToPosition(tester, testValue.length - 2));
      await tester.pump();

      expect(find.byKey(fakeMagnifier.key!), findsOneWidget);
      firstDragGesturePosition = magnifierInfo.value.globalGesturePosition;

      await gesture.moveTo(textOffsetToPosition(tester, testValue.length));
      await tester.pump();

      // Expect the position the magnifier gets to have moved.
      expect(firstDragGesturePosition,
          isNot(magnifierInfo.value.globalGesturePosition));

      await gesture.up();
      await tester.pump();

      expect(find.byKey(fakeMagnifier.key!), findsNothing);
    });
  });

  testWidgets('SelectableText text span style is merged with default text style', (WidgetTester tester) async {
    // This is a regression test for https://github.com/flutter/flutter/issues/71389

    const TextStyle textStyle = TextStyle(color: Color(0xff00ff00), fontSize: 12.0);

    await tester.pumpWidget(
      const MaterialApp(
        home: SelectableText.rich(
          TextSpan(
            text: 'Abcd',
            style: textStyle,
          ),
        ),
      ),
    );

    final EditableText editableText = tester.widget(find.byType(EditableText));
    expect(editableText.style.fontSize, textStyle.fontSize);
  });
}
