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

import 'package:flutter/foundation.dart' show defaultTargetPlatform;
import 'package:flutter/gestures.dart' show PointerDeviceKind, kSecondaryButton;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';

import 'clipboard_utils.dart';
import 'editable_text_utils.dart';

void main() {
  late int tapCount;
  late int singleTapUpCount;
  late int singleTapCancelCount;
  late int singleLongTapStartCount;
  late int doubleTapDownCount;
  late int forcePressStartCount;
  late int forcePressEndCount;
  late int dragStartCount;
  late int dragUpdateCount;
  late int dragEndCount;
  const Offset forcePressOffset = Offset(400.0, 50.0);

  void handleTapDown(TapDownDetails details) { tapCount++; }
  void handleSingleTapUp(TapUpDetails details) { singleTapUpCount++; }
  void handleSingleTapCancel() { singleTapCancelCount++; }
  void handleSingleLongTapStart(LongPressStartDetails details) { singleLongTapStartCount++; }
  void handleDoubleTapDown(TapDownDetails details) { doubleTapDownCount++; }
  void handleForcePressStart(ForcePressDetails details) { forcePressStartCount++; }
  void handleForcePressEnd(ForcePressDetails details) { forcePressEndCount++; }
  void handleDragSelectionStart(DragStartDetails details) { dragStartCount++; }
  void handleDragSelectionUpdate(DragStartDetails _, DragUpdateDetails details) { dragUpdateCount++; }
  void handleDragSelectionEnd(DragEndDetails details) { dragEndCount++; }

  setUp(() {
    tapCount = 0;
    singleTapUpCount = 0;
    singleTapCancelCount = 0;
    singleLongTapStartCount = 0;
    doubleTapDownCount = 0;
    forcePressStartCount = 0;
    forcePressEndCount = 0;
    dragStartCount = 0;
    dragUpdateCount = 0;
    dragEndCount = 0;
  });

  Future<void> pumpGestureDetector(WidgetTester tester) async {
    await tester.pumpWidget(
      TextSelectionGestureDetector(
        behavior: HitTestBehavior.opaque,
        onTapDown: handleTapDown,
        onSingleTapUp: handleSingleTapUp,
        onSingleTapCancel: handleSingleTapCancel,
        onSingleLongTapStart: handleSingleLongTapStart,
        onDoubleTapDown: handleDoubleTapDown,
        onForcePressStart: handleForcePressStart,
        onForcePressEnd: handleForcePressEnd,
        onDragSelectionStart: handleDragSelectionStart,
        onDragSelectionUpdate: handleDragSelectionUpdate,
        onDragSelectionEnd: handleDragSelectionEnd,
        child: Container(),
      ),
    );
  }

  Future<void> pumpTextSelectionGestureDetectorBuilder(
    WidgetTester tester, {
    bool forcePressEnabled = true,
    bool selectionEnabled = true,
  }) async {
    final GlobalKey<EditableTextState> editableTextKey = GlobalKey<EditableTextState>();
    final FakeTextSelectionGestureDetectorBuilderDelegate delegate = FakeTextSelectionGestureDetectorBuilderDelegate(
      editableTextKey: editableTextKey,
      forcePressEnabled: forcePressEnabled,
      selectionEnabled: selectionEnabled,
    );
    final TextSelectionGestureDetectorBuilder provider =
    TextSelectionGestureDetectorBuilder(delegate: delegate);

    await tester.pumpWidget(
      MaterialApp(
        home: provider.buildGestureDetector(
          behavior: HitTestBehavior.translucent,
          child: FakeEditableText(key: editableTextKey),
        ),
      ),
    );
  }

  test('TextSelectionOverlay.fadeDuration exist', () async {
    expect(TextSelectionOverlay.fadeDuration, SelectionOverlay.fadeDuration);
  });

  testWidgets('a series of taps all call onTaps', (WidgetTester tester) async {
    await pumpGestureDetector(tester);
    await tester.tapAt(const Offset(200, 200));
    await tester.pump(const Duration(milliseconds: 150));
    await tester.tapAt(const Offset(200, 200));
    await tester.pump(const Duration(milliseconds: 150));
    await tester.tapAt(const Offset(200, 200));
    await tester.pump(const Duration(milliseconds: 150));
    await tester.tapAt(const Offset(200, 200));
    await tester.pump(const Duration(milliseconds: 150));
    await tester.tapAt(const Offset(200, 200));
    await tester.pump(const Duration(milliseconds: 150));
    await tester.tapAt(const Offset(200, 200));
    expect(tapCount, 6);
  });

  testWidgets('in a series of rapid taps, onTapDown and onDoubleTapDown alternate', (WidgetTester tester) async {
    await pumpGestureDetector(tester);
    await tester.tapAt(const Offset(200, 200));
    await tester.pump(const Duration(milliseconds: 50));
    expect(singleTapUpCount, 1);
    await tester.tapAt(const Offset(200, 200));
    await tester.pump(const Duration(milliseconds: 50));
    expect(singleTapUpCount, 1);
    expect(doubleTapDownCount, 1);
    await tester.tapAt(const Offset(200, 200));
    await tester.pump(const Duration(milliseconds: 50));
    expect(singleTapUpCount, 2);
    expect(doubleTapDownCount, 1);
    await tester.tapAt(const Offset(200, 200));
    await tester.pump(const Duration(milliseconds: 50));
    expect(singleTapUpCount, 2);
    expect(doubleTapDownCount, 2);
    await tester.tapAt(const Offset(200, 200));
    await tester.pump(const Duration(milliseconds: 50));
    expect(singleTapUpCount, 3);
    expect(doubleTapDownCount, 2);
    await tester.tapAt(const Offset(200, 200));
    expect(singleTapUpCount, 3);
    expect(doubleTapDownCount, 3);
    expect(tapCount, 6);
  });

  testWidgets('quick tap-tap-hold is a double tap down', (WidgetTester tester) async {
    await pumpGestureDetector(tester);
    await tester.tapAt(const Offset(200, 200));
    await tester.pump(const Duration(milliseconds: 50));
    expect(singleTapUpCount, 1);
    final TestGesture gesture = await tester.startGesture(const Offset(200, 200));
    await tester.pump(const Duration(milliseconds: 200));
    expect(singleTapUpCount, 1);
    // Every down is counted.
    expect(tapCount, 2);
    // No cancels because the second tap of the double tap is a second successful
    // single tap behind the scene.
    expect(singleTapCancelCount, 0);
    expect(doubleTapDownCount, 1);
    // The double tap down hold supersedes the single tap down.
    expect(singleLongTapStartCount, 0);

    await gesture.up();
    // Nothing else happens on up.
    expect(singleTapUpCount, 1);
    expect(tapCount, 2);
    expect(singleTapCancelCount, 0);
    expect(doubleTapDownCount, 1);
    expect(singleLongTapStartCount, 0);
  });

  testWidgets('a very quick swipe is ignored', (WidgetTester tester) async {
    await pumpGestureDetector(tester);
    final TestGesture gesture = await tester.startGesture(const Offset(200, 200));
    await tester.pump(const Duration(milliseconds: 20));
    await gesture.moveBy(const Offset(100, 100));
    await tester.pump();
    expect(singleTapUpCount, 0);
    expect(tapCount, 0);
    expect(singleTapCancelCount, 0);
    expect(doubleTapDownCount, 0);
    expect(singleLongTapStartCount, 0);

    await gesture.up();
    // Nothing else happens on up.
    expect(singleTapUpCount, 0);
    expect(tapCount, 0);
    expect(singleTapCancelCount, 0);
    expect(doubleTapDownCount, 0);
    expect(singleLongTapStartCount, 0);
  });

  testWidgets('a slower swipe has a tap down and a canceled tap', (WidgetTester tester) async {
    await pumpGestureDetector(tester);
    final TestGesture gesture = await tester.startGesture(const Offset(200, 200));
    await tester.pump(const Duration(milliseconds: 120));
    await gesture.moveBy(const Offset(100, 100));
    await tester.pump();
    expect(singleTapUpCount, 0);
    expect(tapCount, 1);
    expect(singleTapCancelCount, 1);
    expect(doubleTapDownCount, 0);
    expect(singleLongTapStartCount, 0);
  });

  testWidgets('a force press initiates a force press', (WidgetTester tester) async {
    await pumpGestureDetector(tester);

    final int pointerValue = tester.nextPointer;

    final TestGesture gesture = await tester.createGesture();

    await gesture.downWithCustomEvent(
      forcePressOffset,
      PointerDownEvent(
        pointer: pointerValue,
        position: forcePressOffset,
        pressure: 0.0,
        pressureMax: 6.0,
        pressureMin: 0.0,
      ),
    );

    await gesture.updateWithCustomEvent(PointerMoveEvent(
      pointer: pointerValue,
      pressure: 0.5,
      pressureMin: 0,
    ));
    await gesture.up();
    await tester.pumpAndSettle();

    await gesture.downWithCustomEvent(
      forcePressOffset,
      PointerDownEvent(
        pointer: pointerValue,
        position: forcePressOffset,
        pressure: 0.0,
        pressureMax: 6.0,
        pressureMin: 0.0,
      ),
    );
    await gesture.updateWithCustomEvent(PointerMoveEvent(
      pointer: pointerValue,
      pressure: 0.5,
      pressureMin: 0,
    ));
    await gesture.up();
    await tester.pump(const Duration(milliseconds: 20));

    await gesture.downWithCustomEvent(
      forcePressOffset,
      PointerDownEvent(
        pointer: pointerValue,
        position: forcePressOffset,
        pressure: 0.0,
        pressureMax: 6.0,
        pressureMin: 0.0,
      ),
    );
    await gesture.updateWithCustomEvent(PointerMoveEvent(
      pointer: pointerValue,
      pressure: 0.5,
      pressureMin: 0,
    ));
    await gesture.up();
    await tester.pump(const Duration(milliseconds: 20));

    await gesture.downWithCustomEvent(
      forcePressOffset,
      PointerDownEvent(
        pointer: pointerValue,
        position: forcePressOffset,
        pressure: 0.0,
        pressureMax: 6.0,
        pressureMin: 0.0,
      ),
    );
    await gesture.updateWithCustomEvent(PointerMoveEvent(
      pointer: pointerValue,
      pressure: 0.5,
      pressureMin: 0,
    ));
    await gesture.up();

    expect(forcePressStartCount, 4);
  });

  testWidgets('a tap and then force press initiates a force press and not a double tap', (WidgetTester tester) async {
    await pumpGestureDetector(tester);

    final int pointerValue = tester.nextPointer;
    final TestGesture gesture = await tester.createGesture();
    await gesture.downWithCustomEvent(
      forcePressOffset,
      PointerDownEvent(
          pointer: pointerValue,
          position: forcePressOffset,
          pressure: 0.0,
          pressureMax: 6.0,
          pressureMin: 0.0,
      ),

    );
    // Initiate a quick tap.
    await gesture.updateWithCustomEvent(
      PointerMoveEvent(
        pointer: pointerValue,
        pressure: 0.0,
        pressureMin: 0,
      ),
    );
    await tester.pump(const Duration(milliseconds: 50));
    await gesture.up();

    // Initiate a force tap.
    await gesture.downWithCustomEvent(
      forcePressOffset,
      PointerDownEvent(
        pointer: pointerValue,
        position: forcePressOffset,
        pressure: 0.0,
        pressureMax: 6.0,
        pressureMin: 0.0,
      ),
    );
    await gesture.updateWithCustomEvent(PointerMoveEvent(
      pointer: pointerValue,
      pressure: 0.5,
      pressureMin: 0,
    ));
    expect(forcePressStartCount, 1);

    await tester.pump(const Duration(milliseconds: 50));
    await gesture.up();
    await tester.pumpAndSettle();

    expect(forcePressEndCount, 1);
    expect(doubleTapDownCount, 0);
  });

  testWidgets('a long press from a touch device is recognized as a long single tap', (WidgetTester tester) async {
    await pumpGestureDetector(tester);

    final int pointerValue = tester.nextPointer;
    final TestGesture gesture = await tester.startGesture(
      const Offset(200.0, 200.0),
      pointer: pointerValue,
    );
    await tester.pump(const Duration(seconds: 2));
    await gesture.up();
    await tester.pumpAndSettle();

    expect(tapCount, 1);
    expect(singleTapUpCount, 0);
    expect(singleLongTapStartCount, 1);
  });

  testWidgets('a long press from a mouse is just a tap', (WidgetTester tester) async {
    await pumpGestureDetector(tester);

    final int pointerValue = tester.nextPointer;
    final TestGesture gesture = await tester.startGesture(
      const Offset(200.0, 200.0),
      pointer: pointerValue,
      kind: PointerDeviceKind.mouse,
    );
    await tester.pump(const Duration(seconds: 2));
    await gesture.up();
    await tester.pumpAndSettle();

    expect(tapCount, 1);
    expect(singleTapUpCount, 1);
    expect(singleLongTapStartCount, 0);
  });

  testWidgets('a touch drag is not recognized for text selection', (WidgetTester tester) async {
    await pumpGestureDetector(tester);

    final int pointerValue = tester.nextPointer;
    final TestGesture gesture = await tester.startGesture(
      const Offset(200.0, 200.0),
      pointer: pointerValue,
    );
    await tester.pump();
    await gesture.moveBy(const Offset(210.0, 200.0));
    await tester.pump();
    await gesture.up();
    await tester.pumpAndSettle();

    expect(tapCount, 0);
    expect(singleTapUpCount, 0);
    expect(dragStartCount, 0);
    expect(dragUpdateCount, 0);
    expect(dragEndCount, 0);
  });

  testWidgets('a mouse drag is recognized for text selection', (WidgetTester tester) async {
    await pumpGestureDetector(tester);

    final int pointerValue = tester.nextPointer;
    final TestGesture gesture = await tester.startGesture(
      const Offset(200.0, 200.0),
      pointer: pointerValue,
      kind: PointerDeviceKind.mouse,
    );
    await tester.pump();
    await gesture.moveBy(const Offset(210.0, 200.0));
    await tester.pump();
    await gesture.up();
    await tester.pumpAndSettle();

    expect(tapCount, 0);
    expect(singleTapUpCount, 0);
    expect(dragStartCount, 1);
    expect(dragUpdateCount, 1);
    expect(dragEndCount, 1);
  });

  testWidgets('a slow mouse drag is still recognized for text selection', (WidgetTester tester) async {
    await pumpGestureDetector(tester);

    final int pointerValue = tester.nextPointer;
    final TestGesture gesture = await tester.startGesture(
      const Offset(200.0, 200.0),
      pointer: pointerValue,
      kind: PointerDeviceKind.mouse,
    );
    await tester.pump(const Duration(seconds: 2));
    await gesture.moveBy(const Offset(210.0, 200.0));
    await tester.pump();
    await gesture.up();
    await tester.pumpAndSettle();

    expect(dragStartCount, 1);
    expect(dragUpdateCount, 1);
    expect(dragEndCount, 1);
  });

  testWidgets('test TextSelectionGestureDetectorBuilder long press', (WidgetTester tester) async {
    await pumpTextSelectionGestureDetectorBuilder(tester);
    final TestGesture gesture = await tester.startGesture(
      const Offset(200.0, 200.0),
      pointer: 0,
    );
    await tester.pump(const Duration(seconds: 2));
    await gesture.up();
    await tester.pumpAndSettle();

    final FakeEditableTextState state = tester.state(find.byType(FakeEditableText));
    final FakeRenderEditable renderEditable = tester.renderObject(find.byType(FakeEditable));
    expect(state.showToolbarCalled, isTrue);
    expect(renderEditable.selectPositionAtCalled, isTrue);
  });

  testWidgets('TextSelectionGestureDetectorBuilder right click Apple platforms', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/80119
    await pumpTextSelectionGestureDetectorBuilder(tester);

    final FakeRenderEditable renderEditable = tester.renderObject(find.byType(FakeEditable));
    renderEditable.text = const TextSpan(text: 'one two three four five six seven');
    await tester.pump();

    final TestGesture gesture = await tester.createGesture(
      pointer: 0,
      kind: PointerDeviceKind.mouse,
      buttons: kSecondaryButton,
    );

    // Get the location of the 10th character
    final Offset charLocation = renderEditable
        .getLocalRectForCaret(const TextPosition(offset: 10)).center;
    final Offset globalCharLocation = charLocation + tester.getTopLeft(find.byType(FakeEditable));

    // Right clicking on a word should select it
    await gesture.down(globalCharLocation);
    await gesture.up();
    await tester.pump();
    expect(renderEditable.selectWordCalled, isTrue);

    // Right clicking on a word within a selection shouldn't change the selection
    renderEditable.selectWordCalled = false;
    renderEditable.selection = const TextSelection(baseOffset: 3, extentOffset: 20);
    await gesture.down(globalCharLocation);
    await gesture.up();
    await tester.pump();
    expect(renderEditable.selectWordCalled, isFalse);

    // Right clicking on a word within a reverse (right-to-left) selection shouldn't change the selection
    renderEditable.selectWordCalled = false;
    renderEditable.selection = const TextSelection(baseOffset: 20, extentOffset: 3);
    await gesture.down(globalCharLocation);
    await gesture.up();
    await tester.pump();
    expect(renderEditable.selectWordCalled, isFalse);
  },
    variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }),
  );

  testWidgets('TextSelectionGestureDetectorBuilder right click non-Apple platforms', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/80119
    await pumpTextSelectionGestureDetectorBuilder(tester);

    final FakeRenderEditable renderEditable = tester.renderObject(find.byType(FakeEditable));
    renderEditable.text = const TextSpan(text: 'one two three four five six seven');
    await tester.pump();

    final TestGesture gesture = await tester.createGesture(
      pointer: 0,
      kind: PointerDeviceKind.mouse,
      buttons: kSecondaryButton,
    );

    // Get the location of the 10th character
    final Offset charLocation = renderEditable
        .getLocalRectForCaret(const TextPosition(offset: 10)).center;
    final Offset globalCharLocation = charLocation + tester.getTopLeft(find.byType(FakeEditable));

    // Right clicking on an unfocused field should place the cursor, not select
    // the word.
    await gesture.down(globalCharLocation);
    await gesture.up();
    await tester.pump();
    expect(renderEditable.selectWordCalled, isFalse);
    expect(renderEditable.selectPositionCalled, isTrue);

    // Right clicking on a focused field with selection shouldn't change the
    // selection.
    renderEditable.selectPositionCalled = false;
    renderEditable.selection = const TextSelection(baseOffset: 3, extentOffset: 20);
    renderEditable.hasFocus = true;
    await gesture.down(globalCharLocation);
    await gesture.up();
    await tester.pump();
    expect(renderEditable.selectWordCalled, isFalse);
    expect(renderEditable.selectPositionCalled, isFalse);

    // Right clicking on a focused field with a reverse (right to left)
    // selection shouldn't change the selection.
    renderEditable.selection = const TextSelection(baseOffset: 20, extentOffset: 3);
    await gesture.down(globalCharLocation);
    await gesture.up();
    await tester.pump();
    expect(renderEditable.selectWordCalled, isFalse);
    expect(renderEditable.selectPositionCalled, isFalse);
  },
    variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.fuchsia, TargetPlatform.linux, TargetPlatform.windows }),
  );

  testWidgets('test TextSelectionGestureDetectorBuilder tap', (WidgetTester tester) async {
    await pumpTextSelectionGestureDetectorBuilder(tester);
    final TestGesture gesture = await tester.startGesture(
      const Offset(200.0, 200.0),
      pointer: 0,
    );
    await gesture.up();
    await tester.pumpAndSettle();

    final FakeEditableTextState state = tester.state(find.byType(FakeEditableText));
    final FakeRenderEditable renderEditable = tester.renderObject(find.byType(FakeEditable));
    expect(state.showToolbarCalled, isFalse);

    switch (defaultTargetPlatform) {
      case TargetPlatform.iOS:
        expect(renderEditable.selectWordEdgeCalled, isTrue);
        break;
      case TargetPlatform.macOS:
      case TargetPlatform.android:
      case TargetPlatform.fuchsia:
      case TargetPlatform.linux:
      case TargetPlatform.windows:
        expect(renderEditable.selectPositionAtCalled, isTrue);
        break;
    }
  }, variant: TargetPlatformVariant.all());

  testWidgets('test TextSelectionGestureDetectorBuilder double tap', (WidgetTester tester) async {
    await pumpTextSelectionGestureDetectorBuilder(tester);
    final TestGesture gesture = await tester.startGesture(
      const Offset(200.0, 200.0),
      pointer: 0,
    );
    await tester.pump(const Duration(milliseconds: 50));
    await gesture.up();
    await gesture.down(const Offset(200.0, 200.0));
    await tester.pump(const Duration(milliseconds: 50));
    await gesture.up();
    await tester.pumpAndSettle();

    final FakeEditableTextState state = tester.state(find.byType(FakeEditableText));
    final FakeRenderEditable renderEditable = tester.renderObject(find.byType(FakeEditable));
    expect(state.showToolbarCalled, isTrue);
    expect(renderEditable.selectWordCalled, isTrue);
  });

  testWidgets('test TextSelectionGestureDetectorBuilder forcePress enabled', (WidgetTester tester) async {
    await pumpTextSelectionGestureDetectorBuilder(tester);
    final TestGesture gesture = await tester.createGesture();
    await gesture.downWithCustomEvent(
      const Offset(200.0, 200.0),
      const PointerDownEvent(
        position: Offset(200.0, 200.0),
        pressure: 3.0,
        pressureMax: 6.0,
        pressureMin: 0.0,
      ),
    );
    await gesture.updateWithCustomEvent(
      const PointerUpEvent(
        position: Offset(200.0, 200.0),
        pressureMax: 6.0,
        pressureMin: 0.0,
      ),
    );
    await tester.pump();

    final FakeEditableTextState state = tester.state(find.byType(FakeEditableText));
    final FakeRenderEditable renderEditable = tester.renderObject(find.byType(FakeEditable));
    expect(state.showToolbarCalled, isTrue);
    expect(renderEditable.selectWordsInRangeCalled, isTrue);
  });

  testWidgets('Mouse drag does not show handles nor toolbar', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/69001
    await tester.pumpWidget(
      const MaterialApp(
        home: Scaffold(
          body: 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();
    await gesture.moveTo(textFieldStart + const Offset(50.0, 0));
    await tester.pump();
    await gesture.up();
    await tester.pumpAndSettle();

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

  testWidgets('Mouse drag selects and cannot drag cursor', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/102928
    final TextEditingController controller = TextEditingController(
      text: 'I love flutter!',
    );
    final GlobalKey<EditableTextState> editableTextKey = GlobalKey<EditableTextState>();
    final FakeTextSelectionGestureDetectorBuilderDelegate delegate = FakeTextSelectionGestureDetectorBuilderDelegate(
      editableTextKey: editableTextKey,
      forcePressEnabled: false,
      selectionEnabled: true,
    );
    final TextSelectionGestureDetectorBuilder provider =
        TextSelectionGestureDetectorBuilder(delegate: delegate);

    await tester.pumpWidget(
      MaterialApp(
        home: provider.buildGestureDetector(
          behavior: HitTestBehavior.translucent,
          child: EditableText(
            key: editableTextKey,
            controller: controller,
            focusNode: FocusNode(),
            backgroundCursorColor: Colors.white,
            cursorColor: Colors.white,
            style: const TextStyle(),
            selectionControls: materialTextSelectionControls,
          ),
        ),
      ),
    );

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

    final Offset position = textOffsetToPosition(tester, 4);

    await tester.tapAt(position);
    await tester.pump();

    expect(controller.selection.isCollapsed, isTrue);
    expect(controller.selection.baseOffset, 4);

    final TestGesture gesture = await tester.startGesture(position, kind: PointerDeviceKind.mouse);
    addTearDown(gesture.removePointer);
    await tester.pump();
    await gesture.moveTo(textOffsetToPosition(tester, 7));
    await tester.pump();
    await gesture.moveTo(textOffsetToPosition(tester, 10));
    await tester.pump();
    await gesture.up();
    await tester.pumpAndSettle();

    expect(controller.selection.isCollapsed, isFalse);
    expect(controller.selection.baseOffset, 4);
    expect(controller.selection.extentOffset, 10);
  });

  testWidgets('Touch drag moves the cursor', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/102928
    final TextEditingController controller = TextEditingController(
      text: 'I love flutter!',
    );
    final GlobalKey<EditableTextState> editableTextKey = GlobalKey<EditableTextState>();
    final FakeTextSelectionGestureDetectorBuilderDelegate delegate = FakeTextSelectionGestureDetectorBuilderDelegate(
      editableTextKey: editableTextKey,
      forcePressEnabled: false,
      selectionEnabled: true,
    );
    final TextSelectionGestureDetectorBuilder provider =
        TextSelectionGestureDetectorBuilder(delegate: delegate);

    await tester.pumpWidget(
      MaterialApp(
        home: provider.buildGestureDetector(
          behavior: HitTestBehavior.translucent,
          child: EditableText(
            key: editableTextKey,
            controller: controller,
            focusNode: FocusNode(),
            backgroundCursorColor: Colors.white,
            cursorColor: Colors.white,
            style: const TextStyle(),
            selectionControls: materialTextSelectionControls,
          ),
        ),
      ),
    );

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

    final Offset position = textOffsetToPosition(tester, 4);

    await tester.tapAt(position);
    await tester.pump();

    expect(controller.selection.isCollapsed, isTrue);
    expect(controller.selection.baseOffset, 4);

    final TestGesture gesture = await tester.startGesture(position);
    addTearDown(gesture.removePointer);
    await tester.pump();
    await gesture.moveTo(textOffsetToPosition(tester, 7));
    await tester.pump();
    await gesture.moveTo(textOffsetToPosition(tester, 10));
    await tester.pump();
    await gesture.up();
    await tester.pumpAndSettle();

    expect(controller.selection.isCollapsed, isTrue);
    expect(controller.selection.baseOffset, 10);
  });

  testWidgets('Stylus drag moves the cursor', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/102928
    final TextEditingController controller = TextEditingController(
      text: 'I love flutter!',
    );
    final GlobalKey<EditableTextState> editableTextKey = GlobalKey<EditableTextState>();
    final FakeTextSelectionGestureDetectorBuilderDelegate delegate = FakeTextSelectionGestureDetectorBuilderDelegate(
      editableTextKey: editableTextKey,
      forcePressEnabled: false,
      selectionEnabled: true,
    );
    final TextSelectionGestureDetectorBuilder provider =
        TextSelectionGestureDetectorBuilder(delegate: delegate);

    await tester.pumpWidget(
      MaterialApp(
        home: provider.buildGestureDetector(
          behavior: HitTestBehavior.translucent,
          child: EditableText(
            key: editableTextKey,
            controller: controller,
            focusNode: FocusNode(),
            backgroundCursorColor: Colors.white,
            cursorColor: Colors.white,
            style: const TextStyle(),
            selectionControls: materialTextSelectionControls,
          ),
        ),
      ),
    );

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

    final Offset position = textOffsetToPosition(tester, 4);

    await tester.tapAt(position);
    await tester.pump();

    expect(controller.selection.isCollapsed, isTrue);
    expect(controller.selection.baseOffset, 4);

    final TestGesture gesture = await tester.startGesture(position, kind: PointerDeviceKind.stylus);
    addTearDown(gesture.removePointer);
    await tester.pump();
    await gesture.moveTo(textOffsetToPosition(tester, 7));
    await tester.pump();
    await gesture.moveTo(textOffsetToPosition(tester, 10));
    await tester.pump();
    await gesture.up();
    await tester.pumpAndSettle();

    expect(controller.selection.isCollapsed, isTrue);
    expect(controller.selection.baseOffset, 10);
  });

  testWidgets('Drag of unknown type moves the cursor', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/102928
    final TextEditingController controller = TextEditingController(
      text: 'I love flutter!',
    );
    final GlobalKey<EditableTextState> editableTextKey = GlobalKey<EditableTextState>();
    final FakeTextSelectionGestureDetectorBuilderDelegate delegate = FakeTextSelectionGestureDetectorBuilderDelegate(
      editableTextKey: editableTextKey,
      forcePressEnabled: false,
      selectionEnabled: true,
    );
    final TextSelectionGestureDetectorBuilder provider =
        TextSelectionGestureDetectorBuilder(delegate: delegate);

    await tester.pumpWidget(
      MaterialApp(
        home: provider.buildGestureDetector(
          behavior: HitTestBehavior.translucent,
          child: EditableText(
            key: editableTextKey,
            controller: controller,
            focusNode: FocusNode(),
            backgroundCursorColor: Colors.white,
            cursorColor: Colors.white,
            style: const TextStyle(),
            selectionControls: materialTextSelectionControls,
          ),
        ),
      ),
    );

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

    final Offset position = textOffsetToPosition(tester, 4);

    await tester.tapAt(position);
    await tester.pump();

    expect(controller.selection.isCollapsed, isTrue);
    expect(controller.selection.baseOffset, 4);

    final TestGesture gesture = await tester.startGesture(position, kind: PointerDeviceKind.unknown);
    addTearDown(gesture.removePointer);
    await tester.pump();
    await gesture.moveTo(textOffsetToPosition(tester, 7));
    await tester.pump();
    await gesture.moveTo(textOffsetToPosition(tester, 10));
    await tester.pump();
    await gesture.up();
    await tester.pumpAndSettle();

    expect(controller.selection.isCollapsed, isTrue);
    expect(controller.selection.baseOffset, 10);
  });

  testWidgets('test TextSelectionGestureDetectorBuilder drag with RenderEditable viewport offset change', (WidgetTester tester) async {
    await pumpTextSelectionGestureDetectorBuilder(tester);
    final FakeRenderEditable renderEditable = tester.renderObject(find.byType(FakeEditable));

    // Reconfigure the RenderEditable for multi-line.
    renderEditable.maxLines = null;
    renderEditable.offset = ViewportOffset.fixed(20.0);
    renderEditable.layout(const BoxConstraints.tightFor(width: 400, height: 300.0));
    await tester.pumpAndSettle();

    final TestGesture gesture = await tester.startGesture(
      const Offset(200.0, 200.0),
      kind: PointerDeviceKind.mouse,
    );
    await tester.pumpAndSettle();
    expect(renderEditable.selectPositionAtCalled, isFalse);

    await gesture.moveTo(const Offset(300.0, 200.0));
    await tester.pumpAndSettle();
    expect(renderEditable.selectPositionAtCalled, isTrue);
    expect(renderEditable.selectPositionAtFrom, const Offset(200.0, 200.0));
    expect(renderEditable.selectPositionAtTo, const Offset(300.0, 200.0));

    // Move the viewport offset (scroll).
    renderEditable.offset = ViewportOffset.fixed(150.0);
    renderEditable.layout(const BoxConstraints.tightFor(width: 400, height: 300.0));
    await tester.pumpAndSettle();

    await gesture.moveTo(const Offset(300.0, 400.0));
    await tester.pumpAndSettle();
    await gesture.up();
    await tester.pumpAndSettle();
    expect(renderEditable.selectPositionAtCalled, isTrue);
    expect(renderEditable.selectPositionAtFrom, const Offset(200.0, 70.0));
    expect(renderEditable.selectPositionAtTo, const Offset(300.0, 400.0));
  });

  testWidgets('test TextSelectionGestureDetectorBuilder selection disabled', (WidgetTester tester) async {
    await pumpTextSelectionGestureDetectorBuilder(tester, selectionEnabled: false);
    final TestGesture gesture = await tester.startGesture(
      const Offset(200.0, 200.0),
      pointer: 0,
    );
    await tester.pump(const Duration(seconds: 2));
    await gesture.up();
    await tester.pumpAndSettle();

    final FakeEditableTextState state = tester.state(find.byType(FakeEditableText));
    final FakeRenderEditable renderEditable = tester.renderObject(find.byType(FakeEditable));
    expect(state.showToolbarCalled, isTrue);
    expect(renderEditable.selectWordsInRangeCalled, isFalse);
  });

  testWidgets('test TextSelectionGestureDetectorBuilder mouse drag disabled', (WidgetTester tester) async {
    await pumpTextSelectionGestureDetectorBuilder(tester, selectionEnabled: false);
    final TestGesture gesture = await tester.startGesture(
      Offset.zero,
      kind: PointerDeviceKind.mouse,
    );
    await tester.pump();
    await gesture.moveTo(const Offset(50.0, 0));
    await tester.pump();
    await gesture.up();
    await tester.pumpAndSettle();

    final FakeRenderEditable renderEditable = tester.renderObject(find.byType(FakeEditable));
    expect(renderEditable.selectPositionAtCalled, isFalse);
  });

  testWidgets('test TextSelectionGestureDetectorBuilder forcePress disabled', (WidgetTester tester) async {
    await pumpTextSelectionGestureDetectorBuilder(tester, forcePressEnabled: false);
    final TestGesture gesture = await tester.createGesture();
    await gesture.downWithCustomEvent(
      const Offset(200.0, 200.0),
      const PointerDownEvent(
        position: Offset(200.0, 200.0),
        pressure: 3.0,
        pressureMax: 6.0,
        pressureMin: 0.0,
      ),
    );
    await gesture.up();
    await tester.pump();

    final FakeEditableTextState state = tester.state(find.byType(FakeEditableText));
    final FakeRenderEditable renderEditable = tester.renderObject(find.byType(FakeEditable));
    expect(state.showToolbarCalled, isFalse);
    expect(renderEditable.selectWordsInRangeCalled, isFalse);
  });

  // Regression test for https://github.com/flutter/flutter/issues/37032.
  testWidgets("selection handle's GestureDetector should not cover the entire screen", (WidgetTester tester) async {
    final TextEditingController controller = TextEditingController(text: 'a');

    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: TextField(
            autofocus: true,
            controller: controller,
          ),
        ),
      ),
    );

    await tester.pumpAndSettle();

    final Finder gestureDetector = find.descendant(
      of: find.byType(CompositedTransformFollower),
      matching: find.descendant(
        of: find.byType(FadeTransition),
        matching: find.byType(RawGestureDetector),
      ),
    );

    expect(gestureDetector, findsOneWidget);
    // The GestureDetector's size should not exceed that of the TextField.
    final Rect hitRect = tester.getRect(gestureDetector);
    final Rect textFieldRect = tester.getRect(find.byType(TextField));

    expect(hitRect.size.width, lessThan(textFieldRect.size.width));
    expect(hitRect.size.height, lessThan(textFieldRect.size.height));
  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }));

  group('SelectionOverlay', () {
    Future<SelectionOverlay> pumpApp(WidgetTester tester, {
      ValueChanged<DragStartDetails>? onStartDragStart,
      ValueChanged<DragUpdateDetails>? onStartDragUpdate,
      ValueChanged<DragEndDetails>? onStartDragEnd,
      ValueChanged<DragStartDetails>? onEndDragStart,
      ValueChanged<DragUpdateDetails>? onEndDragUpdate,
      ValueChanged<DragEndDetails>? onEndDragEnd,
      VoidCallback? onSelectionHandleTapped,
      TextSelectionControls? selectionControls,
      TextMagnifierConfiguration? magnifierConfiguration,
    }) async {
      final UniqueKey column = UniqueKey();
      final LayerLink startHandleLayerLink = LayerLink();
      final LayerLink endHandleLayerLink = LayerLink();
      final LayerLink toolbarLayerLink = LayerLink();
      await tester.pumpWidget(MaterialApp(
        home: Column(
          key: column,
          children: <Widget>[
            CompositedTransformTarget(
              link: startHandleLayerLink,
              child: const Text('start handle'),
            ),
            CompositedTransformTarget(
              link: endHandleLayerLink,
              child: const Text('end handle'),
            ),
            CompositedTransformTarget(
              link: toolbarLayerLink,
              child: const Text('toolbar'),
            ),
          ],
        ),
      ));

      return SelectionOverlay(
        context: tester.element(find.byKey(column)),
        onSelectionHandleTapped: onSelectionHandleTapped,
        startHandleType: TextSelectionHandleType.collapsed,
        startHandleLayerLink: startHandleLayerLink,
        lineHeightAtStart: 0.0,
        onStartHandleDragStart: onStartDragStart,
        onStartHandleDragUpdate: onStartDragUpdate,
        onStartHandleDragEnd: onStartDragEnd,
        endHandleType: TextSelectionHandleType.collapsed,
        endHandleLayerLink: endHandleLayerLink,
        lineHeightAtEnd: 0.0,
        onEndHandleDragStart: onEndDragStart,
        onEndHandleDragUpdate: onEndDragUpdate,
        onEndHandleDragEnd: onEndDragEnd,
        clipboardStatus: FakeClipboardStatusNotifier(),
        selectionDelegate: FakeTextSelectionDelegate(),
        selectionControls: selectionControls,
        selectionEndpoints: const <TextSelectionPoint>[],
        toolbarLayerLink: toolbarLayerLink,
        magnifierConfiguration: magnifierConfiguration ?? TextMagnifierConfiguration.disabled,
      );
    }

    testWidgets('can show and hide handles', (WidgetTester tester) async {
      final TextSelectionControlsSpy spy = TextSelectionControlsSpy();
      final SelectionOverlay selectionOverlay = await pumpApp(
        tester,
        selectionControls: spy,
      );
      selectionOverlay
        ..startHandleType = TextSelectionHandleType.left
        ..endHandleType = TextSelectionHandleType.right
        ..selectionEndpoints = const <TextSelectionPoint>[
          TextSelectionPoint(Offset(10, 10), TextDirection.ltr),
          TextSelectionPoint(Offset(20, 20), TextDirection.ltr),
        ];
      selectionOverlay.showHandles();
      await tester.pump();
      expect(find.byKey(spy.leftHandleKey), findsOneWidget);
      expect(find.byKey(spy.rightHandleKey), findsOneWidget);

      selectionOverlay.hideHandles();
      await tester.pump();
      expect(find.byKey(spy.leftHandleKey), findsNothing);
      expect(find.byKey(spy.rightHandleKey), findsNothing);

      selectionOverlay.showToolbar();
      await tester.pump();
      expect(find.byKey(spy.toolBarKey), findsOneWidget);

      selectionOverlay.hideToolbar();
      await tester.pump();
      expect(find.byKey(spy.toolBarKey), findsNothing);

      selectionOverlay.showHandles();
      selectionOverlay.showToolbar();
      await tester.pump();
      expect(find.byKey(spy.leftHandleKey), findsOneWidget);
      expect(find.byKey(spy.rightHandleKey), findsOneWidget);
      expect(find.byKey(spy.toolBarKey), findsOneWidget);

      selectionOverlay.hide();
      await tester.pump();
      expect(find.byKey(spy.leftHandleKey), findsNothing);
      expect(find.byKey(spy.rightHandleKey), findsNothing);
      expect(find.byKey(spy.toolBarKey), findsNothing);
    });

    testWidgets('only paints one collapsed handle', (WidgetTester tester) async {
      final TextSelectionControlsSpy spy = TextSelectionControlsSpy();
      final SelectionOverlay selectionOverlay = await pumpApp(
        tester,
        selectionControls: spy,
      );
      selectionOverlay
        ..startHandleType = TextSelectionHandleType.collapsed
        ..endHandleType = TextSelectionHandleType.collapsed
        ..selectionEndpoints = const <TextSelectionPoint>[
          TextSelectionPoint(Offset(10, 10), TextDirection.ltr),
          TextSelectionPoint(Offset(20, 20), TextDirection.ltr),
        ];
      selectionOverlay.showHandles();
      await tester.pump();
      expect(find.byKey(spy.leftHandleKey), findsNothing);
      expect(find.byKey(spy.rightHandleKey), findsNothing);
      expect(find.byKey(spy.collapsedHandleKey), findsOneWidget);
    });

    testWidgets('can change handle parameter', (WidgetTester tester) async {
      final TextSelectionControlsSpy spy = TextSelectionControlsSpy();
      final SelectionOverlay selectionOverlay = await pumpApp(
        tester,
        selectionControls: spy,
      );
      selectionOverlay
        ..startHandleType = TextSelectionHandleType.left
        ..lineHeightAtStart = 10.0
        ..endHandleType = TextSelectionHandleType.right
        ..lineHeightAtEnd = 11.0
        ..selectionEndpoints = const <TextSelectionPoint>[
          TextSelectionPoint(Offset(10, 10), TextDirection.ltr),
          TextSelectionPoint(Offset(20, 20), TextDirection.ltr),
        ];
      selectionOverlay.showHandles();
      await tester.pump();
      Text leftHandle = tester.widget(find.byKey(spy.leftHandleKey)) as Text;
      Text rightHandle = tester.widget(find.byKey(spy.rightHandleKey)) as Text;
      expect(leftHandle.data, 'height 10');
      expect(rightHandle.data, 'height 11');

      selectionOverlay
        ..startHandleType = TextSelectionHandleType.right
        ..lineHeightAtStart = 12.0
        ..endHandleType = TextSelectionHandleType.left
        ..lineHeightAtEnd = 13.0;
      await tester.pump();
      leftHandle = tester.widget(find.byKey(spy.leftHandleKey)) as Text;
      rightHandle = tester.widget(find.byKey(spy.rightHandleKey)) as Text;
      expect(leftHandle.data, 'height 13');
      expect(rightHandle.data, 'height 12');
    });

    testWidgets('can trigger selection handle onTap', (WidgetTester tester) async {
      bool selectionHandleTapped = false;
      void handleTapped() => selectionHandleTapped = true;
      final TextSelectionControlsSpy spy = TextSelectionControlsSpy();
      final SelectionOverlay selectionOverlay = await pumpApp(
        tester,
        onSelectionHandleTapped: handleTapped,
        selectionControls: spy,
      );
      selectionOverlay
        ..startHandleType = TextSelectionHandleType.left
        ..lineHeightAtStart = 10.0
        ..endHandleType = TextSelectionHandleType.right
        ..lineHeightAtEnd = 11.0
        ..selectionEndpoints = const <TextSelectionPoint>[
          TextSelectionPoint(Offset(10, 10), TextDirection.ltr),
          TextSelectionPoint(Offset(20, 20), TextDirection.ltr),
        ];
      selectionOverlay.showHandles();
      await tester.pump();
      expect(find.byKey(spy.leftHandleKey), findsOneWidget);
      expect(find.byKey(spy.rightHandleKey), findsOneWidget);
      expect(selectionHandleTapped, isFalse);

      await tester.tap(find.byKey(spy.leftHandleKey));
      expect(selectionHandleTapped, isTrue);

      selectionHandleTapped = false;
      await tester.tap(find.byKey(spy.rightHandleKey));
      expect(selectionHandleTapped, isTrue);
    });

    testWidgets('can trigger selection handle drag', (WidgetTester tester) async {
      DragStartDetails? startDragStartDetails;
      DragUpdateDetails? startDragUpdateDetails;
      DragEndDetails? startDragEndDetails;
      DragStartDetails? endDragStartDetails;
      DragUpdateDetails? endDragUpdateDetails;
      DragEndDetails? endDragEndDetails;
      void startDragStart(DragStartDetails details) => startDragStartDetails = details;
      void startDragUpdate(DragUpdateDetails details) => startDragUpdateDetails = details;
      void startDragEnd(DragEndDetails details) => startDragEndDetails = details;
      void endDragStart(DragStartDetails details) => endDragStartDetails = details;
      void endDragUpdate(DragUpdateDetails details) => endDragUpdateDetails = details;
      void endDragEnd(DragEndDetails details) => endDragEndDetails = details;
      final TextSelectionControlsSpy spy = TextSelectionControlsSpy();
      final SelectionOverlay selectionOverlay = await pumpApp(
        tester,
        onStartDragStart: startDragStart,
        onStartDragUpdate: startDragUpdate,
        onStartDragEnd: startDragEnd,
        onEndDragStart: endDragStart,
        onEndDragUpdate: endDragUpdate,
        onEndDragEnd: endDragEnd,
        selectionControls: spy,
      );
      selectionOverlay
        ..startHandleType = TextSelectionHandleType.left
        ..lineHeightAtStart = 10.0
        ..endHandleType = TextSelectionHandleType.right
        ..lineHeightAtEnd = 11.0
        ..selectionEndpoints = const <TextSelectionPoint>[
          TextSelectionPoint(Offset(10, 10), TextDirection.ltr),
          TextSelectionPoint(Offset(20, 20), TextDirection.ltr),
        ];
      selectionOverlay.showHandles();
      await tester.pump();
      expect(find.byKey(spy.leftHandleKey), findsOneWidget);
      expect(find.byKey(spy.rightHandleKey), findsOneWidget);
      expect(startDragStartDetails, isNull);
      expect(startDragUpdateDetails, isNull);
      expect(startDragEndDetails, isNull);
      expect(endDragStartDetails, isNull);
      expect(endDragUpdateDetails, isNull);
      expect(endDragEndDetails, isNull);

      final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byKey(spy.leftHandleKey)));
      await tester.pump(const Duration(milliseconds: 200));
      expect(startDragStartDetails!.globalPosition, tester.getCenter(find.byKey(spy.leftHandleKey)));

      const Offset newLocation = Offset(20, 20);
      await gesture.moveTo(newLocation);
      await tester.pump(const Duration(milliseconds: 20));
      expect(startDragUpdateDetails!.globalPosition, newLocation);

      await gesture.up();
      await tester.pump(const Duration(milliseconds: 20));
      expect(startDragEndDetails, isNotNull);

      final TestGesture gesture2 = await tester.startGesture(tester.getCenter(find.byKey(spy.rightHandleKey)));
      addTearDown(gesture2.removePointer);
      await tester.pump(const Duration(milliseconds: 200));
      expect(endDragStartDetails!.globalPosition, tester.getCenter(find.byKey(spy.rightHandleKey)));

      await gesture2.moveTo(newLocation);
      await tester.pump(const Duration(milliseconds: 20));
      expect(endDragUpdateDetails!.globalPosition, newLocation);

      await gesture2.up();
      await tester.pump(const Duration(milliseconds: 20));
      expect(endDragEndDetails, isNotNull);
    });

    testWidgets('can show magnifier when no handles exist', (WidgetTester tester) async {
      final GlobalKey magnifierKey = GlobalKey();
      final SelectionOverlay selectionOverlay = await pumpApp(
        tester,
        magnifierConfiguration: TextMagnifierConfiguration(
          shouldDisplayHandlesInMagnifier: false,
          magnifierBuilder: (BuildContext context, MagnifierController controller, ValueNotifier<MagnifierInfo>? notifier) {
            return SizedBox.shrink(
              key: magnifierKey,
            );
          },
        ),
      );

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

      final MagnifierInfo info = MagnifierInfo(
        globalGesturePosition: Offset.zero,
        caretRect: Offset.zero & const Size(5.0, 20.0),
        fieldBounds: Offset.zero & const Size(200.0, 50.0),
        currentLineBoundaries: Offset.zero & const Size(200.0, 50.0),
      );
      selectionOverlay.showMagnifier(info);
      await tester.pump();

      expect(tester.takeException(), isNull);
      expect(find.byKey(magnifierKey), findsOneWidget);
    });
  });

  group('ClipboardStatusNotifier', () {
    group('when Clipboard fails', () {
      setUp(() {
        final MockClipboard mockClipboard = MockClipboard(hasStringsThrows: true);
        TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, mockClipboard.handleMethodCall);
      });

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

      test('Clipboard API failure is gracefully recovered from', () async {
        final ClipboardStatusNotifier notifier = ClipboardStatusNotifier();
        expect(notifier.value, ClipboardStatus.unknown);

        await expectLater(notifier.update(), completes);
        expect(notifier.value, ClipboardStatus.unknown);
      });
    });

    group('when Clipboard succeeds', () {
      final MockClipboard mockClipboard = MockClipboard();

      setUp(() {
        TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, mockClipboard.handleMethodCall);
      });

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

      test('update sets value based on clipboard contents', () async {
        final ClipboardStatusNotifier notifier = ClipboardStatusNotifier();
        expect(notifier.value, ClipboardStatus.unknown);

        await expectLater(notifier.update(), completes);
        expect(notifier.value, ClipboardStatus.notPasteable);

        mockClipboard.handleMethodCall(const MethodCall(
          'Clipboard.setData',
          <String, dynamic>{
            'text': 'pasteablestring',
          },
        ));
        await expectLater(notifier.update(), completes);
        expect(notifier.value, ClipboardStatus.pasteable);
      });
    });
  });
}

class FakeTextSelectionGestureDetectorBuilderDelegate implements TextSelectionGestureDetectorBuilderDelegate {
  FakeTextSelectionGestureDetectorBuilderDelegate({
    required this.editableTextKey,
    required this.forcePressEnabled,
    required this.selectionEnabled,
  });

  @override
  final GlobalKey<EditableTextState> editableTextKey;

  @override
  final bool forcePressEnabled;

  @override
  final bool selectionEnabled;
}

class FakeEditableText extends EditableText {
  FakeEditableText({super.key}): super(
    controller: TextEditingController(),
    focusNode: FocusNode(),
    backgroundCursorColor: Colors.white,
    cursorColor: Colors.white,
    style: const TextStyle(),
  );

  @override
  FakeEditableTextState createState() => FakeEditableTextState();
}

class FakeEditableTextState extends EditableTextState {
  final GlobalKey _editableKey = GlobalKey();
  bool showToolbarCalled = false;

  @override
  RenderEditable get renderEditable => _editableKey.currentContext!.findRenderObject()! as RenderEditable;

  @override
  bool showToolbar() {
    showToolbarCalled = true;
    return true;
  }

  @override
  void toggleToolbar() {
    return;
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return FakeEditable(this, key: _editableKey);
  }
}

class FakeEditable extends LeafRenderObjectWidget {
  const FakeEditable(
    this.delegate, {
    super.key,
  });
  final EditableTextState delegate;

  @override
  RenderEditable createRenderObject(BuildContext context) {
    return FakeRenderEditable(delegate);
  }
}

class FakeRenderEditable extends RenderEditable {
  FakeRenderEditable(EditableTextState delegate) : super(
    text: const TextSpan(
      style: TextStyle(height: 1.0, fontSize: 10.0, fontFamily: 'Ahem'),
      text: 'placeholder',
    ),
    startHandleLayerLink: LayerLink(),
    endHandleLayerLink: LayerLink(),
    ignorePointer: true,
    textAlign: TextAlign.start,
    textDirection: TextDirection.ltr,
    locale: const Locale('en', 'US'),
    offset: ViewportOffset.fixed(10.0),
    textSelectionDelegate: delegate,
    selection: const TextSelection.collapsed(
      offset: 0,
    ),
  );

  bool selectWordsInRangeCalled = false;
  @override
  void selectWordsInRange({ required Offset from, Offset? to, required SelectionChangedCause cause }) {
    selectWordsInRangeCalled = true;
    hasFocus = true;
  }

  bool selectWordEdgeCalled = false;
  @override
  void selectWordEdge({ required SelectionChangedCause cause }) {
    selectWordEdgeCalled = true;
    hasFocus = true;
  }

  bool selectPositionAtCalled = false;
  Offset? selectPositionAtFrom;
  Offset? selectPositionAtTo;
  @override
  void selectPositionAt({ required Offset from, Offset? to, required SelectionChangedCause cause }) {
    selectPositionAtCalled = true;
    selectPositionAtFrom = from;
    selectPositionAtTo = to;
    hasFocus = true;
  }

  bool selectPositionCalled = false;
  @override
  void selectPosition({ required SelectionChangedCause cause }) {
    selectPositionCalled = true;
    return super.selectPosition(cause: cause);
  }

  bool selectWordCalled = false;
  @override
  void selectWord({ required SelectionChangedCause cause }) {
    selectWordCalled = true;
    hasFocus = true;
  }

  @override
  bool hasFocus = false;
}

class TextSelectionControlsSpy extends TextSelectionControls {
  UniqueKey leftHandleKey = UniqueKey();
  UniqueKey rightHandleKey = UniqueKey();
  UniqueKey collapsedHandleKey = UniqueKey();
  UniqueKey toolBarKey = UniqueKey();

  @override
  Widget buildHandle(BuildContext context, TextSelectionHandleType type, double textLineHeight, [VoidCallback? onTap]) {
    switch (type) {
      case TextSelectionHandleType.left:
        return ElevatedButton(onPressed: onTap, child: Text('height ${textLineHeight.toInt()}', key: leftHandleKey));
      case TextSelectionHandleType.right:
        return ElevatedButton(onPressed: onTap, child: Text('height ${textLineHeight.toInt()}', key: rightHandleKey));
      case TextSelectionHandleType.collapsed:
        return ElevatedButton(onPressed: onTap, child: Text('height ${textLineHeight.toInt()}', key: collapsedHandleKey));
    }
  }

  @override
  Widget buildToolbar(
    BuildContext context,
    Rect globalEditableRegion,
    double textLineHeight,
    Offset position,
    List<TextSelectionPoint> endpoints,
    TextSelectionDelegate delegate,
    ClipboardStatusNotifier? clipboardStatus,
    Offset? lastSecondaryTapDownPosition,
  ) {
    return Text('dummy', key: toolBarKey);
  }

  @override
  Offset getHandleAnchor(TextSelectionHandleType type, double textLineHeight) {
    return Offset.zero;
  }

  @override
  Size getHandleSize(double textLineHeight) {
    return Size(textLineHeight, textLineHeight);
  }
}

class FakeClipboardStatusNotifier extends ClipboardStatusNotifier {
  FakeClipboardStatusNotifier() : super(value: ClipboardStatus.unknown);

  bool updateCalled = false;
  @override
  Future<void> update() async {
    updateCalled = true;
  }
}

class FakeTextSelectionDelegate extends Fake implements TextSelectionDelegate {
  @override
  void cutSelection(SelectionChangedCause cause) { }

  @override
  void copySelection(SelectionChangedCause cause) { }
}
