@@ -29,6 +29,137 @@ const Key _newKey = ValueKey<String>('editorNewButton');
2929
3030void main () {
3131 group ('A-20 EditorView — editable surface' , () {
32+ testWidgets ('shows one-based logical line numbers including a blank tail' , (
33+ WidgetTester tester,
34+ ) async {
35+ final FakeConnection fake = FakeConnection (initial: ConnState .ready);
36+ addTearDown (fake.dispose);
37+ await pumpSurface (tester, const EditorView (), connection: fake);
38+
39+ containerOf (tester)
40+ .read (editorDocumentProvider.notifier)
41+ .openFromBoard (path: '/main.py' , content: 'alpha\n beta\n ' );
42+ await tester.pump ();
43+
44+ expect (find.byKey (kEditorRichSurfaceKey), findsOneWidget);
45+ expect (find.text ('1' ), findsOneWidget);
46+ expect (find.text ('2' ), findsOneWidget);
47+ expect (
48+ find.text ('3' ),
49+ findsOneWidget,
50+ reason: 'a trailing newline creates a numbered blank logical line' ,
51+ );
52+
53+ await tester.enterText (find.byType (EditableText ), 'alpha' );
54+ await tester.pump ();
55+ expect (find.text ('1' ), findsOneWidget);
56+ expect (find.text ('2' ), findsNothing);
57+ expect (find.text ('3' ), findsNothing);
58+ });
59+
60+ testWidgets ('font controls resize code and gutter without editing' , (
61+ WidgetTester tester,
62+ ) async {
63+ final FakeConnection fake = FakeConnection (initial: ConnState .ready);
64+ addTearDown (fake.dispose);
65+ await pumpSurface (tester, const EditorView (), connection: fake);
66+ containerOf (tester)
67+ .read (editorDocumentProvider.notifier)
68+ .openFromBoard (path: '/main.py' , content: 'alpha\n beta' );
69+ await tester.pump ();
70+
71+ final EditableText before = tester.widget <EditableText >(
72+ find.byType (EditableText ),
73+ );
74+ before.controller.selection = const TextSelection .collapsed (offset: 3 );
75+ final EditorDocument documentBefore = containerOf (
76+ tester,
77+ ).read (editorDocumentProvider);
78+
79+ expect (before.style.fontSize, kEditorDefaultFontSize);
80+ expect (tester.widget <Text >(find.text ('1' )).style? .fontSize, 14 );
81+
82+ await tester.tap (find.byKey (kEditorIncreaseFontSizeButtonKey));
83+ await tester.pump ();
84+
85+ final EditableText after = tester.widget <EditableText >(
86+ find.byType (EditableText ),
87+ );
88+ expect (after.style.fontSize, 15 );
89+ expect (tester.widget <Text >(find.text ('1' )).style? .fontSize, 15 );
90+ expect (
91+ after.controller.selection,
92+ const TextSelection .collapsed (offset: 3 ),
93+ );
94+ expect (
95+ containerOf (tester).read (editorDocumentProvider),
96+ same (documentBefore),
97+ );
98+ });
99+
100+ testWidgets ('font buttons are localized and disable at their bounds' , (
101+ WidgetTester tester,
102+ ) async {
103+ final FakeConnection fake = FakeConnection (initial: ConnState .ready);
104+ addTearDown (fake.dispose);
105+ await pumpSurface (tester, const EditorView (), connection: fake);
106+ final AppLocalizations l10n = l10nOf (tester);
107+
108+ expect (
109+ tester
110+ .widget <IconButton >(find.byKey (kEditorDecreaseFontSizeButtonKey))
111+ .tooltip,
112+ l10n.editorDecreaseFontSize,
113+ );
114+ expect (
115+ tester
116+ .widget <IconButton >(find.byKey (kEditorIncreaseFontSizeButtonKey))
117+ .tooltip,
118+ l10n.editorIncreaseFontSize,
119+ );
120+
121+ containerOf (tester)
122+ .read (editorDisplaySettingsProvider.notifier)
123+ .setFontSize (kEditorMinFontSize);
124+ await tester.pump ();
125+ expect (
126+ tester
127+ .widget <IconButton >(find.byKey (kEditorDecreaseFontSizeButtonKey))
128+ .onPressed,
129+ isNull,
130+ );
131+
132+ containerOf (tester)
133+ .read (editorDisplaySettingsProvider.notifier)
134+ .setFontSize (kEditorMaxFontSize);
135+ await tester.pump ();
136+ expect (
137+ tester
138+ .widget <IconButton >(find.byKey (kEditorIncreaseFontSizeButtonKey))
139+ .onPressed,
140+ isNull,
141+ );
142+ });
143+
144+ testWidgets ('compact editor exposes font sizing without overflowing' , (
145+ WidgetTester tester,
146+ ) async {
147+ final FakeConnection fake = FakeConnection (initial: ConnState .ready);
148+ addTearDown (fake.dispose);
149+ await pumpSurface (
150+ tester,
151+ const EditorView (),
152+ connection: fake,
153+ size: const Size (390 , 844 ),
154+ );
155+
156+ expect (find.byKey (kEditorCompactFontSizeButtonKey), findsOneWidget);
157+ expect (tester.takeException (), isNull);
158+ await tester.tap (find.byKey (kEditorCompactFontSizeButtonKey));
159+ await tester.pumpAndSettle ();
160+ expect (find.byKey (kEditorCompactFontSizeIncreaseKey), findsOneWidget);
161+ });
162+
32163 testWidgets ('exposes the app-layer Python to Blocks action' , (
33164 WidgetTester tester,
34165 ) async {
@@ -73,6 +204,11 @@ void main() {
73204 findsOneWidget,
74205 reason: 'the empty buffer shows the localized MicroPython hint' ,
75206 );
207+ expect (
208+ find.text ('1' ),
209+ findsOneWidget,
210+ reason: 'the empty buffer still has logical line one' ,
211+ );
76212 });
77213
78214 testWidgets ('typing updates the current document and marks it dirty' , (
0 commit comments