From 7714f7515f64a14ea3dd44913aabde3858157e28 Mon Sep 17 00:00:00 2001 From: Alex Hart Date: Fri, 28 Aug 2026 13:30:33 -0300 Subject: [PATCH] Try to repair flakey instrumentation test. --- .../subscription/donate/CheckoutFlowDriver.kt | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/app/src/androidTest/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/CheckoutFlowDriver.kt b/app/src/androidTest/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/CheckoutFlowDriver.kt index 54b6aa9b11..5db26cee91 100644 --- a/app/src/androidTest/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/CheckoutFlowDriver.kt +++ b/app/src/androidTest/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/CheckoutFlowDriver.kt @@ -210,13 +210,27 @@ class CheckoutFlowDriver( composeRule.onNodeWithTag(fieldTag).performTextInput(text) } - /** Retries clicking a Compose node until the click lands (e.g. once a submit button becomes enabled). */ - private fun clickWhenReady(tag: String) { + /** + * Clicks the Compose node tagged [tag] once per flush until [settled] holds, which defaults to the node + * no longer being present (the transfer forms navigate away on submit). + * + * A dispatched click is not proof the click landed, so "did it throw" is not a usable stop condition: + * [performClick] succeeds on a disabled button, and these forms pin their submit button above an animating + * IME, so a click issued while the insets are still settling is delivered to the strip the button has + * already vacated and silently does nothing. Retrying until the flow has actually advanced makes the step + * independent of where the button was a frame ago. + */ + private fun clickWhenReady( + tag: String, + settled: () -> Boolean = { composeRule.onAllNodesWithTag(tag).fetchSemanticsNodes().isEmpty() } + ) { scheduler.flushUntil { - runCatching { - composeRule.onNodeWithTag(tag).performClick() + if (settled()) { true - }.getOrDefault(false) + } else { + runCatching { composeRule.onNodeWithTag(tag).performClick() } + false + } } scheduler.triggerActions() }