Add donation checkout spec test suite.

Co-authored-by: Cody Henthorne <cody@signal.org>
This commit is contained in:
Alex Hart
2026-07-15 16:43:47 -04:00
committed by Greyson Parrelli
co-authored by Cody Henthorne
parent fe6a74eb56
commit 5e3a34e1bc
28 changed files with 1618 additions and 119 deletions
@@ -0,0 +1,29 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.subscription.donate.transfer
/**
* Test tags for the bank-transfer (SEPA) and iDEAL Compose entry forms, so instrumentation tests can
* drive them reliably. Follows the central-object convention used by the registration module's
* `TestTags`.
*/
object DonationTransferTestTags {
// SEPA bank transfer mandate
const val SEPA_MANDATE_CONTINUE_BUTTON = "sepa_mandate_continue_button"
// SEPA bank transfer details
const val SEPA_DETAILS_LIST = "sepa_details_list"
const val SEPA_IBAN_FIELD = "sepa_iban_field"
const val SEPA_NAME_FIELD = "sepa_name_field"
const val SEPA_EMAIL_FIELD = "sepa_email_field"
const val SEPA_DONATE_BUTTON = "sepa_donate_button"
// iDEAL transfer details
const val IDEAL_DETAILS_LIST = "ideal_details_list"
const val IDEAL_NAME_FIELD = "ideal_name_field"
const val IDEAL_EMAIL_FIELD = "ideal_email_field"
const val IDEAL_DONATE_BUTTON = "ideal_donate_button"
}
@@ -32,6 +32,7 @@ import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardCapitalization
@@ -63,6 +64,7 @@ import org.thoughtcrime.securesms.components.settings.app.subscription.donate.In
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.stripe.StripePaymentInProgressFragment
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.stripe.StripePaymentInProgressViewModel
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.transfer.BankTransferRequestKeys
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.transfer.DonationTransferTestTags
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.transfer.details.BankTransferDetailsViewModel.Field
import org.thoughtcrime.securesms.database.InAppPaymentTable
import org.thoughtcrime.securesms.payments.FiatMoneyUtil
@@ -237,6 +239,7 @@ fun BankTransferDetailsContent(
modifier = Modifier
.weight(1f)
.padding(horizontal = 24.dp)
.testTag(DonationTransferTestTags.SEPA_DETAILS_LIST)
) {
item {
val learnMore = stringResource(id = R.string.BankTransferDetailsFragment__learn_more)
@@ -292,6 +295,7 @@ fun BankTransferDetailsContent(
.defaultMinSize(minHeight = 78.dp)
.onFocusChanged { onFocusChanged(Field.IBAN, it.hasFocus) }
.focusRequester(focusRequester)
.testTag(DonationTransferTestTags.SEPA_IBAN_FIELD)
)
}
@@ -320,6 +324,7 @@ fun BankTransferDetailsContent(
.padding(top = 16.dp)
.defaultMinSize(minHeight = 78.dp)
.onFocusChanged { onFocusChanged(Field.NAME, it.hasFocus) }
.testTag(DonationTransferTestTags.SEPA_NAME_FIELD)
)
}
@@ -348,6 +353,7 @@ fun BankTransferDetailsContent(
.padding(top = 16.dp)
.defaultMinSize(minHeight = 78.dp)
.onFocusChanged { onFocusChanged(Field.EMAIL, it.hasFocus) }
.testTag(DonationTransferTestTags.SEPA_EMAIL_FIELD)
)
}
@@ -373,6 +379,7 @@ fun BankTransferDetailsContent(
modifier = Modifier
.defaultMinSize(minWidth = 220.dp)
.padding(vertical = 16.dp)
.testTag(DonationTransferTestTags.SEPA_DONATE_BUTTON)
) {
Text(text = donateLabel)
}
@@ -26,6 +26,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusDirection
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardCapitalization
@@ -60,6 +61,7 @@ import org.thoughtcrime.securesms.components.settings.app.subscription.donate.ga
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.stripe.StripePaymentInProgressFragment
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.stripe.StripePaymentInProgressViewModel
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.transfer.BankTransferRequestKeys
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.transfer.DonationTransferTestTags
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.transfer.ideal.IdealTransferDetailsViewModel.Field
import org.thoughtcrime.securesms.database.InAppPaymentTable
import org.thoughtcrime.securesms.payments.FiatMoneyUtil
@@ -241,6 +243,7 @@ private fun IdealTransferDetailsContent(
modifier = Modifier
.weight(1f)
.padding(horizontal = 24.dp)
.testTag(DonationTransferTestTags.IDEAL_DETAILS_LIST)
) {
item {
val learnMore = stringResource(id = R.string.IdealTransferDetailsFragment__learn_more)
@@ -283,6 +286,7 @@ private fun IdealTransferDetailsContent(
.padding(top = 16.dp)
.defaultMinSize(minHeight = 78.dp)
.onFocusChanged { onFocusChanged(Field.NAME, it.hasFocus) }
.testTag(DonationTransferTestTags.IDEAL_NAME_FIELD)
)
}
@@ -316,6 +320,7 @@ private fun IdealTransferDetailsContent(
.padding(top = 16.dp)
.defaultMinSize(minHeight = 78.dp)
.onFocusChanged { onFocusChanged(Field.EMAIL, it.hasFocus) }
.testTag(DonationTransferTestTags.IDEAL_EMAIL_FIELD)
)
}
}
@@ -327,6 +332,7 @@ private fun IdealTransferDetailsContent(
modifier = Modifier
.defaultMinSize(minWidth = 220.dp)
.padding(bottom = 16.dp)
.testTag(DonationTransferTestTags.IDEAL_DONATE_BUTTON)
) {
Text(text = donateLabel)
}
@@ -40,6 +40,7 @@ import androidx.compose.ui.Alignment.Companion.CenterHorizontally
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
@@ -58,6 +59,7 @@ import org.signal.core.ui.compose.SignalIcons
import org.signal.core.ui.compose.Texts
import org.signal.core.ui.compose.theme.SignalTheme
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.transfer.DonationTransferTestTags
import org.thoughtcrime.securesms.compose.StatusBarColorAnimator
import org.thoughtcrime.securesms.database.model.databaseprotos.InAppPaymentData
import org.thoughtcrime.securesms.util.SpanUtil
@@ -267,6 +269,7 @@ fun BankTransferScreen(
.wrapContentWidth()
.padding(top = 16.dp, bottom = 16.dp)
.defaultMinSize(minWidth = 220.dp)
.testTag(DonationTransferTestTags.SEPA_MANDATE_CONTINUE_BUTTON)
) {
Text(text = if (listState.canScrollForward) stringResource(id = R.string.BankTransferMandateFragment__read_more) else stringResource(id = R.string.BankTransferMandateFragment__agree))
}
@@ -498,6 +498,7 @@ object AppDependencies {
fun provideProfileService(profileOperations: ClientZkProfileOperations, authWebSocket: SignalWebSocket.AuthenticatedWebSocket, unauthWebSocket: SignalWebSocket.UnauthenticatedWebSocket): ProfileService
fun provideDeadlockDetector(): DeadlockDetector
fun provideClientZkReceiptOperations(signalServiceConfiguration: SignalServiceConfiguration): ClientZkReceiptOperations
fun provideOkHttpClient(): OkHttpClient
fun provideScheduledMessageManager(): ScheduledMessageManager
fun providePinnedMessageManager(): PinnedMessageManager
fun provideLibsignalNetwork(config: SignalServiceConfiguration): Network
@@ -9,6 +9,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.media3.exoplayer.ExoPlayer;
import okhttp3.OkHttpClient;
import org.jetbrains.annotations.NotNull;
import org.signal.billing.BillingFactory;
import org.signal.core.models.ServiceId.ACI;
@@ -542,6 +543,14 @@ public class ApplicationDependencyProvider implements AppDependencies.Provider {
return provideClientZkOperations(signalServiceConfiguration).getReceiptOperations();
}
@Override
public @NonNull OkHttpClient provideOkHttpClient() {
return new OkHttpClient.Builder()
.addInterceptor(new StandardUserAgentInterceptor())
.dns(SignalServiceNetworkAccess.DNS)
.build();
}
@Override
public @NonNull BillingApi provideBillingApi() {
return BillingFactory.create(GooglePlayBillingDependencies.INSTANCE, Environment.Backups.supportsGooglePlayBilling());
@@ -37,7 +37,6 @@ import org.thoughtcrime.securesms.groups.GroupsV2Authorization
import org.thoughtcrime.securesms.groups.GroupsV2AuthorizationMemoryValueCache
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.messages.IncomingMessageObserver
import org.thoughtcrime.securesms.net.StandardUserAgentInterceptor
import org.thoughtcrime.securesms.payments.Payments
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess
import org.thoughtcrime.securesms.push.SignalServiceTrustStore
@@ -244,10 +243,7 @@ class NetworkDependenciesModule(
}
val okHttpClient: OkHttpClient by lazy {
OkHttpClient.Builder()
.addInterceptor(StandardUserAgentInterceptor())
.dns(SignalServiceNetworkAccess.DNS)
.build()
provider.provideOkHttpClient()
}
val signalOkHttpClient: OkHttpClient by lazy {