// 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'])

import 'dart:ui' as ui show BoxHeightStyle;

import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.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, findRenderEditable;

class _LongCupertinoLocalizationsDelegate extends LocalizationsDelegate<CupertinoLocalizations> {
  const _LongCupertinoLocalizationsDelegate();

  @override
  bool isSupported(Locale locale) => locale.languageCode == 'en';

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

  @override
  bool shouldReload(_LongCupertinoLocalizationsDelegate old) => false;

  @override
  String toString() => '_LongCupertinoLocalizations.delegate(en_US)';
}

class _LongCupertinoLocalizations extends DefaultCupertinoLocalizations {
  const _LongCupertinoLocalizations();

  @override
  String get cutButtonLabel => 'Cutttttttttttttttttttttttttttttttttttttttttttt';
  @override
  String get copyButtonLabel => 'Copyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy';
  @override
  String get pasteButtonLabel => 'Pasteeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee';
  @override
  String get selectAllButtonLabel => 'Select Allllllllllllllllllllllllllllllll';

  static Future<_LongCupertinoLocalizations> load(Locale locale) {
    return SynchronousFuture<_LongCupertinoLocalizations>(const _LongCupertinoLocalizations());
  }

  static const LocalizationsDelegate<CupertinoLocalizations> delegate = _LongCupertinoLocalizationsDelegate();
}

const _LongCupertinoLocalizations _longLocalizations = _LongCupertinoLocalizations();

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

  // Returns true iff the button is visually enabled.
  bool appearsEnabled(WidgetTester tester, String text) {
    final CupertinoButton button = tester.widget<CupertinoButton>(
      find.ancestor(
        of: find.text(text),
        matching: find.byType(CupertinoButton),
      ),
    );
    // Disabled buttons have no opacity change when pressed.
    return button.pressedOpacity! < 1.0;
  }

  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 {
    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,
    );
  });

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

    testWidgets('should return false when there is no text', (WidgetTester tester) async {
      final GlobalKey<EditableTextState> key = GlobalKey();
      await tester.pumpWidget(createEditableText(key: key));
      expect(cupertinoTextSelectionControls.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(cupertinoTextSelectionControls.canSelectAll(key.currentState!), true);
    });

    testWidgets('should return false 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(cupertinoTextSelectionControls.canSelectAll(key.currentState!), false);
    });

    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(cupertinoTextSelectionControls.canSelectAll(key.currentState!), false);
    });
  });

  group('cupertino handles', () {
    testWidgets('draws transparent handle correctly', (WidgetTester tester) async {
      await tester.pumpWidget(RepaintBoundary(
        child: CupertinoTheme(
          data: const CupertinoThemeData(
            primaryColor: Color(0x550000AA),
          ),
          child: Builder(
            builder: (BuildContext context) {
              return Container(
                color: CupertinoColors.white,
                height: 800,
                width: 800,
                child: Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 250),
                  child: FittedBox(
                    child: cupertinoTextSelectionControls.buildHandle(
                      context,
                      TextSelectionHandleType.right,
                      10.0,
                    ),
                  ),
                ),
              );
            },
          ),
        ),
      ));

      await expectLater(
        find.byType(RepaintBoundary),
        matchesGoldenFile('text_selection.handle.transparent.png'),
      );
    });
  });

  group('Text selection menu overflow (iOS)', () {
    testWidgets('All menu items show when they fit.', (WidgetTester tester) async {
      final TextEditingController controller = TextEditingController(text: 'abc def ghi');
      await tester.pumpWidget(CupertinoApp(
        home: Directionality(
            textDirection: TextDirection.ltr,
            child: MediaQuery(
              data: const MediaQueryData(size: Size(800.0, 600.0)),
              child: Center(
                child: CupertinoTextField(
                  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.text('◀'), findsNothing);
      expect(find.text('▶'), findsNothing);

      // Long press on an empty space to show the selection menu.
      await tester.longPressAt(textOffsetToPosition(tester, 4));
      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.text('◀'), findsNothing);
      expect(find.text('▶'), findsNothing);

      // Double tap to select a word and show the full selection menu.
      final Offset textOffset = textOffsetToPosition(tester, 1);
      await tester.tapAt(textOffset);
      await tester.pump(const Duration(milliseconds: 200));
      await tester.tapAt(textOffset);
      await tester.pumpAndSettle();

      // The full menu is shown without the navigation buttons.
      expect(find.text('Cut'), findsOneWidget);
      expect(find.text('Copy'), findsOneWidget);
      expect(find.text('Paste'), findsOneWidget);
      expect(find.text('Select All'), findsNothing);
      expect(find.text('◀'), findsNothing);
      expect(find.text('▶'), findsNothing);
    },
      skip: isBrowser, // [intended] We do not use Flutter-rendered context menu on the Web.
      variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }),
    );

    testWidgets("When a menu item doesn't fit, a second page is used.", (WidgetTester tester) async {
      // Set the screen size to more narrow, so that Paste can't 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(CupertinoApp(
        home: Directionality(
            textDirection: TextDirection.ltr,
            child: MediaQuery(
              data: const MediaQueryData(size: Size(800.0, 600.0)),
              child: Center(
                child: CupertinoTextField(
                  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.text('◀'), findsNothing);
      expect(find.text('▶'), findsNothing);

      // Double tap to select a word and show the selection menu.
      final Offset textOffset = textOffsetToPosition(tester, 1);
      await tester.tapAt(textOffset);
      await tester.pump(const Duration(milliseconds: 200));
      await tester.tapAt(textOffset);
      await tester.pumpAndSettle();

      // The last button is missing, and a next 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.text('◀'), findsNothing);
      expect(find.text('▶'), findsOneWidget);
      expect(appearsEnabled(tester, '▶'), true);

      // Tapping the next button shows the overflowing button.
      await tester.tap(find.text('▶'));
      await tester.pumpAndSettle();
      expect(find.text('Cut'), findsNothing);
      expect(find.text('Copy'), findsNothing);
      expect(find.text('Paste'), findsOneWidget);
      expect(find.text('Select All'), findsNothing);
      expect(find.text('◀'), findsOneWidget);
      expect(appearsEnabled(tester, '◀'), true);
      expect(find.text('▶'), findsOneWidget);
      expect(appearsEnabled(tester, '▶'), false);

      // Tapping the back button shows the first page again.
      await tester.tap(find.text('◀'));
      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.text('◀'), findsNothing);
      expect(find.text('▶'), findsOneWidget);
      expect(appearsEnabled(tester, '▶'), true);
    },
      skip: isBrowser, // [intended] We do not use Flutter-rendered context menu on the Web.
      variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }),
    );

    testWidgets('A smaller menu puts each button on its own page.', (WidgetTester tester) async {
      // Set the screen size to more narrow, so that two buttons can't fit on
      // the same page.
      tester.binding.window.physicalSizeTestValue = const Size(640, 800);
      addTearDown(tester.binding.window.clearPhysicalSizeTestValue);

      final TextEditingController controller = TextEditingController(text: 'abc def ghi');
      await tester.pumpWidget(CupertinoApp(
        home: Directionality(
            textDirection: TextDirection.ltr,
            child: MediaQuery(
              data: const MediaQueryData(size: Size(800.0, 600.0)),
              child: Center(
                child: CupertinoTextField(
                  controller: controller,
                ),
              ),
            ),
          ),
      ));

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

      // Double tap to select a word and show the selection menu.
      final Offset textOffset = textOffsetToPosition(tester, 1);
      await tester.tapAt(textOffset);
      await tester.pump(const Duration(milliseconds: 200));
      await tester.tapAt(textOffset);
      await tester.pumpAndSettle();

      // Only the first button fits, and a next button is shown.
      expect(find.byType(CupertinoButton), findsNWidgets(2));
      expect(find.text('Cut'), findsOneWidget);
      expect(find.text('Copy'), findsNothing);
      expect(find.text('Paste'), findsNothing);
      expect(find.text('Select All'), findsNothing);
      expect(find.text('◀'), findsNothing);
      expect(find.text('▶'), findsOneWidget);
      expect(appearsEnabled(tester, '▶'), true);

      // Tapping the next button shows Copy.
      await tester.tap(find.text('▶'));
      await tester.pumpAndSettle();
      expect(find.byType(CupertinoButton), findsNWidgets(3));
      expect(find.text('Cut'), findsNothing);
      expect(find.text('Copy'), findsOneWidget);
      expect(find.text('Paste'), findsNothing);
      expect(find.text('Select All'), findsNothing);
      expect(find.text('◀'), findsOneWidget);
      expect(appearsEnabled(tester, '◀'), true);
      expect(find.text('▶'), findsOneWidget);
      expect(appearsEnabled(tester, '▶'), true);

      // Tapping the next button again shows Paste.
      await tester.tap(find.text('▶'));
      await tester.pumpAndSettle();
      expect(find.byType(CupertinoButton), findsNWidgets(3));
      expect(find.text('Cut'), findsNothing);
      expect(find.text('Copy'), findsNothing);
      expect(find.text('Paste'), findsOneWidget);
      expect(find.text('Select All'), findsNothing);
      expect(find.text('◀'), findsOneWidget);
      expect(appearsEnabled(tester, '◀'), true);
      expect(find.text('▶'), findsOneWidget);
      expect(appearsEnabled(tester, '▶'), false);

      // Tapping the back button shows the second page again.
      await tester.tap(find.text('◀'));
      await tester.pumpAndSettle();
      expect(find.byType(CupertinoButton), findsNWidgets(3));
      expect(find.text('Cut'), findsNothing);
      expect(find.text('Copy'), findsOneWidget);
      expect(find.text('Paste'), findsNothing);
      expect(find.text('Select All'), findsNothing);
      expect(find.text('◀'), findsOneWidget);
      expect(appearsEnabled(tester, '◀'), true);
      expect(find.text('▶'), findsOneWidget);
      expect(appearsEnabled(tester, '▶'), true);

      // Tapping the back button again shows the first page again.
      await tester.tap(find.text('◀'));
      await tester.pumpAndSettle();
      expect(find.byType(CupertinoButton), findsNWidgets(2));
      expect(find.text('Cut'), findsOneWidget);
      expect(find.text('Copy'), findsNothing);
      expect(find.text('Paste'), findsNothing);
      expect(find.text('Select All'), findsNothing);
      expect(find.text('◀'), findsNothing);
      expect(find.text('▶'), findsOneWidget);
      expect(appearsEnabled(tester, '▶'), true);
    },
      skip: isBrowser, // [intended] We do not use Flutter-rendered context menu on the Web.
      variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }),
    );

    testWidgets('Handles very long locale strings', (WidgetTester tester) async {
      final TextEditingController controller = TextEditingController(text: 'abc def ghi');
      await tester.pumpWidget(CupertinoApp(
        locale: const Locale('en', 'us'),
        localizationsDelegates: const <LocalizationsDelegate<dynamic>>[
          _LongCupertinoLocalizations.delegate,
          DefaultWidgetsLocalizations.delegate,
          DefaultMaterialLocalizations.delegate,
        ],
        home: Directionality(
            textDirection: TextDirection.ltr,
            child: MediaQuery(
              data: const MediaQueryData(size: Size(800.0, 600.0)),
              child: Center(
                child: CupertinoTextField(
                  controller: controller,
                ),
              ),
            ),
          ),
      ));

      // Initially, the menu isn't shown at all.
      expect(find.text(_longLocalizations.cutButtonLabel), findsNothing);
      expect(find.text(_longLocalizations.copyButtonLabel), findsNothing);
      expect(find.text(_longLocalizations.pasteButtonLabel), findsNothing);
      expect(find.text(_longLocalizations.selectAllButtonLabel), findsNothing);
      expect(find.text('◀'), findsNothing);
      expect(find.text('▶'), findsNothing);

      // Long press on an empty space to show the selection menu, with only the
      // paste button visible.
      await tester.longPressAt(textOffsetToPosition(tester, 4));
      await tester.pumpAndSettle();
      expect(find.text(_longLocalizations.cutButtonLabel), findsNothing);
      expect(find.text(_longLocalizations.copyButtonLabel), findsNothing);
      expect(find.text(_longLocalizations.pasteButtonLabel), findsOneWidget);
      expect(find.text(_longLocalizations.selectAllButtonLabel), findsNothing);
      expect(find.text('◀'), findsNothing);
      expect(find.text('▶'), findsOneWidget);
      expect(appearsEnabled(tester, '▶'), true);

      // Tap next to go to the second and final page.
      await tester.tap(find.text('▶'));
      await tester.pumpAndSettle();
      expect(find.text(_longLocalizations.cutButtonLabel), findsNothing);
      expect(find.text(_longLocalizations.copyButtonLabel), findsNothing);
      expect(find.text(_longLocalizations.pasteButtonLabel), findsNothing);
      expect(find.text(_longLocalizations.selectAllButtonLabel), findsOneWidget);
      expect(find.text('◀'), findsOneWidget);
      expect(find.text('▶'), findsOneWidget);
      expect(appearsEnabled(tester, '◀'), true);
      expect(appearsEnabled(tester, '▶'), false);

      // Tap select all to show the full selection menu.
      await tester.tap(find.text(_longLocalizations.selectAllButtonLabel));
      await tester.pumpAndSettle();

      // Only one button fits on each page.
      expect(find.text(_longLocalizations.cutButtonLabel), findsOneWidget);
      expect(find.text(_longLocalizations.copyButtonLabel), findsNothing);
      expect(find.text(_longLocalizations.pasteButtonLabel), findsNothing);
      expect(find.text(_longLocalizations.selectAllButtonLabel), findsNothing);
      expect(find.text('◀'), findsNothing);
      expect(find.text('▶'), findsOneWidget);
      expect(appearsEnabled(tester, '▶'), true);

      // Tap next to go to the second page.
      await tester.tap(find.text('▶'));
      await tester.pumpAndSettle();
      expect(find.text(_longLocalizations.cutButtonLabel), findsNothing);
      expect(find.text(_longLocalizations.copyButtonLabel), findsOneWidget);
      expect(find.text(_longLocalizations.pasteButtonLabel), findsNothing);
      expect(find.text(_longLocalizations.selectAllButtonLabel), findsNothing);
      expect(find.text('◀'), findsOneWidget);
      expect(find.text('▶'), findsOneWidget);
      expect(appearsEnabled(tester, '◀'), true);
      expect(appearsEnabled(tester, '▶'), true);

      // Tap next to go to the third and final page.
      await tester.tap(find.text('▶'));
      await tester.pumpAndSettle();
      expect(find.text(_longLocalizations.cutButtonLabel), findsNothing);
      expect(find.text(_longLocalizations.copyButtonLabel), findsNothing);
      expect(find.text(_longLocalizations.pasteButtonLabel), findsOneWidget);
      expect(find.text(_longLocalizations.selectAllButtonLabel), findsNothing);
      expect(find.text('◀'), findsOneWidget);
      expect(find.text('▶'), findsOneWidget);
      expect(appearsEnabled(tester, '◀'), true);
      expect(appearsEnabled(tester, '▶'), false);

      // Tap back to go to the second page again.
      await tester.tap(find.text('◀'));
      await tester.pumpAndSettle();
      expect(find.text(_longLocalizations.cutButtonLabel), findsNothing);
      expect(find.text(_longLocalizations.copyButtonLabel), findsOneWidget);
      expect(find.text(_longLocalizations.pasteButtonLabel), findsNothing);
      expect(find.text(_longLocalizations.selectAllButtonLabel), findsNothing);
      expect(find.text('◀'), findsOneWidget);
      expect(find.text('▶'), findsOneWidget);
      expect(appearsEnabled(tester, '◀'), true);
      expect(appearsEnabled(tester, '▶'), true);

      // Tap back to go to the first page again.
      await tester.tap(find.text('◀'));
      await tester.pumpAndSettle();
      expect(find.text(_longLocalizations.cutButtonLabel), findsOneWidget);
      expect(find.text(_longLocalizations.copyButtonLabel), findsNothing);
      expect(find.text(_longLocalizations.pasteButtonLabel), findsNothing);
      expect(find.text(_longLocalizations.selectAllButtonLabel), findsNothing);
      expect(find.text('◀'), findsNothing);
      expect(find.text('▶'), findsOneWidget);
      expect(appearsEnabled(tester, '▶'), true);
    },
      skip: isBrowser, // [intended] We do not use Flutter-rendered context menu on the Web.
      variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }),
    );
  });

  testWidgets('iOS selection handles scale with rich text (selection style 1)', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        home: Center(
          child: SelectableText.rich(
            TextSpan(
              children: <InlineSpan>[
                TextSpan(text: 'abc ', style: TextStyle(fontSize: 100.0)),
                TextSpan(text: 'def ', style: TextStyle(fontSize: 50.0)),
                TextSpan(text: 'hij', style: TextStyle(fontSize: 25.0)),
              ],
            ),
          ),
        ),
      ),
    );

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

    // Double tap to select the second 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();
    expect(editableTextState.selectionOverlay!.handlesAreVisible, isTrue);
    expect(controller.selection.baseOffset, 4);
    expect(controller.selection.extentOffset, 7);

    // Drag the right handle 2 letters to the right. Placing the end handle on
    // the third word. We use a small offset because the endpoint is on the very
    // corner of the handle.
    final TextSelection selection = controller.selection;
    final RenderEditable renderEditable = findRenderEditable(tester);
    final List<TextSelectionPoint> endpoints = globalize(
      renderEditable.getEndpointsForSelection(selection),
      renderEditable,
    );
    expect(endpoints.length, 2);

    final Offset handlePos = endpoints[1].point + const Offset(1.0, 1.0);
    final Offset newHandlePos = textOffsetToPosition(tester, 11);
    final TestGesture 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);

    // Find start and end handles and verify their sizes.
    expect(find.byType(Overlay), findsOneWidget);
    expect(find.descendant(
      of: find.byType(Overlay),
      matching: find.byType(CustomPaint),
    ), findsNWidgets(2));

    final Iterable<RenderBox> handles = tester.renderObjectList(find.descendant(
      of: find.byType(Overlay),
      matching: find.byType(CustomPaint),
    ));

    // The handle height is determined by the formula:
    // textLineHeight + _kSelectionHandleRadius * 2 - _kSelectionHandleOverlap .
    // The text line height will be the value of the fontSize.
    // The constant _kSelectionHandleRadius has the value of 6.
    // The constant _kSelectionHandleOverlap has the value of 1.5.
    // In the case of the start handle, which is located on the word 'def',
    // 50.0 + 6 * 2 - 1.5 = 60.5 .
    expect(handles.first.size.height, 60.5);
    expect(handles.last.size.height, 35.5);
  },
    skip: isBrowser, // [intended] We do not use Flutter-rendered context menu on the Web.
    variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }),
  );

  testWidgets('iOS selection handles scale with rich text (selection style 2)', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        home: Center(
          child: SelectableText.rich(
            TextSpan(
              children: <InlineSpan>[
                TextSpan(text: 'abc ', style: TextStyle(fontSize: 100.0)),
                TextSpan(text: 'def ', style: TextStyle(fontSize: 50.0)),
                TextSpan(text: 'hij', style: TextStyle(fontSize: 25.0)),
              ],
            ),
            selectionHeightStyle: ui.BoxHeightStyle.max,
          ),
        ),
      ),
    );

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

    // Double tap to select the second 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();
    expect(editableTextState.selectionOverlay!.handlesAreVisible, isTrue);
    expect(controller.selection.baseOffset, 4);
    expect(controller.selection.extentOffset, 7);

    // Drag the right handle 2 letters to the right. Placing the end handle on
    // the third word. We use a small offset because the endpoint is on the very
    // corner of the handle.
    final TextSelection selection = controller.selection;
    final RenderEditable renderEditable = findRenderEditable(tester);
    final List<TextSelectionPoint> endpoints = globalize(
      renderEditable.getEndpointsForSelection(selection),
      renderEditable,
    );
    expect(endpoints.length, 2);

    final Offset handlePos = endpoints[1].point + const Offset(1.0, 1.0);
    final Offset newHandlePos = textOffsetToPosition(tester, 11);
    final TestGesture 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);

    // Find start and end handles and verify their sizes.
    expect(find.byType(Overlay), findsOneWidget);
    expect(find.descendant(
      of: find.byType(Overlay),
      matching: find.byType(CustomPaint),
    ), findsNWidgets(2));

    final Iterable<RenderBox> handles = tester.renderObjectList(find.descendant(
      of: find.byType(Overlay),
      matching: find.byType(CustomPaint),
    ));

    // The handle height is determined by the formula:
    // textLineHeight + _kSelectionHandleRadius * 2 - _kSelectionHandleOverlap .
    // The text line height will be the value of the fontSize, of the largest word on the line.
    // The constant _kSelectionHandleRadius has the value of 6.
    // The constant _kSelectionHandleOverlap has the value of 1.5.
    // In the case of the start handle, which is located on the word 'def',
    // 100 + 6 * 2 - 1.5 = 110.5 .
    // In this case both selection handles are the same size because the selection
    // height style is set to BoxHeightStyle.max which means that the height of
    // the selection highlight will be the height of the largest word on the line.
    expect(handles.first.size.height, 110.5);
    expect(handles.last.size.height, 110.5);
  },
    skip: isBrowser, // [intended] We do not use Flutter-rendered context menu on the Web.
    variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }),
  );

  testWidgets('iOS selection handles scale with rich text (grapheme clusters)', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        home: Center(
          child: SelectableText.rich(
            TextSpan(
              children: <InlineSpan>[
                TextSpan(text: 'abc ', style: TextStyle(fontSize: 100.0)),
                TextSpan(text: 'def ', style: TextStyle(fontSize: 50.0)),
                TextSpan(text: '👨‍👩‍👦 ', style: TextStyle(fontSize: 35.0)),
                TextSpan(text: 'hij', style: TextStyle(fontSize: 25.0)),
              ],
            ),
          ),
        ),
      ),
    );

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

    // Double tap to select the second 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();
    expect(editableTextState.selectionOverlay!.handlesAreVisible, isTrue);
    expect(controller.selection.baseOffset, 4);
    expect(controller.selection.extentOffset, 7);

    // Drag the right handle 2 letters to the right. Placing the end handle on
    // the third word. We use a small offset because the endpoint is on the very
    // corner of the handle.
    final TextSelection selection = controller.selection;
    final RenderEditable renderEditable = findRenderEditable(tester);
    final List<TextSelectionPoint> endpoints = globalize(
      renderEditable.getEndpointsForSelection(selection),
      renderEditable,
    );
    expect(endpoints.length, 2);

    final Offset handlePos = endpoints[1].point + const Offset(1.0, 1.0);
    final Offset newHandlePos = textOffsetToPosition(tester, 16);
    final TestGesture 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, 16);

    // Find start and end handles and verify their sizes.
    expect(find.byType(Overlay), findsOneWidget);
    expect(find.descendant(
      of: find.byType(Overlay),
      matching: find.byType(CustomPaint),
    ), findsNWidgets(2));

    final Iterable<RenderBox> handles = tester.renderObjectList(find.descendant(
      of: find.byType(Overlay),
      matching: find.byType(CustomPaint),
    ));

    // The handle height is determined by the formula:
    // textLineHeight + _kSelectionHandleRadius * 2 - _kSelectionHandleOverlap .
    // The text line height will be the value of the fontSize.
    // The constant _kSelectionHandleRadius has the value of 6.
    // The constant _kSelectionHandleOverlap has the value of 1.5.
    // In the case of the end handle, which is located on the grapheme cluster '👨‍👩‍👦',
    // 35.0 + 6 * 2 - 1.5 = 45.5 .
    expect(handles.first.size.height, 60.5);
    expect(handles.last.size.height, 45.5);
  },
    skip: isBrowser, // [intended] We do not use Flutter-rendered context menu on the Web.
    variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }),
  );

  testWidgets('iOS selection handles scaling falls back to preferredLineHeight when the current frame does not match the previous', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        home: Center(
          child: SelectableText.rich(
            TextSpan(
              children: <InlineSpan>[
                TextSpan(text: 'abc', style: TextStyle(fontSize: 40.0)),
                TextSpan(text: 'def', style: TextStyle(fontSize: 50.0)),
              ],
            ),
          ),
        ),
      ),
    );

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

    // Double tap to select the second 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();
    expect(editableTextState.selectionOverlay!.handlesAreVisible, isTrue);
    expect(controller.selection.baseOffset, 0);
    expect(controller.selection.extentOffset, 6);

    // Drag the right handle 2 letters to the right. Placing the end handle on
    // the third word. We use a small offset because the endpoint is on the very
    // corner of the handle.
    final TextSelection selection = controller.selection;
    final RenderEditable renderEditable = findRenderEditable(tester);
    final List<TextSelectionPoint> endpoints = globalize(
      renderEditable.getEndpointsForSelection(selection),
      renderEditable,
    );
    expect(endpoints.length, 2);

    final Offset handlePos = endpoints[1].point + const Offset(1.0, 1.0);
    final Offset newHandlePos = textOffsetToPosition(tester, 3);
    final TestGesture 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, 3);

    // Find start and end handles and verify their sizes.
    expect(find.byType(Overlay), findsOneWidget);
    expect(find.descendant(
      of: find.byType(Overlay),
      matching: find.byType(CustomPaint),
    ), findsNWidgets(2));

    final Iterable<RenderBox> handles = tester.renderObjectList(find.descendant(
      of: find.byType(Overlay),
      matching: find.byType(CustomPaint),
    ));

    // The handle height is determined by the formula:
    // textLineHeight + _kSelectionHandleRadius * 2 - _kSelectionHandleOverlap .
    // The text line height will be the value of the fontSize.
    // The constant _kSelectionHandleRadius has the value of 6.
    // The constant _kSelectionHandleOverlap has the value of 1.5.
    // In the case of the start handle, which is located on the word 'abc',
    // 40.0 + 6 * 2 - 1.5 = 50.5 .
    //
    // We are now using the current frames selection and text in order to
    // calculate the start and end handle heights (we fall back to preferredLineHeight
    // when the current frame differs from the previous frame), where previously
    // we would be using a mix of the previous and current frame. This could
    // result in the start and end handle heights being calculated inaccurately
    // if one of the handles falls between two varying text styles.
    expect(handles.first.size.height, 50.5);
    expect(handles.last.size.height, 50.5); // This is 60.5 with the previous frame.
  },
    skip: isBrowser, // [intended] We do not use Flutter-rendered context menu on the Web.
    variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS }),
  );
}
