@@ -287,7 +287,12 @@ Future<void> _tapVisible(WidgetTester tester, Finder finder) async {
287287 // A real Android IME can keep the footer below the resized render surface
288288 // even after ensureVisible scrolls its RenderBox. Commit the field edit and
289289 // restore the full viewport before resolving the action's tap position.
290+ // The integration binding also retains its focusedEditable pointer after a
291+ // modal closes even though Android has closed that text-input connection.
292+ // Clear the pointer with the focus so a later enterText on the same field
293+ // requests a fresh connection instead of sending the edit to the stale one.
290294 FocusManager .instance.primaryFocus? .unfocus ();
295+ tester.binding.focusedEditable = null ;
291296 await SystemChannels .textInput.invokeMethod <void >('TextInput.hide' );
292297 await tester.pumpAndSettle ();
293298 await tester.ensureVisible (finder);
@@ -775,8 +780,23 @@ pixels.write()
775780 find.byKey (const ValueKey <String >('blocksExampleCard-blink-led' )),
776781 );
777782 await tester.pumpAndSettle ();
778- await tester.enterText (find.widgetWithText (TextField , 'LED GPIO' ), '17' );
783+ final Finder labelledLedGpioField = find.widgetWithText (
784+ TextField ,
785+ 'LED GPIO' ,
786+ );
787+ expect (labelledLedGpioField, findsOneWidget);
788+ final Key ? ledGpioFieldKey = tester
789+ .widget <TextField >(labelledLedGpioField)
790+ .key;
791+ expect (
792+ ledGpioFieldKey,
793+ isNotNull,
794+ reason: 'the responsive chooser must retain a stable GPIO field key' ,
795+ );
796+ final Finder ledGpioField = find.byKey (ledGpioFieldKey! );
797+ await tester.enterText (ledGpioField, '17' );
779798 await tester.pumpAndSettle ();
799+ expect (tester.widget <TextField >(ledGpioField).controller? .text, '17' );
780800 expect (
781801 find.textContaining ('Pin(17, Pin.OUT' ),
782802 findsNothing,
@@ -801,14 +821,23 @@ pixels.write()
801821 // -> sealed Blockly generator path with a real MicroPython named pin.
802822 // Editing remains local until Preview, and the active workspace and
803823 // connected board remain untouched by the disposable scratch run.
804- final Finder ledGpioField = find.widgetWithText (TextField , 'LED GPIO' );
805824 await tester.enterText (ledGpioField, 'LED' );
806825 await tester.pumpAndSettle ();
826+ expect (
827+ tester.widget <TextField >(ledGpioField).controller? .text,
828+ 'LED' ,
829+ reason: 'the fresh Android text connection must commit the named pin' ,
830+ );
807831 expect (
808832 find.textContaining ('Pin("LED", Pin.OUT' ),
809833 findsNothing,
810834 reason: 'named GPIO editing must not generate before Preview' ,
811835 );
836+ expect (
837+ find.textContaining ('Pin(17, Pin.OUT' ),
838+ findsNothing,
839+ reason: 'the named edit must invalidate the cached numeric preview' ,
840+ );
812841 expect (
813842 tester
814843 .widget <ButtonStyleButton >(
@@ -824,6 +853,13 @@ pixels.write()
824853 () => find.textContaining ('Pin("LED", Pin.OUT' ).evaluate ().isNotEmpty,
825854 reason:
826855 'the real scratch Blockly workspace did not quote the named LED pin' ,
856+ diagnostics: () =>
857+ 'gpio=${tester .widget <TextField >(ledGpioField ).controller ?.text }; '
858+ 'numericPreviewMatches='
859+ '${find .textContaining ('Pin(17, Pin.OUT' ).evaluate ().length }; '
860+ 'namedPreviewMatches='
861+ '${find .textContaining ('Pin("LED", Pin.OUT' ).evaluate ().length }; '
862+ 'dialogs=${find .byType (AlertDialog ).evaluate ().length }' ,
827863 );
828864 await tester.tap (
829865 find.descendant (
0 commit comments