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

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

import '../widgets/editable_text_utils.dart' show findRenderEditable, globalize, textOffsetToPosition;

class MockClipboard {
  Object _clipboardData = <String, dynamic>{
    'text': null,
  };

  Future<dynamic> handleMethodCall(MethodCall methodCall) async {
    switch (methodCall.method) {
      case 'Clipboard.getData':
        return _clipboardData;
      case 'Clipboard.setData':
        _clipboardData = methodCall.arguments as Object;
        break;
    }
  }
}

void main() {
  TestWidgetsFlutterBinding.ensureInitialized();
  final MockClipboard mockClipboard = MockClipboard();
  TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, mockClipboard.handleMethodCall);

  setUp(() async {
    await Clipboard.setData(const ClipboardData(text: 'clipboard data'));
  });

  group('canSelectAll', () {
    Widget createEditableText({
      required Key key,
      String? text,
      TextSelection? selection,
    }) {
      final TextEditingController controller = TextEditingController(text: text)
        ..selection = selection ?? const TextSelection.collapsed(offset: -1);
      return MaterialApp(
        home: EditableText(
          key: key,
          controller: controller,
          focusNode: FocusNode(),
          style: const TextStyle(),
          cursorColor: Colors.black,
          backgroundCursorColor: Colors.black,
        ),
      );
    }

    testWidgets('should return false when there is no text', (WidgetTester tester) async {
      final GlobalKey<EditableTextState> key = GlobalKey();
      await tester.pumpWidget(createEditableText(key: key));
      expect(materialTextSelectionControls.canSelectAll(key.currentState!), false);
    });

    testWidgets('should return true when there is text and collapsed selection', (WidgetTester tester) async {
      final GlobalKey<EditableTextState> key = GlobalKey();
      await tester.pumpWidget(createEditableText(
        key: key,
        text: '123',
      ));
      expect(materialTextSelectionControls.canSelectAll(key.currentState!), true);
    });

    testWidgets('should return true when there is text and partial uncollapsed selection', (WidgetTester tester) async {
      final GlobalKey<EditableTextState> key = GlobalKey();
      await tester.pumpWidget(createEditableText(
        key: key,
        text: '123',
        selection: const TextSelection(baseOffset: 1, extentOffset: 2),
      ));
      expect(materialTextSelectionControls.canSelectAll(key.currentState!), true);
    });

    testWidgets('should return false when there is text and full selection', (WidgetTester tester) async {
      final GlobalKey<EditableTextState> key = GlobalKey();
      await tester.pumpWidget(createEditableText(
        key: key,
        text: '123',
        selection: const TextSelection(baseOffset: 0, extentOffset: 3),
      ));
      expect(materialTextSelectionControls.canSelectAll(key.currentState!), false);
    });
  });

  group('Text selection menu overflow (Android)', () {
    testWidgets('All menu items show when they fit.', (WidgetTester tester) async {
      final TextEditingController controller = TextEditingController(text: 'abc def ghi');
      await tester.pumpWidget(MaterialApp(
        theme: ThemeData(platform: TargetPlatform.android),
        home: Directionality(
            textDirection: TextDirection.ltr,
            child: MediaQuery(
              data: const MediaQueryData(size: Size(800.0, 600.0)),
              child: Center(
                child: Material(
                  child: TextField(
                    controller: controller,
                  ),
                ),
              ),
            ),
          ),
      ));

      // Initially, the menu isn't shown at all.
      expect(find.text('Cut'), findsNothing);
      expect(find.text('Copy'), findsNothing);
      expect(find.text('Paste'), findsNothing);
      expect(find.text('Select all'), findsNothing);
      expect(find.byType(IconButton), findsNothing);

      // Tap to place the cursor in the field, then tap the handle to show the
      // selection menu.
      await tester.tap(find.byType(TextField));
      await tester.pumpAndSettle();
      final RenderEditable renderEditable = findRenderEditable(tester);
      final List<TextSelectionPoint> endpoints = globalize(
        renderEditable.getEndpointsForSelection(controller.selection),
        renderEditable,
      );
      expect(endpoints.length, 1);
      final Offset handlePos = endpoints[0].point + const Offset(0.0, 1.0);
      await tester.tapAt(handlePos, pointer: 7);
      await tester.pumpAndSettle();
      expect(find.text('Cut'), findsNothing);
      expect(find.text('Copy'), findsNothing);
      expect(find.text('Paste'), findsOneWidget);
      expect(find.text('Select all'), findsOneWidget);
      expect(find.byType(IconButton), findsNothing);

      // Long press to select a word and show the full selection menu.
      final Offset textOffset = textOffsetToPosition(tester, 1);
      await tester.longPressAt(textOffset);
      await tester.pump();
      await tester.pump();

      // The full menu is shown without the more button.
      expect(find.text('Cut'), findsOneWidget);
      expect(find.text('Copy'), findsOneWidget);
      expect(find.text('Paste'), findsOneWidget);
      expect(find.text('Select all'), findsOneWidget);
      expect(find.byType(IconButton), findsNothing);
    },
      skip: isBrowser, // We do not use Flutter-rendered context menu on the Web
      variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android }),
    );

    testWidgets("When menu items don't fit, an overflow menu is used.", (WidgetTester tester) async {
      // Set the screen size to more narrow, so that Select all can't fit.
      tester.binding.window.physicalSizeTestValue = const Size(1000, 800);
      addTearDown(tester.binding.window.clearPhysicalSizeTestValue);

      final TextEditingController controller = TextEditingController(text: 'abc def ghi');
      await tester.pumpWidget(MaterialApp(
        theme: ThemeData(platform: TargetPlatform.android),
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: MediaQuery(
            data: const MediaQueryData(size: Size(800.0, 600.0)),
            child: Center(
              child: Material(
                child: TextField(
                  controller: controller,
                ),
              ),
            ),
          ),
        ),
      ));

      // Initially, the menu isn't shown at all.
      expect(find.text('Cut'), findsNothing);
      expect(find.text('Copy'), findsNothing);
      expect(find.text('Paste'), findsNothing);
      expect(find.text('Select all'), findsNothing);
      expect(find.byType(IconButton), findsNothing);

      // Long press to show the menu.
      final Offset textOffset = textOffsetToPosition(tester, 1);
      await tester.longPressAt(textOffset);
      await tester.pumpAndSettle();

      // The last button is missing, and a more button is shown.
      expect(find.text('Cut'), findsOneWidget);
      expect(find.text('Copy'), findsOneWidget);
      expect(find.text('Paste'), findsOneWidget);
      expect(find.text('Select all'), findsNothing);
      expect(find.byType(IconButton), findsOneWidget);
      final Offset cutOffset = tester.getTopLeft(find.text('Cut'));

      // Tapping the button shows the overflow menu.
      await tester.tap(find.byType(IconButton));
      await tester.pumpAndSettle();
      expect(find.text('Cut'), findsNothing);
      expect(find.text('Copy'), findsNothing);
      expect(find.text('Paste'), findsNothing);
      expect(find.text('Select all'), findsOneWidget);
      expect(find.byType(IconButton), findsOneWidget);

      // The back button is at the bottom of the overflow menu.
      final Offset selectAllOffset = tester.getTopLeft(find.text('Select all'));
      final Offset moreOffset = tester.getTopLeft(find.byType(IconButton));
      expect(moreOffset.dy, greaterThan(selectAllOffset.dy));

      // The overflow menu grows upward.
      expect(selectAllOffset.dy, lessThan(cutOffset.dy));

      // Tapping the back button shows the selection menu again.
      expect(find.byType(IconButton), findsOneWidget);
      await tester.tap(find.byType(IconButton));
      await tester.pumpAndSettle();
      expect(find.text('Cut'), findsOneWidget);
      expect(find.text('Copy'), findsOneWidget);
      expect(find.text('Paste'), findsOneWidget);
      expect(find.text('Select all'), findsNothing);
      expect(find.byType(IconButton), findsOneWidget);
    },
      skip: isBrowser, // We do not use Flutter-rendered context menu on the Web
      variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android }),
    );

    testWidgets('A smaller menu bumps more items to the overflow menu.', (WidgetTester tester) async {
      // Set the screen size so narrow that only Cut and Copy can fit.
      tester.binding.window.physicalSizeTestValue = const Size(800, 800);
      addTearDown(tester.binding.window.clearPhysicalSizeTestValue);

      final TextEditingController controller = TextEditingController(text: 'abc def ghi');
      await tester.pumpWidget(MaterialApp(
        theme: ThemeData(platform: TargetPlatform.android),
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: MediaQuery(
            data: const MediaQueryData(size: Size(800.0, 600.0)),
            child: Center(
              child: Material(
                child: TextField(
                  controller: controller,
                ),
              ),
            ),
          ),
        ),
      ));

      // Initially, the menu isn't shown at all.
      expect(find.text('Cut'), findsNothing);
      expect(find.text('Copy'), findsNothing);
      expect(find.text('Paste'), findsNothing);
      expect(find.text('Select all'), findsNothing);
      expect(find.byType(IconButton), findsNothing);

      // Long press to show the menu.
      final Offset textOffset = textOffsetToPosition(tester, 1);
      await tester.longPressAt(textOffset);
      await tester.pumpAndSettle();

      // The last two buttons are missing, and a more button is shown.
      expect(find.text('Cut'), findsOneWidget);
      expect(find.text('Copy'), findsOneWidget);
      expect(find.text('Paste'), findsNothing);
      expect(find.text('Select all'), findsNothing);
      expect(find.byType(IconButton), findsOneWidget);

      // Tapping the button shows the overflow menu, which contains both buttons
      // missing from the main menu, and a back button.
      await tester.tap(find.byType(IconButton));
      await tester.pumpAndSettle();
      expect(find.text('Cut'), findsNothing);
      expect(find.text('Copy'), findsNothing);
      expect(find.text('Paste'), findsOneWidget);
      expect(find.text('Select all'), findsOneWidget);
      expect(find.byType(IconButton), findsOneWidget);

      // Tapping the back button shows the selection menu again.
      await tester.tap(find.byType(IconButton));
      await tester.pumpAndSettle();
      expect(find.text('Cut'), findsOneWidget);
      expect(find.text('Copy'), findsOneWidget);
      expect(find.text('Paste'), findsNothing);
      expect(find.text('Select all'), findsNothing);
      expect(find.byType(IconButton), findsOneWidget);
    },
      skip: isBrowser, // We do not use Flutter-rendered context menu on the Web
      variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android }),
    );

    testWidgets('When the menu renders below the text, the overflow menu back button is at the top.', (WidgetTester tester) async {
      // Set the screen size to more narrow, so that Select all can't fit.
      tester.binding.window.physicalSizeTestValue = const Size(1000, 800);
      addTearDown(tester.binding.window.clearPhysicalSizeTestValue);

      final TextEditingController controller = TextEditingController(text: 'abc def ghi');
      await tester.pumpWidget(MaterialApp(
        theme: ThemeData(platform: TargetPlatform.android),
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: MediaQuery(
            data: const MediaQueryData(size: Size(800.0, 600.0)),
            child: Align(
              alignment: Alignment.topLeft,
              child: Material(
                child: TextField(
                  controller: controller,
                ),
              ),
            ),
          ),
        ),
      ));

      // Initially, the menu isn't shown at all.
      expect(find.text('Cut'), findsNothing);
      expect(find.text('Copy'), findsNothing);
      expect(find.text('Paste'), findsNothing);
      expect(find.text('Select all'), findsNothing);
      expect(find.byType(IconButton), findsNothing);

      // Long press to show the menu.
      final Offset textOffset = textOffsetToPosition(tester, 1);
      await tester.longPressAt(textOffset);
      await tester.pumpAndSettle();

      // The last button is missing, and a more button is shown.
      expect(find.text('Cut'), findsOneWidget);
      expect(find.text('Copy'), findsOneWidget);
      expect(find.text('Paste'), findsOneWidget);
      expect(find.text('Select all'), findsNothing);
      expect(find.byType(IconButton), findsOneWidget);
      final Offset cutOffset = tester.getTopLeft(find.text('Cut'));

      // Tapping the button shows the overflow menu.
      await tester.tap(find.byType(IconButton));
      await tester.pumpAndSettle();
      expect(find.text('Cut'), findsNothing);
      expect(find.text('Copy'), findsNothing);
      expect(find.text('Paste'), findsNothing);
      expect(find.text('Select all'), findsOneWidget);
      expect(find.byType(IconButton), findsOneWidget);

      // The back button is at the top of the overflow menu.
      final Offset selectAllOffset = tester.getTopLeft(find.text('Select all'));
      final Offset moreOffset = tester.getTopLeft(find.byType(IconButton));
      expect(moreOffset.dy, lessThan(selectAllOffset.dy));

      // The overflow menu grows downward.
      expect(selectAllOffset.dy, greaterThan(cutOffset.dy));

      // Tapping the back button shows the selection menu again.
      await tester.tap(find.byType(IconButton));
      await tester.pumpAndSettle();
      expect(find.text('Cut'), findsOneWidget);
      expect(find.text('Copy'), findsOneWidget);
      expect(find.text('Paste'), findsOneWidget);
      expect(find.text('Select all'), findsNothing);
      expect(find.byType(IconButton), findsOneWidget);
    },
      skip: isBrowser, // We do not use Flutter-rendered context menu on the Web
      variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android }),
    );

    testWidgets('When the menu items change, the menu is closed and _closedWidth reset.', (WidgetTester tester) async {
      // Set the screen size to more narrow, so that Select all can't fit.
      tester.binding.window.physicalSizeTestValue = const Size(1000, 800);
      addTearDown(tester.binding.window.clearPhysicalSizeTestValue);

      final TextEditingController controller = TextEditingController(text: 'abc def ghi');
      await tester.pumpWidget(MaterialApp(
        theme: ThemeData(platform: TargetPlatform.android),
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: MediaQuery(
            data: const MediaQueryData(size: Size(800.0, 600.0)),
            child: Align(
              alignment: Alignment.topLeft,
              child: Material(
                child: TextField(
                  controller: controller,
                ),
              ),
            ),
          ),
        ),
      ));

      // Initially, the menu isn't shown at all.
      expect(find.text('Cut'), findsNothing);
      expect(find.text('Copy'), findsNothing);
      expect(find.text('Paste'), findsNothing);
      expect(find.text('Select all'), findsNothing);
      expect(find.byType(IconButton), findsNothing);

      // Tap to place the cursor and tap again to show the menu without a
      // selection.
      await tester.tapAt(textOffsetToPosition(tester, 0));
      await tester.pumpAndSettle();
      final RenderEditable renderEditable = findRenderEditable(tester);
      final List<TextSelectionPoint> endpoints = globalize(
        renderEditable.getEndpointsForSelection(controller.selection),
        renderEditable,
      );
      expect(endpoints.length, 1);
      final Offset handlePos = endpoints[0].point + const Offset(0.0, 1.0);
      await tester.tapAt(handlePos, pointer: 7);
      await tester.pumpAndSettle();
      expect(find.text('Cut'), findsNothing);
      expect(find.text('Copy'), findsNothing);
      expect(find.text('Paste'), findsOneWidget);
      expect(find.text('Select all'), findsOneWidget);
      expect(find.byType(IconButton), findsNothing);

      // Tap Select all and measure the usual position of Cut, without
      // _closedWidth having been used yet.
      await tester.tap(find.text('Select all'));
      await tester.pumpAndSettle();
      expect(find.text('Cut'), findsOneWidget);
      expect(find.text('Copy'), findsOneWidget);
      expect(find.text('Paste'), findsOneWidget);
      expect(find.text('Select all'), findsNothing);
      expect(find.byType(IconButton), findsNothing);
      final Offset cutOffset = tester.getTopLeft(find.text('Cut'));

      // Tap to clear the selection.
      await tester.tapAt(textOffsetToPosition(tester, 0));
      await tester.pumpAndSettle();
      expect(find.text('Cut'), findsNothing);
      expect(find.text('Copy'), findsNothing);
      expect(find.text('Paste'), findsNothing);
      expect(find.text('Select all'), findsNothing);
      expect(find.byType(IconButton), findsNothing);

      // Long press to show the menu.
      await tester.longPressAt(textOffsetToPosition(tester, 1));
      await tester.pumpAndSettle();

      // The last button is missing, and a more button is shown.
      expect(find.text('Cut'), findsOneWidget);
      expect(find.text('Copy'), findsOneWidget);
      expect(find.text('Paste'), findsOneWidget);
      expect(find.text('Select all'), findsNothing);
      expect(find.byType(IconButton), findsOneWidget);

      // Tapping the button shows the overflow menu.
      await tester.tap(find.byType(IconButton));
      await tester.pumpAndSettle();
      expect(find.text('Cut'), findsNothing);
      expect(find.text('Copy'), findsNothing);
      expect(find.text('Paste'), findsNothing);
      expect(find.text('Select all'), findsOneWidget);
      expect(find.byType(IconButton), findsOneWidget);

      // Tapping Select all changes the menu items so that there is no no longer
      // any overflow.
      await tester.tap(find.text('Select all'));
      await tester.pumpAndSettle();
      expect(find.text('Cut'), findsOneWidget);
      expect(find.text('Copy'), findsOneWidget);
      expect(find.text('Paste'), findsOneWidget);
      expect(find.text('Select all'), findsNothing);
      expect(find.byType(IconButton), findsNothing);
      final Offset newCutOffset = tester.getTopLeft(find.text('Cut'));
      expect(newCutOffset, equals(cutOffset));
    },
      skip: isBrowser, // We do not use Flutter-rendered context menu on the Web
      variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android }),
    );
  });

  group('menu position', () {
    testWidgets('When renders below a block of text, menu appears below bottom endpoint', (WidgetTester tester) async {
      final TextEditingController controller = TextEditingController(text: 'abc\ndef\nghi\njkl\nmno\npqr');
      await tester.pumpWidget(MaterialApp(
        theme: ThemeData(platform: TargetPlatform.android),
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: MediaQuery(
            data: const MediaQueryData(size: Size(800.0, 600.0)),
            child: Align(
              alignment: Alignment.topLeft,
              child: Material(
                child: TextField(
                  controller: controller,
                ),
              ),
            ),
          ),
        ),
      ));

      // Initially, the menu isn't shown at all.
      expect(find.text('Cut'), findsNothing);
      expect(find.text('Copy'), findsNothing);
      expect(find.text('Paste'), findsNothing);
      expect(find.text('Select all'), findsNothing);
      expect(find.byType(IconButton), findsNothing);

      // Tap to place the cursor in the field, then tap the handle to show the
      // selection menu.
      await tester.tap(find.byType(TextField));
      await tester.pumpAndSettle();
      RenderEditable renderEditable = findRenderEditable(tester);
      List<TextSelectionPoint> endpoints = globalize(
        renderEditable.getEndpointsForSelection(controller.selection),
        renderEditable,
      );
      expect(endpoints.length, 1);
      final Offset handlePos = endpoints[0].point + const Offset(0.0, 1.0);
      await tester.tapAt(handlePos, pointer: 7);
      await tester.pumpAndSettle();
      expect(find.text('Cut'), findsNothing);
      expect(find.text('Copy'), findsNothing);
      expect(find.text('Paste'), findsOneWidget);
      expect(find.text('Select all'), findsOneWidget);
      expect(find.byType(IconButton), findsNothing);

      // Tap to select all.
      await tester.tap(find.text('Select all'));
      await tester.pumpAndSettle();

      // Only Cut, Copy, and Paste are shown.
      expect(find.text('Cut'), findsOneWidget);
      expect(find.text('Copy'), findsOneWidget);
      expect(find.text('Paste'), findsOneWidget);
      expect(find.text('Select all'), findsNothing);
      expect(find.byType(IconButton), findsNothing);

      // The menu appears below the bottom handle.
      renderEditable = findRenderEditable(tester);
      endpoints = globalize(
        renderEditable.getEndpointsForSelection(controller.selection),
        renderEditable,
      );
      expect(endpoints.length, 2);
      final Offset bottomHandlePos = endpoints[1].point;
      final Offset cutOffset = tester.getTopLeft(find.text('Cut'));
      expect(cutOffset.dy, greaterThan(bottomHandlePos.dy));
    },
      skip: isBrowser, // We do not use Flutter-rendered context menu on the Web
      variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android }),
    );
  });

  group('material handles', () {
    testWidgets('draws transparent handle correctly', (WidgetTester tester) async {
      await tester.pumpWidget(RepaintBoundary(
        child: Theme(
          data: ThemeData(
            textSelectionTheme: const TextSelectionThemeData(
              selectionHandleColor: Color(0x550000AA),
            ),
          ),
          child: Builder(
            builder: (BuildContext context) {
              return Container(
                color: Colors.white,
                height: 800,
                width: 800,
                child: Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 250),
                  child: FittedBox(
                    child: materialTextSelectionControls.buildHandle(
                      context, TextSelectionHandleType.right, 10.0, null,
                    ),
                  ),
                ),
              );
            },
          ),
        ),
      ));

      await expectLater(
        find.byType(RepaintBoundary),
        matchesGoldenFile('transparent_handle.png'),
      );
    });

    testWidgets('works with 3 positional parameters', (WidgetTester tester) async {
      await tester.pumpWidget(Theme(
        data: ThemeData(
          textSelectionTheme: const TextSelectionThemeData(
            selectionHandleColor: Color(0x550000AA),
          ),
        ),
        child: Builder(
          builder: (BuildContext context) {
            return Container(
              color: Colors.white,
              height: 800,
              width: 800,
              child: Padding(
                padding: const EdgeInsets.symmetric(horizontal: 250),
                child: FittedBox(
                  child: materialTextSelectionControls.buildHandle(
                    context, TextSelectionHandleType.right, 10.0,
                  ),
                ),
              ),
            );
          },
        ),
      ));

      // No expect here as this should simply compile / not throw any
      // exceptions while building. The test will fail if this either does
      // not compile or if the tester catches an exception, which we do
      // not take here.
    });
  });

  // TODO(justinmc): Paste should only appears when the clipboard has contents.
  //                 https://github.com/flutter/flutter/issues/74139
  testWidgets('Paste always appears regardless of clipboard content on Android', (WidgetTester tester) async {
    final TextEditingController controller = TextEditingController(
      text: 'Atwater Peel Sherbrooke Bonaventure',
    );
    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: Column(
            children: <Widget>[
              TextField(
                controller: controller,
              ),
            ],
          ),
        ),
      ),
    );

    // Make sure the clipboard is empty to start.
    await Clipboard.setData(const ClipboardData(text: ''));

    // Double tap to select the first word.
    const int index = 4;
    await tester.tapAt(textOffsetToPosition(tester, index));
    await tester.pump(const Duration(milliseconds: 50));
    await tester.tapAt(textOffsetToPosition(tester, index));
    await tester.pumpAndSettle();

    // Paste is showing even though clipboard is empty.
    // TODO(justinmc): Paste should not appears when the clipboard is empty.
    //                 https://github.com/flutter/flutter/issues/74139
    expect(find.text('Paste'), findsOneWidget);
    expect(find.text('Copy'), findsOneWidget);
    expect(find.text('Cut'), findsOneWidget);
    expect(find.text('Select all'), findsOneWidget);

    // Tap copy to add something to the clipboard and close the menu.
    await tester.tapAt(tester.getCenter(find.text('Copy')));
    await tester.pumpAndSettle();
    expect(find.text('Copy'), findsNothing);
    expect(find.text('Cut'), findsNothing);
    expect(find.text('Select all'), findsNothing);

    // Double tap to show the menu again.
    await tester.tapAt(textOffsetToPosition(tester, index));
    await tester.pump(const Duration(milliseconds: 50));
    await tester.tapAt(textOffsetToPosition(tester, index));
    await tester.pumpAndSettle();

    // Paste now shows.
    expect(find.text('Copy'), findsOneWidget);
    expect(find.text('Cut'), findsOneWidget);
    expect(find.text('Paste'), findsOneWidget);
    expect(find.text('Select all'), findsOneWidget);
  }, skip: isBrowser, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android }));

  // TODO(justinmc): https://github.com/flutter/flutter/issues/60145
  testWidgets('Paste always appears regardless of clipboard content on iOS', (WidgetTester tester) async {
    final TextEditingController controller = TextEditingController(
      text: 'Atwater Peel Sherbrooke Bonaventure',
    );
    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: Column(
            children: <Widget>[
              TextField(
                controller: controller,
              ),
            ],
          ),
        ),
      ),
    );

    // Make sure the clipboard is empty.
    await Clipboard.setData(const ClipboardData(text: ''));

    // Double tap to select the first word.
    const int index = 4;
    await tester.tapAt(textOffsetToPosition(tester, index));
    await tester.pump(const Duration(milliseconds: 50));
    await tester.tapAt(textOffsetToPosition(tester, index));
    await tester.pumpAndSettle();

    // Paste is showing even though clipboard is empty.
    expect(find.text('Paste'), findsOneWidget);
    expect(find.text('Copy'), findsOneWidget);
    expect(find.text('Cut'), findsOneWidget);

    // Tap copy to add something to the clipboard and close the menu.
    await tester.tapAt(tester.getCenter(find.text('Copy')));
    await tester.pumpAndSettle();
    expect(find.text('Copy'), findsNothing);
    expect(find.text('Cut'), findsNothing);

    // Double tap to show the menu again.
    await tester.tapAt(textOffsetToPosition(tester, index));
    await tester.pump(const Duration(milliseconds: 50));
    await tester.tapAt(textOffsetToPosition(tester, index));
    await tester.pumpAndSettle();

    // Paste still shows.
    expect(find.text('Copy'), findsOneWidget);
    expect(find.text('Cut'), findsOneWidget);
    expect(find.text('Paste'), findsOneWidget);
  }, skip: isBrowser, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }));
}
