@@ -10,6 +10,7 @@ import 'package:flutter/services.dart';
1010import 'package:flutter_test/flutter_test.dart' ;
1111
1212import 'clipboard_utils.dart' ;
13+ import 'editable_text_utils.dart' ;
1314
1415void main () {
1516 late int tapCount;
@@ -628,7 +629,7 @@ void main() {
628629 });
629630
630631 testWidgets ('Mouse drag does not show handles nor toolbar' , (WidgetTester tester) async {
631- // Regressing test for https://github.com/flutter/flutter/issues/69001
632+ // Regression test for https://github.com/flutter/flutter/issues/69001
632633 await tester.pumpWidget (
633634 const MaterialApp (
634635 home: Scaffold (
@@ -652,6 +653,231 @@ void main() {
652653 expect (editableText.selectionOverlay! .toolbarIsVisible, isFalse);
653654 });
654655
656+ testWidgets ('Mouse drag selects and cannot drag cursor' , (WidgetTester tester) async {
657+ // Regression test for https://github.com/flutter/flutter/issues/102928
658+ final TextEditingController controller = TextEditingController (
659+ text: 'I love flutter!' ,
660+ );
661+ final GlobalKey <EditableTextState > editableTextKey = GlobalKey <EditableTextState >();
662+ final FakeTextSelectionGestureDetectorBuilderDelegate delegate = FakeTextSelectionGestureDetectorBuilderDelegate (
663+ editableTextKey: editableTextKey,
664+ forcePressEnabled: false ,
665+ selectionEnabled: true ,
666+ );
667+ final TextSelectionGestureDetectorBuilder provider =
668+ TextSelectionGestureDetectorBuilder (delegate: delegate);
669+
670+ await tester.pumpWidget (
671+ MaterialApp (
672+ home: provider.buildGestureDetector (
673+ behavior: HitTestBehavior .translucent,
674+ child: EditableText (
675+ key: editableTextKey,
676+ controller: controller,
677+ focusNode: FocusNode (),
678+ backgroundCursorColor: Colors .white,
679+ cursorColor: Colors .white,
680+ style: const TextStyle (),
681+ selectionControls: materialTextSelectionControls,
682+ ),
683+ ),
684+ ),
685+ );
686+
687+ expect (controller.selection.isCollapsed, isTrue);
688+ expect (controller.selection.baseOffset, - 1 );
689+
690+ final Offset position = textOffsetToPosition (tester, 4 );
691+
692+ await tester.tapAt (position);
693+ await tester.pump ();
694+
695+ expect (controller.selection.isCollapsed, isTrue);
696+ expect (controller.selection.baseOffset, 4 );
697+
698+ final TestGesture gesture = await tester.startGesture (position, kind: PointerDeviceKind .mouse);
699+ addTearDown (gesture.removePointer);
700+ await tester.pump ();
701+ await gesture.moveTo (textOffsetToPosition (tester, 7 ));
702+ await tester.pump ();
703+ await gesture.moveTo (textOffsetToPosition (tester, 10 ));
704+ await tester.pump ();
705+ await gesture.up ();
706+ await tester.pumpAndSettle ();
707+
708+ expect (controller.selection.isCollapsed, isFalse);
709+ expect (controller.selection.baseOffset, 4 );
710+ expect (controller.selection.extentOffset, 10 );
711+ });
712+
713+ testWidgets ('Touch drag moves the cursor' , (WidgetTester tester) async {
714+ // Regression test for https://github.com/flutter/flutter/issues/102928
715+ final TextEditingController controller = TextEditingController (
716+ text: 'I love flutter!' ,
717+ );
718+ final GlobalKey <EditableTextState > editableTextKey = GlobalKey <EditableTextState >();
719+ final FakeTextSelectionGestureDetectorBuilderDelegate delegate = FakeTextSelectionGestureDetectorBuilderDelegate (
720+ editableTextKey: editableTextKey,
721+ forcePressEnabled: false ,
722+ selectionEnabled: true ,
723+ );
724+ final TextSelectionGestureDetectorBuilder provider =
725+ TextSelectionGestureDetectorBuilder (delegate: delegate);
726+
727+ await tester.pumpWidget (
728+ MaterialApp (
729+ home: provider.buildGestureDetector (
730+ behavior: HitTestBehavior .translucent,
731+ child: EditableText (
732+ key: editableTextKey,
733+ controller: controller,
734+ focusNode: FocusNode (),
735+ backgroundCursorColor: Colors .white,
736+ cursorColor: Colors .white,
737+ style: const TextStyle (),
738+ selectionControls: materialTextSelectionControls,
739+ ),
740+ ),
741+ ),
742+ );
743+
744+ expect (controller.selection.isCollapsed, isTrue);
745+ expect (controller.selection.baseOffset, - 1 );
746+
747+ final Offset position = textOffsetToPosition (tester, 4 );
748+
749+ await tester.tapAt (position);
750+ await tester.pump ();
751+
752+ expect (controller.selection.isCollapsed, isTrue);
753+ expect (controller.selection.baseOffset, 4 );
754+
755+ final TestGesture gesture = await tester.startGesture (position);
756+ addTearDown (gesture.removePointer);
757+ await tester.pump ();
758+ await gesture.moveTo (textOffsetToPosition (tester, 7 ));
759+ await tester.pump ();
760+ await gesture.moveTo (textOffsetToPosition (tester, 10 ));
761+ await tester.pump ();
762+ await gesture.up ();
763+ await tester.pumpAndSettle ();
764+
765+ expect (controller.selection.isCollapsed, isTrue);
766+ expect (controller.selection.baseOffset, 10 );
767+ });
768+
769+ testWidgets ('Stylus drag moves the cursor' , (WidgetTester tester) async {
770+ // Regression test for https://github.com/flutter/flutter/issues/102928
771+ final TextEditingController controller = TextEditingController (
772+ text: 'I love flutter!' ,
773+ );
774+ final GlobalKey <EditableTextState > editableTextKey = GlobalKey <EditableTextState >();
775+ final FakeTextSelectionGestureDetectorBuilderDelegate delegate = FakeTextSelectionGestureDetectorBuilderDelegate (
776+ editableTextKey: editableTextKey,
777+ forcePressEnabled: false ,
778+ selectionEnabled: true ,
779+ );
780+ final TextSelectionGestureDetectorBuilder provider =
781+ TextSelectionGestureDetectorBuilder (delegate: delegate);
782+
783+ await tester.pumpWidget (
784+ MaterialApp (
785+ home: provider.buildGestureDetector (
786+ behavior: HitTestBehavior .translucent,
787+ child: EditableText (
788+ key: editableTextKey,
789+ controller: controller,
790+ focusNode: FocusNode (),
791+ backgroundCursorColor: Colors .white,
792+ cursorColor: Colors .white,
793+ style: const TextStyle (),
794+ selectionControls: materialTextSelectionControls,
795+ ),
796+ ),
797+ ),
798+ );
799+
800+ expect (controller.selection.isCollapsed, isTrue);
801+ expect (controller.selection.baseOffset, - 1 );
802+
803+ final Offset position = textOffsetToPosition (tester, 4 );
804+
805+ await tester.tapAt (position);
806+ await tester.pump ();
807+
808+ expect (controller.selection.isCollapsed, isTrue);
809+ expect (controller.selection.baseOffset, 4 );
810+
811+ final TestGesture gesture = await tester.startGesture (position, kind: PointerDeviceKind .stylus);
812+ addTearDown (gesture.removePointer);
813+ await tester.pump ();
814+ await gesture.moveTo (textOffsetToPosition (tester, 7 ));
815+ await tester.pump ();
816+ await gesture.moveTo (textOffsetToPosition (tester, 10 ));
817+ await tester.pump ();
818+ await gesture.up ();
819+ await tester.pumpAndSettle ();
820+
821+ expect (controller.selection.isCollapsed, isTrue);
822+ expect (controller.selection.baseOffset, 10 );
823+ });
824+
825+ testWidgets ('Drag of unknown type moves the cursor' , (WidgetTester tester) async {
826+ // Regression test for https://github.com/flutter/flutter/issues/102928
827+ final TextEditingController controller = TextEditingController (
828+ text: 'I love flutter!' ,
829+ );
830+ final GlobalKey <EditableTextState > editableTextKey = GlobalKey <EditableTextState >();
831+ final FakeTextSelectionGestureDetectorBuilderDelegate delegate = FakeTextSelectionGestureDetectorBuilderDelegate (
832+ editableTextKey: editableTextKey,
833+ forcePressEnabled: false ,
834+ selectionEnabled: true ,
835+ );
836+ final TextSelectionGestureDetectorBuilder provider =
837+ TextSelectionGestureDetectorBuilder (delegate: delegate);
838+
839+ await tester.pumpWidget (
840+ MaterialApp (
841+ home: provider.buildGestureDetector (
842+ behavior: HitTestBehavior .translucent,
843+ child: EditableText (
844+ key: editableTextKey,
845+ controller: controller,
846+ focusNode: FocusNode (),
847+ backgroundCursorColor: Colors .white,
848+ cursorColor: Colors .white,
849+ style: const TextStyle (),
850+ selectionControls: materialTextSelectionControls,
851+ ),
852+ ),
853+ ),
854+ );
855+
856+ expect (controller.selection.isCollapsed, isTrue);
857+ expect (controller.selection.baseOffset, - 1 );
858+
859+ final Offset position = textOffsetToPosition (tester, 4 );
860+
861+ await tester.tapAt (position);
862+ await tester.pump ();
863+
864+ expect (controller.selection.isCollapsed, isTrue);
865+ expect (controller.selection.baseOffset, 4 );
866+
867+ final TestGesture gesture = await tester.startGesture (position, kind: PointerDeviceKind .unknown);
868+ addTearDown (gesture.removePointer);
869+ await tester.pump ();
870+ await gesture.moveTo (textOffsetToPosition (tester, 7 ));
871+ await tester.pump ();
872+ await gesture.moveTo (textOffsetToPosition (tester, 10 ));
873+ await tester.pump ();
874+ await gesture.up ();
875+ await tester.pumpAndSettle ();
876+
877+ expect (controller.selection.isCollapsed, isTrue);
878+ expect (controller.selection.baseOffset, 10 );
879+ });
880+
655881 testWidgets ('test TextSelectionGestureDetectorBuilder drag with RenderEditable viewport offset change' , (WidgetTester tester) async {
656882 await pumpTextSelectionGestureDetectorBuilder (tester);
657883 final FakeRenderEditable renderEditable = tester.renderObject (find.byType (FakeEditable ));
@@ -767,7 +993,7 @@ void main() {
767993 of: find.byType (CompositedTransformFollower ),
768994 matching: find.descendant (
769995 of: find.byType (FadeTransition ),
770- matching: find.byType (GestureDetector ),
996+ matching: find.byType (RawGestureDetector ),
771997 ),
772998 );
773999
0 commit comments