@@ -164,7 +164,7 @@ extension SuperEditorRobot on WidgetTester {
164
164
/// {@macro supereditor_finder}
165
165
Future <void > tapAtDocumentPosition (DocumentPosition position, [Finder ? superEditorFinder]) async {
166
166
final documentLayout = _findDocumentLayout (superEditorFinder);
167
- final positionRectInDoc = documentLayout. getRectForPosition (position) ! ;
167
+ final positionRectInDoc = _getRectForDocumentPosition (position, documentLayout, superEditorFinder) ;
168
168
final globalTapOffset = documentLayout.getAncestorOffsetFromDocumentOffset (positionRectInDoc.center);
169
169
170
170
await tapAt (globalTapOffset);
@@ -436,17 +436,67 @@ extension SuperEditorRobot on WidgetTester {
436
436
return textLayout.getOffsetForCaret (position) + Offset (affinity == TextAffinity .upstream ? - 1 : 1 , 5 );
437
437
}
438
438
439
+ /// Returns the bounding box around the given [position] , within the associated component.
440
+ ///
441
+ /// If the component is a block component, the returned [Rect] will be half of its width.
442
+ Rect _getRectForDocumentPosition (DocumentPosition position, DocumentLayout documentLayout,
443
+ [Finder ? superEditorFinder]) {
444
+ final component = documentLayout.getComponentByNodeId (position.nodeId);
445
+ if (component == null ) {
446
+ throw Exception ('No component found for node ID: ${position .nodeId }' );
447
+ }
448
+
449
+ if (component.getBeginningPosition () is UpstreamDownstreamNodePosition ) {
450
+ // The component is a block component. Compute the rect manually, because
451
+ // `getRectForPosition` returns always the rect of the whole block.
452
+ // The returned rect will be half of the width of the component.
453
+ final componentBox = component.context.findRenderObject () as RenderBox ;
454
+ final edge = component.getEdgeForPosition (position.nodePosition);
455
+
456
+ final positionRect = position.nodePosition == UpstreamDownstreamNodePosition .upstream ()
457
+ // For upstream position, the edge is a zero width rect starting from the left.
458
+ ? Rect .fromLTWH (
459
+ edge.left,
460
+ edge.top,
461
+ componentBox.size.width / 2 ,
462
+ componentBox.size.height,
463
+ )
464
+ // For downstream position, the edge is a zero width rect starting at the right.
465
+ // Subtract half of the width to make it start from the center.
466
+ : Rect .fromLTWH (
467
+ edge.left - componentBox.size.width / 2 ,
468
+ edge.top,
469
+ componentBox.size.width / 2 ,
470
+ componentBox.size.height,
471
+ );
472
+
473
+ // Translate the rect to global coordinates.
474
+ final documentLayoutElement = _findDocumentLayoutElement (superEditorFinder);
475
+ final docOffset = componentBox.localToGlobal (Offset .zero, ancestor: documentLayoutElement.findRenderObject ());
476
+ return positionRect.translate (docOffset.dx, docOffset.dy);
477
+ }
478
+
479
+ // The component isn't a block node. Use the default implementation for getRectForPosition.
480
+ return documentLayout.getRectForPosition (position)! ;
481
+ }
482
+
439
483
/// Finds and returns the [DocumentLayout] within the only [SuperEditor] in the
440
484
/// widget tree, or within the [SuperEditor] found via the optional [superEditorFinder] .
441
485
DocumentLayout _findDocumentLayout ([Finder ? superEditorFinder]) {
486
+ final documentLayoutElement = _findDocumentLayoutElement (superEditorFinder);
487
+ return documentLayoutElement.state as DocumentLayout ;
488
+ }
489
+
490
+ /// Finds and returns the document layout element within the only [SuperEditor] in the
491
+ /// widget tree, or within the [SuperEditor] found via the optional [superEditorFinder] .
492
+ StatefulElement _findDocumentLayoutElement ([Finder ? superEditorFinder]) {
442
493
late final Finder layoutFinder;
443
494
if (superEditorFinder != null ) {
444
495
layoutFinder = find.descendant (of: superEditorFinder, matching: find.byType (SingleColumnDocumentLayout ));
445
496
} else {
446
497
layoutFinder = find.byType (SingleColumnDocumentLayout );
447
498
}
448
- final documentLayoutElement = layoutFinder.evaluate ().single as StatefulElement ;
449
- return documentLayoutElement.state as DocumentLayout ;
499
+ return layoutFinder.evaluate ().single as StatefulElement ;
450
500
}
451
501
452
502
/// Finds the [GlobalKey] that's attached to the [TextComponent] , which presents the
0 commit comments