@@ -138,7 +138,8 @@ class TextFieldStateRenderTest {
138138 PythonComposition (REMEMBERED )
139139 }
140140 val before: IntArray
141- val after: IntArray
141+ var after: IntArray
142+ var frames = 0
142143 try {
143144 before = pixelsOf(scene.render())
144145 Python3 .exec(
@@ -148,8 +149,18 @@ class TextFieldStateRenderTest {
148149 _tfs_seen[0].setTextAndPlaceCursorAtEnd('a much longer line of text')
149150 """ .trimIndent(),
150151 )
151- Snapshot .sendApplyNotifications()
152- after = pixelsOf(scene.render())
152+ // `TextField(state=...)` does not finish reacting to a state write inside one frame: the
153+ // text-changed handling of BasicTextField runs on the scene's coroutine dispatcher, which is
154+ // flushed by `render()`, so the pixels can trail the write by a frame. The test is the frame
155+ // clock (there is none), so it advances it explicitly -- but only up to MAX_FRAMES, and it
156+ // stops at the first frame that differs. A write that truly never reaches the draw leaves every
157+ // one of these frames identical to `before`, and the assertion below still fails.
158+ after = before
159+ while (frames < MAX_FRAMES && differing(before, after) <= 10 ) {
160+ Snapshot .sendApplyNotifications()
161+ after = pixelsOf(scene.render())
162+ frames++
163+ }
153164 Python3 .exec(
154165 """
155166 assert all(_s.text == 'a much longer line of text' for _s in _tfs_seen), \
@@ -160,7 +171,7 @@ class TextFieldStateRenderTest {
160171 scene.close()
161172 }
162173 val moved = differing(before, after)
163- println (" compose rememberTextFieldState: ink ${inkOf(before)} -> ${inkOf(after)} px, $moved pixels differ" )
174+ println (" compose rememberTextFieldState: ink ${inkOf(before)} -> ${inkOf(after)} px, $moved pixels differ after $frames frame(s) " )
164175 assertTrue(inkOf(before) > 0 , " TextField(state=rememberTextFieldState(...)) never composed" )
165176 assertTrue(moved > 10 , " only $moved pixels differ, so the write from Python never reached the next frame" )
166177 }
@@ -198,6 +209,9 @@ class TextFieldStateRenderTest {
198209 const val FIELD_WIDTH = 280
199210 const val FIELD_HEIGHT = 64
200211
212+ /* * Upper bound on frames rendered after the write in the remembered-state test. */
213+ const val MAX_FRAMES = 4
214+
201215 val REMEMBERED = """
202216 from androidx.compose.foundation.text.input import rememberTextFieldState
203217 from androidx.compose.material3 import TextField
0 commit comments