@@ -1721,6 +1721,89 @@ void main() {
17211721 editable.hitTest (result, position: const Offset (5.0 , 15.0 ));
17221722 expect (result.path, hasLength (0 ));
17231723 }, skip: isBrowser); // https://github.com/flutter/flutter/issues/61020
1724+
1725+ test ('hits correct WidgetSpan when scrolled' , () {
1726+ final String text = '${"\n " * 10 }test' ;
1727+ final TextSelectionDelegate delegate = _FakeEditableTextState ()
1728+ ..textEditingValue = TextEditingValue (
1729+ text: text,
1730+ selection: const TextSelection .collapsed (offset: 13 ),
1731+ );
1732+ final List <RenderBox > renderBoxes = < RenderBox > [
1733+ RenderParagraph (const TextSpan (text: 'a' ), textDirection: TextDirection .ltr),
1734+ RenderParagraph (const TextSpan (text: 'b' ), textDirection: TextDirection .ltr),
1735+ RenderParagraph (const TextSpan (text: 'c' ), textDirection: TextDirection .ltr),
1736+ ];
1737+ final RenderEditable editable = RenderEditable (
1738+ maxLines: null ,
1739+ text: TextSpan (
1740+ style: const TextStyle (height: 1.0 , fontSize: 10.0 ),
1741+ children: < InlineSpan > [
1742+ TextSpan (text: text),
1743+ const WidgetSpan (child: Text ('a' )),
1744+ const TextSpan (children: < InlineSpan > [
1745+ WidgetSpan (child: Text ('b' )),
1746+ WidgetSpan (child: Text ('c' )),
1747+ ],
1748+ ),
1749+ ],
1750+ ),
1751+ startHandleLayerLink: LayerLink (),
1752+ endHandleLayerLink: LayerLink (),
1753+ textDirection: TextDirection .ltr,
1754+ offset: ViewportOffset .fixed (100.0 ), // equal to the height of the 10 empty lines
1755+ textSelectionDelegate: delegate,
1756+ selection: const TextSelection .collapsed (
1757+ offset: 0 ,
1758+ ),
1759+ children: renderBoxes,
1760+ );
1761+ _applyParentData (renderBoxes, editable.text! );
1762+ layout (editable, constraints: BoxConstraints .loose (const Size (500.0 , 500.0 )));
1763+ // Prepare for painting after layout.
1764+ pumpFrame (phase: EnginePhase .compositingBits);
1765+ BoxHitTestResult result = BoxHitTestResult ();
1766+ editable.hitTest (result, position: Offset .zero);
1767+ // We expect two hit test entries in the path because the RenderEditable
1768+ // will add itself as well.
1769+ expect (result.path, hasLength (2 ));
1770+ HitTestTarget target = result.path.first.target;
1771+ expect (target, isA <TextSpan >());
1772+ expect ((target as TextSpan ).text, text);
1773+ // Only testing the RenderEditable entry here once, not anymore below.
1774+ expect (result.path.last.target, isA <RenderEditable >());
1775+ result = BoxHitTestResult ();
1776+ editable.hitTest (result, position: const Offset (15.0 , 0.0 ));
1777+ expect (result.path, hasLength (2 ));
1778+ target = result.path.first.target;
1779+ expect (target, isA <TextSpan >());
1780+ expect ((target as TextSpan ).text, text);
1781+
1782+ result = BoxHitTestResult ();
1783+ editable.hitTest (result, position: const Offset (41.0 , 0.0 ));
1784+ expect (result.path, hasLength (3 ));
1785+ target = result.path.first.target;
1786+ expect (target, isA <TextSpan >());
1787+ expect ((target as TextSpan ).text, 'a' );
1788+
1789+ result = BoxHitTestResult ();
1790+ editable.hitTest (result, position: const Offset (55.0 , 0.0 ));
1791+ expect (result.path, hasLength (3 ));
1792+ target = result.path.first.target;
1793+ expect (target, isA <TextSpan >());
1794+ expect ((target as TextSpan ).text, 'b' );
1795+
1796+ result = BoxHitTestResult ();
1797+ editable.hitTest (result, position: const Offset (69.0 , 5.0 ));
1798+ expect (result.path, hasLength (3 ));
1799+ target = result.path.first.target;
1800+ expect (target, isA <TextSpan >());
1801+ expect ((target as TextSpan ).text, 'c' );
1802+
1803+ result = BoxHitTestResult ();
1804+ editable.hitTest (result, position: const Offset (5.0 , 15.0 ));
1805+ expect (result.path, hasLength (2 ));
1806+ }, skip: isBrowser); // https://github.com/flutter/flutter/issues/61020
17241807 });
17251808
17261809 test ('does not skip TextPainter.layout because of invalid cache' , () {
0 commit comments