diff --git a/app/src/androidTest/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/CheckoutFlowActivityTest__RecurringDonations.kt b/app/src/androidTest/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/CheckoutFlowActivityTest__RecurringDonations.kt index 862bf29994..6ceb6dd17d 100644 --- a/app/src/androidTest/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/CheckoutFlowActivityTest__RecurringDonations.kt +++ b/app/src/androidTest/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/CheckoutFlowActivityTest__RecurringDonations.kt @@ -12,7 +12,6 @@ import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry import okhttp3.mockwebserver.MockResponse -import org.junit.Ignore import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @@ -26,6 +25,7 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.testing.Delete import org.thoughtcrime.securesms.testing.Get import org.thoughtcrime.securesms.testing.SignalActivityRule +import org.thoughtcrime.securesms.testing.actions.RecyclerViewScrollToBottomAction import org.thoughtcrime.securesms.testing.success import org.thoughtcrime.securesms.util.JsonUtils import org.whispersystems.signalservice.api.subscriptions.ActiveSubscription @@ -36,7 +36,6 @@ import java.util.Currency import kotlin.time.Duration.Companion.days import kotlin.time.Duration.Companion.milliseconds -@Ignore("Test fails on small screens, requires scrolling.") @Suppress("ClassName") @RunWith(AndroidJUnit4::class) class CheckoutFlowActivityTest__RecurringDonations { @@ -54,6 +53,7 @@ class CheckoutFlowActivityTest__RecurringDonations { @Test fun givenNoCurrentDonation_whenILoadScreen_thenIExpectContinueButton() { ActivityScenario.launch(intent) + onView(withId(R.id.recycler)).perform(RecyclerViewScrollToBottomAction) onView(withText("Continue")).check(matches(isDisplayed())) } @@ -63,6 +63,8 @@ class CheckoutFlowActivityTest__RecurringDonations { initialiseActiveSubscription() ActivityScenario.launch(intent) + + onView(withId(R.id.recycler)).perform(RecyclerViewScrollToBottomAction) onView(withText(R.string.SubscribeFragment__update_subscription)).check(matches(isDisplayed())) onView(withText(R.string.SubscribeFragment__cancel_subscription)).check(matches(isDisplayed())) } @@ -73,6 +75,7 @@ class CheckoutFlowActivityTest__RecurringDonations { initialiseActiveSubscription() ActivityScenario.launch(intent) + onView(withId(R.id.recycler)).perform(RecyclerViewScrollToBottomAction) onView(withText(R.string.SubscribeFragment__cancel_subscription)).check(matches(isDisplayed())) onView(withText(R.string.SubscribeFragment__cancel_subscription)).perform(ViewActions.click()) onView(withText(R.string.SubscribeFragment__confirm_cancellation)).check(matches(isDisplayed())) @@ -86,6 +89,7 @@ class CheckoutFlowActivityTest__RecurringDonations { initialisePendingSubscription() ActivityScenario.launch(intent) + onView(withId(R.id.recycler)).perform(RecyclerViewScrollToBottomAction) onView(withText(R.string.SubscribeFragment__update_subscription)).check(matches(isDisplayed())) onView(withText(R.string.SubscribeFragment__update_subscription)).check(matches(isNotEnabled())) } diff --git a/app/src/androidTest/java/org/thoughtcrime/securesms/testing/actions/RecyclerViewScrollToBottomAction.kt b/app/src/androidTest/java/org/thoughtcrime/securesms/testing/actions/RecyclerViewScrollToBottomAction.kt new file mode 100644 index 0000000000..eecb22a4f5 --- /dev/null +++ b/app/src/androidTest/java/org/thoughtcrime/securesms/testing/actions/RecyclerViewScrollToBottomAction.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2025 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.thoughtcrime.securesms.testing.actions + +import android.view.View +import androidx.recyclerview.widget.RecyclerView +import androidx.test.espresso.UiController +import androidx.test.espresso.ViewAction +import androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import org.hamcrest.CoreMatchers.allOf +import org.hamcrest.Matcher + +/** + * Scrolls the RecyclerView to the bottom position. + * + * Borrowed from [https://stackoverflow.com/a/55990445](https://stackoverflow.com/a/55990445) + */ +object RecyclerViewScrollToBottomAction : ViewAction { + override fun getDescription(): String = "scroll RecyclerView to bottom" + + override fun getConstraints(): Matcher = allOf(isAssignableFrom(RecyclerView::class.java), isDisplayed()) + + override fun perform(uiController: UiController?, view: View?) { + val recyclerView = view as RecyclerView + val itemCount = recyclerView.adapter?.itemCount + val position = itemCount?.minus(1) ?: 0 + recyclerView.scrollToPosition(position) + uiController?.loopMainThreadUntilIdle() + } +} \ No newline at end of file