diff --git a/paymentsheet/api/paymentsheet.api b/paymentsheet/api/paymentsheet.api index 2a9e4014703..76ae6bb8695 100644 --- a/paymentsheet/api/paymentsheet.api +++ b/paymentsheet/api/paymentsheet.api @@ -1822,6 +1822,14 @@ public final class com/stripe/android/paymentsheet/model/PaymentIntentClientSecr public synthetic fun newArray (I)[Ljava/lang/Object; } +public final class com/stripe/android/paymentsheet/model/PaymentMethodIncentive$Creator : android/os/Parcelable$Creator { + public fun ()V + public final fun createFromParcel (Landroid/os/Parcel;)Lcom/stripe/android/paymentsheet/model/PaymentMethodIncentive; + public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object; + public final fun newArray (I)[Lcom/stripe/android/paymentsheet/model/PaymentMethodIncentive; + public synthetic fun newArray (I)[Ljava/lang/Object; +} + public final class com/stripe/android/paymentsheet/model/PaymentOption { public static final field $stable I public fun (ILjava/lang/String;)V diff --git a/paymentsheet/detekt-baseline.xml b/paymentsheet/detekt-baseline.xml index d32a4857888..012862d07e5 100644 --- a/paymentsheet/detekt-baseline.xml +++ b/paymentsheet/detekt-baseline.xml @@ -32,7 +32,8 @@ LongMethod:EditPaymentMethod.kt$@Composable internal fun EditPaymentMethodUi( viewState: EditPaymentMethodViewState, viewActionHandler: (action: EditPaymentMethodViewAction) -> Unit, modifier: Modifier = Modifier ) LongMethod:FormViewModelTest.kt$FormViewModelTest$@Test fun `Verify params are set when element address fields are complete`() LongMethod:FormViewModelTest.kt$FormViewModelTest$@Test fun `Verify params are set when required address fields are complete`() - LongMethod:PaymentMethodVerticalLayoutInteractor.kt$DefaultPaymentMethodVerticalLayoutInteractor.Companion$fun create( viewModel: BaseSheetViewModel, paymentMethodMetadata: PaymentMethodMetadata, customerStateHolder: CustomerStateHolder, ): PaymentMethodVerticalLayoutInteractor + LongMethod:PaymentMethodMetadataTest.kt$PaymentMethodMetadataTest$@OptIn(ExperimentalCardBrandFilteringApi::class) @Test fun `should create metadata properly with elements session response, payment sheet config, and data specs`() + LongMethod:PaymentMethodVerticalLayoutInteractor.kt$DefaultPaymentMethodVerticalLayoutInteractor.Companion$fun create( viewModel: BaseSheetViewModel, paymentMethodMetadata: PaymentMethodMetadata, customerStateHolder: CustomerStateHolder, bankFormInteractor: BankFormInteractor, ): PaymentMethodVerticalLayoutInteractor LongMethod:PaymentSheetConfigurationKtx.kt$internal fun PaymentSheet.Appearance.parseAppearance() LongMethod:PaymentSheetScreen.kt$@Composable private fun PaymentSheetContent( viewModel: BaseSheetViewModel, headerText: ResolvableString?, walletsState: WalletsState?, walletsProcessingState: WalletsProcessingState?, error: ResolvableString?, currentScreen: PaymentSheetScreen, mandateText: MandateText?, modifier: Modifier ) LongMethod:PaymentSheetViewModelTest.kt$PaymentSheetViewModelTest$@Test fun `Can complete payment after switching to another LPM from card selection with inline Link signup state`() diff --git a/paymentsheet/src/main/java/com/stripe/android/customersheet/ui/CustomerSheetScreen.kt b/paymentsheet/src/main/java/com/stripe/android/customersheet/ui/CustomerSheetScreen.kt index 4bf82fa06ed..41420cf700d 100644 --- a/paymentsheet/src/main/java/com/stripe/android/customersheet/ui/CustomerSheetScreen.kt +++ b/paymentsheet/src/main/java/com/stripe/android/customersheet/ui/CustomerSheetScreen.kt @@ -238,6 +238,7 @@ internal fun AddPaymentMethod( }, formArguments = viewState.formArguments, usBankAccountFormArguments = viewState.usBankAccountFormArguments, + incentive = null, onFormFieldValuesChanged = { // This only gets emitted if form field values are complete viewActionHandler(CustomerSheetViewAction.OnFormFieldValuesCompleted(it)) diff --git a/paymentsheet/src/main/java/com/stripe/android/lpmfoundations/luxe/SupportedPaymentMethod.kt b/paymentsheet/src/main/java/com/stripe/android/lpmfoundations/luxe/SupportedPaymentMethod.kt index bdad607428b..948579f2701 100644 --- a/paymentsheet/src/main/java/com/stripe/android/lpmfoundations/luxe/SupportedPaymentMethod.kt +++ b/paymentsheet/src/main/java/com/stripe/android/lpmfoundations/luxe/SupportedPaymentMethod.kt @@ -9,6 +9,7 @@ import com.stripe.android.lpmfoundations.paymentmethod.PaymentMethodDefinition import com.stripe.android.model.PaymentMethod import com.stripe.android.model.PaymentMethodCode import com.stripe.android.paymentsheet.R +import com.stripe.android.paymentsheet.model.PaymentMethodIncentive import com.stripe.android.paymentsheet.verticalmode.DisplayablePaymentMethod import com.stripe.android.ui.core.elements.SharedDataSpec @@ -85,6 +86,7 @@ internal data class SupportedPaymentMethod( fun asDisplayablePaymentMethod( customerSavedPaymentMethods: List, + incentive: PaymentMethodIncentive?, onClick: () -> Unit, ): DisplayablePaymentMethod { fun isTypeAndHasCustomerSavedPaymentMethodsOfType(type: PaymentMethod.Type): Boolean { @@ -105,6 +107,7 @@ internal data class SupportedPaymentMethod( darkThemeIconUrl = darkThemeIconUrl, iconRequiresTinting = iconRequiresTinting, subtitle = subtitle, + promoBadge = incentive?.takeIf { it.matches(code) }?.displayText, onClick = onClick, ) } diff --git a/paymentsheet/src/main/java/com/stripe/android/lpmfoundations/paymentmethod/PaymentMethodMetadata.kt b/paymentsheet/src/main/java/com/stripe/android/lpmfoundations/paymentmethod/PaymentMethodMetadata.kt index 8762bca438d..aaf434f7eac 100644 --- a/paymentsheet/src/main/java/com/stripe/android/lpmfoundations/paymentmethod/PaymentMethodMetadata.kt +++ b/paymentsheet/src/main/java/com/stripe/android/lpmfoundations/paymentmethod/PaymentMethodMetadata.kt @@ -19,7 +19,9 @@ import com.stripe.android.payments.financialconnections.DefaultIsFinancialConnec import com.stripe.android.payments.financialconnections.IsFinancialConnectionsAvailable import com.stripe.android.paymentsheet.PaymentSheet import com.stripe.android.paymentsheet.addresselement.AddressDetails +import com.stripe.android.paymentsheet.model.PaymentMethodIncentive import com.stripe.android.paymentsheet.model.PaymentSelection +import com.stripe.android.paymentsheet.model.toPaymentMethodIncentive import com.stripe.android.ui.core.Amount import com.stripe.android.ui.core.cbc.CardBrandChoiceEligibility import com.stripe.android.ui.core.elements.ExternalPaymentMethodSpec @@ -49,6 +51,7 @@ internal data class PaymentMethodMetadata( val linkInlineConfiguration: LinkInlineConfiguration?, val paymentMethodSaveConsentBehavior: PaymentMethodSaveConsentBehavior, val linkMode: LinkMode?, + val paymentMethodIncentive: PaymentMethodIncentive?, val financialConnectionsAvailable: Boolean = DefaultIsFinancialConnectionsAvailable(), val cardBrandFilter: CardBrandFilter, ) : Parcelable { @@ -231,6 +234,7 @@ internal data class PaymentMethodMetadata( isGooglePayReady: Boolean, linkInlineConfiguration: LinkInlineConfiguration?, ): PaymentMethodMetadata { + val linkSettings = elementsSession.linkSettings return PaymentMethodMetadata( stripeIntent = elementsSession.stripeIntent, billingDetailsCollectionConfiguration = configuration.billingDetailsCollectionConfiguration, @@ -250,7 +254,8 @@ internal data class PaymentMethodMetadata( externalPaymentMethodSpecs = externalPaymentMethodSpecs, paymentMethodSaveConsentBehavior = elementsSession.toPaymentSheetSaveConsentBehavior(), linkInlineConfiguration = linkInlineConfiguration, - linkMode = elementsSession.linkSettings?.linkMode, + linkMode = linkSettings?.linkMode, + paymentMethodIncentive = linkSettings?.linkConsumerIncentive?.toPaymentMethodIncentive(), isGooglePayReady = isGooglePayReady, cardBrandFilter = PaymentSheetCardBrandFilter(configuration.cardBrandAcceptance) ) @@ -284,6 +289,7 @@ internal data class PaymentMethodMetadata( financialConnectionsAvailable = isFinancialConnectionsAvailable(), paymentMethodSaveConsentBehavior = paymentMethodSaveConsentBehavior, linkMode = elementsSession.linkSettings?.linkMode, + paymentMethodIncentive = null, externalPaymentMethodSpecs = emptyList(), cardBrandFilter = PaymentSheetCardBrandFilter(configuration.cardBrandAcceptance) ) diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/model/PaymentMethodIncentive.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/model/PaymentMethodIncentive.kt new file mode 100644 index 00000000000..0be52fd56c1 --- /dev/null +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/model/PaymentMethodIncentive.kt @@ -0,0 +1,27 @@ +package com.stripe.android.paymentsheet.model + +import android.os.Parcelable +import com.stripe.android.model.LinkConsumerIncentive +import com.stripe.android.model.PaymentMethod +import com.stripe.android.model.PaymentMethodCode +import kotlinx.parcelize.Parcelize + +@Parcelize +internal data class PaymentMethodIncentive( + private val identifier: String, + val displayText: String, +) : Parcelable { + + fun matches(code: PaymentMethodCode): Boolean { + return identifier == "link_instant_debits" && code == PaymentMethod.Type.Link.code + } +} + +internal fun LinkConsumerIncentive.toPaymentMethodIncentive(): PaymentMethodIncentive? { + return incentiveDisplayText?.let { displayText -> + PaymentMethodIncentive( + identifier = incentiveParams.paymentMethod, + displayText = displayText, + ) + } +} diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/paymentdatacollection/ach/USBankAccountFormArguments.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/paymentdatacollection/ach/USBankAccountFormArguments.kt index dfa9a7fb52f..89a14c8ab26 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/paymentdatacollection/ach/USBankAccountFormArguments.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/paymentdatacollection/ach/USBankAccountFormArguments.kt @@ -12,6 +12,7 @@ import com.stripe.android.paymentsheet.addresselement.AddressDetails import com.stripe.android.paymentsheet.model.PaymentSelection import com.stripe.android.paymentsheet.state.PaymentElementLoader import com.stripe.android.paymentsheet.ui.PrimaryButton +import com.stripe.android.paymentsheet.verticalmode.BankFormInteractor import com.stripe.android.paymentsheet.viewmodels.BaseSheetViewModel import kotlinx.coroutines.flow.update @@ -61,6 +62,7 @@ internal class USBankAccountFormArguments( paymentMethodMetadata: PaymentMethodMetadata, hostedSurface: String, selectedPaymentMethodCode: String, + bankFormInteractor: BankFormInteractor, ): USBankAccountFormArguments { val isSaveForFutureUseValueChangeable = isSaveForFutureUseValueChangeable( code = selectedPaymentMethodCode, @@ -91,7 +93,7 @@ internal class USBankAccountFormArguments( shippingDetails = viewModel.config.shippingDetails, draftPaymentSelection = viewModel.newPaymentSelection?.paymentSelection, onMandateTextChanged = viewModel.mandateHandler::updateMandateText, - onLinkedBankAccountChanged = viewModel::handleLinkedBankAccountChanged, + onLinkedBankAccountChanged = bankFormInteractor::handleLinkedBankAccountChanged, onUpdatePrimaryButtonUIState = { viewModel.customPrimaryButtonUiState.update(it) }, onUpdatePrimaryButtonState = viewModel::updatePrimaryButtonState, onError = viewModel::onError diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/AddPaymentMethod.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/AddPaymentMethod.kt index 66e1aabd81b..2963ea24afe 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/AddPaymentMethod.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/AddPaymentMethod.kt @@ -31,6 +31,7 @@ internal fun AddPaymentMethod( enabled = !state.processing, supportedPaymentMethods = state.supportedPaymentMethods, selectedItemCode = state.selectedPaymentMethodCode, + incentive = state.incentive, formElements = state.formElements, onItemSelectedListener = { selectedLpm -> interactor.handleViewAction( diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/AddPaymentMethodInteractor.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/AddPaymentMethodInteractor.kt index 73326c222c3..3cababdad92 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/AddPaymentMethodInteractor.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/AddPaymentMethodInteractor.kt @@ -7,9 +7,11 @@ import com.stripe.android.payments.bankaccount.CollectBankAccountLauncher import com.stripe.android.paymentsheet.FormHelper import com.stripe.android.paymentsheet.LinkInlineHandler import com.stripe.android.paymentsheet.forms.FormFieldValues +import com.stripe.android.paymentsheet.model.PaymentMethodIncentive import com.stripe.android.paymentsheet.model.PaymentSelection import com.stripe.android.paymentsheet.paymentdatacollection.FormArguments import com.stripe.android.paymentsheet.paymentdatacollection.ach.USBankAccountFormArguments +import com.stripe.android.paymentsheet.verticalmode.BankFormInteractor import com.stripe.android.paymentsheet.viewmodels.BaseSheetViewModel import com.stripe.android.uicore.elements.FormElement import kotlinx.coroutines.CoroutineScope @@ -36,6 +38,7 @@ internal interface AddPaymentMethodInteractor { val formElements: List, val paymentSelection: PaymentSelection?, val processing: Boolean, + val incentive: PaymentMethodIncentive?, val usBankAccountFormArguments: USBankAccountFormArguments, ) @@ -54,6 +57,7 @@ internal class DefaultAddPaymentMethodInteractor( private val initiallySelectedPaymentMethodType: PaymentMethodCode, private val selection: StateFlow, private val processing: StateFlow, + private val incentive: StateFlow, private val supportedPaymentMethods: List, private val createFormArguments: (PaymentMethodCode) -> FormArguments, private val formElementsForCode: (PaymentMethodCode) -> List, @@ -78,10 +82,13 @@ internal class DefaultAddPaymentMethodInteractor( linkInlineHandler = linkInlineHandler, paymentMethodMetadata = paymentMethodMetadata ) + val bankFormInteractor = BankFormInteractor.create(viewModel) + return DefaultAddPaymentMethodInteractor( initiallySelectedPaymentMethodType = viewModel.initiallySelectedPaymentMethodType, selection = viewModel.selection, processing = viewModel.processing, + incentive = bankFormInteractor.paymentMethodIncentiveInteractor.displayedIncentive, supportedPaymentMethods = paymentMethodMetadata.sortedSupportedPaymentMethods(), createFormArguments = formHelper::createFormArguments, formElementsForCode = formHelper::formElementsForCode, @@ -95,6 +102,7 @@ internal class DefaultAddPaymentMethodInteractor( paymentMethodMetadata = paymentMethodMetadata, hostedSurface = CollectBankAccountLauncher.HOSTED_SURFACE_PAYMENT_ELEMENT, selectedPaymentMethodCode = it, + bankFormInteractor = bankFormInteractor, ) }, coroutineScope = coroutineScope, @@ -122,6 +130,7 @@ internal class DefaultAddPaymentMethodInteractor( formElements = formElementsForCode(selectedPaymentMethodCode), paymentSelection = selection.value, processing = processing.value, + incentive = incentive.value, usBankAccountFormArguments = createUSBankAccountFormArguments(selectedPaymentMethodCode), ) } diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/NewPaymentMethodTabLayoutUI.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/NewPaymentMethodTabLayoutUI.kt index 9794e1a1b9d..15f4b6f81e3 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/NewPaymentMethodTabLayoutUI.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/NewPaymentMethodTabLayoutUI.kt @@ -21,6 +21,7 @@ import androidx.compose.ui.platform.testTag import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.stripe.android.lpmfoundations.luxe.SupportedPaymentMethod +import com.stripe.android.paymentsheet.model.PaymentMethodIncentive import com.stripe.android.uicore.image.StripeImageLoader import com.stripe.android.uicore.strings.resolve @@ -37,6 +38,7 @@ internal fun NewPaymentMethodTabLayoutUI( paymentMethods: List, selectedIndex: Int, isEnabled: Boolean, + incentive: PaymentMethodIncentive?, onItemSelectedListener: (SupportedPaymentMethod) -> Unit, imageLoader: StripeImageLoader, modifier: Modifier = Modifier, @@ -88,7 +90,7 @@ internal fun NewPaymentMethodTabLayoutUI( isSelected = index == selectedIndex, isEnabled = isEnabled, iconRequiresTinting = item.iconRequiresTinting, - promoBadge = null, + promoBadge = incentive?.takeIf { it.matches(item.code) }?.displayText, onItemSelectedListener = { onItemSelectedListener(paymentMethods[index]) } diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/PaymentElement.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/PaymentElement.kt index 777c00060bf..f5908e0e4ae 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/PaymentElement.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/PaymentElement.kt @@ -24,6 +24,7 @@ import com.stripe.android.model.PaymentMethod.Type.USBankAccount import com.stripe.android.model.PaymentMethodCode import com.stripe.android.paymentsheet.R import com.stripe.android.paymentsheet.forms.FormFieldValues +import com.stripe.android.paymentsheet.model.PaymentMethodIncentive import com.stripe.android.paymentsheet.paymentdatacollection.FormArguments import com.stripe.android.paymentsheet.paymentdatacollection.ach.USBankAccountForm import com.stripe.android.paymentsheet.paymentdatacollection.ach.USBankAccountFormArguments @@ -36,6 +37,7 @@ internal fun PaymentElement( enabled: Boolean, supportedPaymentMethods: List, selectedItemCode: PaymentMethodCode, + incentive: PaymentMethodIncentive?, formElements: List, onItemSelectedListener: (SupportedPaymentMethod) -> Unit, formArguments: FormArguments, @@ -66,6 +68,7 @@ internal fun PaymentElement( selectedIndex = selectedIndex, isEnabled = enabled, paymentMethods = supportedPaymentMethods, + incentive = incentive, onItemSelectedListener = onItemSelectedListener, imageLoader = imageLoader, modifier = Modifier.padding(bottom = 12.dp), diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/verticalmode/BankFormInteractor.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/verticalmode/BankFormInteractor.kt new file mode 100644 index 00000000000..19976fc7c2a --- /dev/null +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/verticalmode/BankFormInteractor.kt @@ -0,0 +1,26 @@ +package com.stripe.android.paymentsheet.verticalmode + +import com.stripe.android.paymentsheet.model.PaymentSelection +import com.stripe.android.paymentsheet.viewmodels.BaseSheetViewModel + +internal class BankFormInteractor( + private val updateSelection: (PaymentSelection.New.USBankAccount?) -> Unit, + val paymentMethodIncentiveInteractor: PaymentMethodIncentiveInteractor, +) { + + fun handleLinkedBankAccountChanged(selection: PaymentSelection.New.USBankAccount?) { + updateSelection(selection) + + // TODO(tillh-stripe): Update incentive badge here + } + + companion object { + + fun create(viewModel: BaseSheetViewModel): BankFormInteractor { + return BankFormInteractor( + updateSelection = viewModel::updateSelection, + paymentMethodIncentiveInteractor = PaymentMethodIncentiveInteractor.create(viewModel), + ) + } + } +} diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/verticalmode/PaymentMethodIncentiveInteractor.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/verticalmode/PaymentMethodIncentiveInteractor.kt new file mode 100644 index 00000000000..5a0baa88220 --- /dev/null +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/verticalmode/PaymentMethodIncentiveInteractor.kt @@ -0,0 +1,24 @@ +package com.stripe.android.paymentsheet.verticalmode + +import com.stripe.android.paymentsheet.model.PaymentMethodIncentive +import com.stripe.android.paymentsheet.viewmodels.BaseSheetViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow + +internal class PaymentMethodIncentiveInteractor( + private val incentive: PaymentMethodIncentive?, +) { + + private val _displayedIncentive = MutableStateFlow(incentive) + val displayedIncentive: StateFlow = _displayedIncentive.asStateFlow() + + companion object { + + fun create(viewModel: BaseSheetViewModel): PaymentMethodIncentiveInteractor { + return PaymentMethodIncentiveInteractor( + incentive = viewModel.paymentMethodMetadata.value?.paymentMethodIncentive, + ) + } + } +} diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/verticalmode/PaymentMethodVerticalLayoutInteractor.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/verticalmode/PaymentMethodVerticalLayoutInteractor.kt index 90fbffcc438..00489de8913 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/verticalmode/PaymentMethodVerticalLayoutInteractor.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/verticalmode/PaymentMethodVerticalLayoutInteractor.kt @@ -14,6 +14,7 @@ import com.stripe.android.paymentsheet.LinkInlineHandler import com.stripe.android.paymentsheet.R import com.stripe.android.paymentsheet.analytics.code import com.stripe.android.paymentsheet.forms.FormFieldValues +import com.stripe.android.paymentsheet.model.PaymentMethodIncentive import com.stripe.android.paymentsheet.model.PaymentSelection import com.stripe.android.paymentsheet.navigation.PaymentSheetScreen import com.stripe.android.paymentsheet.state.WalletsState @@ -68,6 +69,7 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( paymentMethodMetadata: PaymentMethodMetadata, processing: StateFlow, selection: StateFlow, + paymentMethodIncentiveInteractor: PaymentMethodIncentiveInteractor, private val formTypeForCode: (code: String) -> FormType, private val onFormFieldValuesChanged: (formValues: FormFieldValues, selectedPaymentMethodCode: String) -> Unit, private val transitionToManageScreen: () -> Unit, @@ -102,6 +104,7 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( viewModel: BaseSheetViewModel, paymentMethodMetadata: PaymentMethodMetadata, customerStateHolder: CustomerStateHolder, + bankFormInteractor: BankFormInteractor, ): PaymentMethodVerticalLayoutInteractor { val linkInlineHandler = LinkInlineHandler.create(viewModel, viewModel.viewModelScope) val formHelper = FormHelper.create(viewModel, linkInlineHandler, paymentMethodMetadata) @@ -109,6 +112,7 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( paymentMethodMetadata = paymentMethodMetadata, processing = viewModel.processing, selection = viewModel.selection, + paymentMethodIncentiveInteractor = bankFormInteractor.paymentMethodIncentiveInteractor, formTypeForCode = { code -> if (formHelper.requiresFormScreen(code)) { FormType.UserInteractionRequired @@ -148,6 +152,7 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( viewModel = viewModel, paymentMethodMetadata = paymentMethodMetadata, customerStateHolder = customerStateHolder, + bankFormInteractor = bankFormInteractor, ) val screen = PaymentSheetScreen.VerticalModeForm(interactor = interactor) viewModel.navigationHandler.transitionToWithDelay(screen) @@ -207,16 +212,23 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( ) } - override val state: StateFlow = combineAsStateFlow( + private val displayablePaymentMethods = combineAsStateFlow( paymentMethods, + walletsState, + paymentMethodIncentiveInteractor.displayedIncentive, + ) { paymentMethods, walletsState, incentive -> + getDisplayablePaymentMethods(paymentMethods, walletsState, incentive) + } + + override val state: StateFlow = combineAsStateFlow( + displayablePaymentMethods, processing, verticalModeScreenSelection, displayedSavedPaymentMethod, - walletsState, availableSavedPaymentMethodAction, - ) { paymentMethods, isProcessing, mostRecentSelection, displayedSavedPaymentMethod, walletsState, action -> + ) { displayablePaymentMethods, isProcessing, mostRecentSelection, displayedSavedPaymentMethod, action -> PaymentMethodVerticalLayoutInteractor.State( - displayablePaymentMethods = getDisplayablePaymentMethods(paymentMethods, walletsState), + displayablePaymentMethods = displayablePaymentMethods, isProcessing = isProcessing, selection = mostRecentSelection, displayedSavedPaymentMethod = displayedSavedPaymentMethod, @@ -271,9 +283,10 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( private fun getDisplayablePaymentMethods( paymentMethods: List, walletsState: WalletsState?, + incentive: PaymentMethodIncentive?, ): List { val lpms = supportedPaymentMethods.map { supportedPaymentMethod -> - supportedPaymentMethod.asDisplayablePaymentMethod(paymentMethods) { + supportedPaymentMethod.asDisplayablePaymentMethod(paymentMethods, incentive) { handleViewAction(ViewAction.PaymentMethodSelected(supportedPaymentMethod.code)) } } diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/verticalmode/VerticalModeFormInteractor.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/verticalmode/VerticalModeFormInteractor.kt index c7982f42d54..8b80e545bf2 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/verticalmode/VerticalModeFormInteractor.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/verticalmode/VerticalModeFormInteractor.kt @@ -93,6 +93,7 @@ internal class DefaultVerticalModeFormInteractor( viewModel: BaseSheetViewModel, paymentMethodMetadata: PaymentMethodMetadata, customerStateHolder: CustomerStateHolder, + bankFormInteractor: BankFormInteractor, ): VerticalModeFormInteractor { val coroutineScope = CoroutineScope(Dispatchers.Default + SupervisorJob()) val formHelper = FormHelper.create( @@ -109,7 +110,8 @@ internal class DefaultVerticalModeFormInteractor( viewModel = viewModel, paymentMethodMetadata = paymentMethodMetadata, hostedSurface = CollectBankAccountLauncher.HOSTED_SURFACE_PAYMENT_ELEMENT, - selectedPaymentMethodCode = selectedPaymentMethodCode + selectedPaymentMethodCode = selectedPaymentMethodCode, + bankFormInteractor = bankFormInteractor, ), headerInformation = paymentMethodMetadata.formHeaderInformationForCode( selectedPaymentMethodCode, diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/verticalmode/VerticalModeInitialScreenFactory.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/verticalmode/VerticalModeInitialScreenFactory.kt index deea858fca0..d8df2736857 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/verticalmode/VerticalModeInitialScreenFactory.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/verticalmode/VerticalModeInitialScreenFactory.kt @@ -16,6 +16,7 @@ internal object VerticalModeInitialScreenFactory { customerStateHolder: CustomerStateHolder, ): List { val supportedPaymentMethodTypes = paymentMethodMetadata.supportedPaymentMethodTypes() + val bankFormInteractor = BankFormInteractor.create(viewModel) if (supportedPaymentMethodTypes.size == 1 && customerStateHolder.paymentMethods.value.isEmpty()) { return listOf( @@ -25,6 +26,7 @@ internal object VerticalModeInitialScreenFactory { viewModel = viewModel, paymentMethodMetadata = paymentMethodMetadata, customerStateHolder = customerStateHolder, + bankFormInteractor = bankFormInteractor, ), showsWalletHeader = true, ) @@ -36,6 +38,7 @@ internal object VerticalModeInitialScreenFactory { viewModel = viewModel, paymentMethodMetadata = paymentMethodMetadata, customerStateHolder = customerStateHolder, + bankFormInteractor = bankFormInteractor, ) val verticalModeScreen = PaymentSheetScreen.VerticalMode(interactor = interactor) add(verticalModeScreen) @@ -54,6 +57,7 @@ internal object VerticalModeInitialScreenFactory { viewModel = viewModel, paymentMethodMetadata = paymentMethodMetadata, customerStateHolder = customerStateHolder, + bankFormInteractor = bankFormInteractor, ), ) ) diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/viewmodels/BaseSheetViewModel.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/viewmodels/BaseSheetViewModel.kt index e1ce613ce62..c2763936a20 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/viewmodels/BaseSheetViewModel.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/viewmodels/BaseSheetViewModel.kt @@ -141,10 +141,6 @@ internal abstract class BaseSheetViewModel( abstract fun handlePaymentMethodSelected(selection: PaymentSelection?) - fun handleLinkedBankAccountChanged(selection: PaymentSelection.New.USBankAccount?) { - updateSelection(selection) - } - fun updateSelection(selection: PaymentSelection?) { when (selection) { is PaymentSelection.New -> newPaymentSelection = NewOrExternalPaymentSelection.New(selection) diff --git a/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/PaymentMethodMetadataFactory.kt b/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/PaymentMethodMetadataFactory.kt index 2b06267e483..59cea83d2f2 100644 --- a/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/PaymentMethodMetadataFactory.kt +++ b/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/PaymentMethodMetadataFactory.kt @@ -9,6 +9,7 @@ import com.stripe.android.model.StripeIntent import com.stripe.android.paymentsheet.PaymentSheet import com.stripe.android.paymentsheet.PaymentSheetFixtures import com.stripe.android.paymentsheet.addresselement.AddressDetails +import com.stripe.android.paymentsheet.model.PaymentMethodIncentive import com.stripe.android.ui.core.cbc.CardBrandChoiceEligibility import com.stripe.android.ui.core.elements.ExternalPaymentMethodSpec import com.stripe.android.ui.core.elements.LpmSerializer @@ -34,6 +35,7 @@ internal object PaymentMethodMetadataFactory { linkMode: LinkMode? = LinkMode.LinkPaymentMethod, cardBrandFilter: CardBrandFilter = DefaultCardBrandFilter, defaultBillingDetails: PaymentSheet.BillingDetails = PaymentSheet.BillingDetails(), + paymentMethodIncentive: PaymentMethodIncentive? = null, ): PaymentMethodMetadata { return PaymentMethodMetadata( stripeIntent = stripeIntent, @@ -53,7 +55,8 @@ internal object PaymentMethodMetadataFactory { isGooglePayReady = isGooglePayReady, linkInlineConfiguration = linkInlineConfiguration, linkMode = linkMode, - cardBrandFilter = cardBrandFilter + cardBrandFilter = cardBrandFilter, + paymentMethodIncentive = paymentMethodIncentive, ) } diff --git a/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/PaymentMethodMetadataTest.kt b/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/PaymentMethodMetadataTest.kt index b9e2bd8f61a..32b4490135f 100644 --- a/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/PaymentMethodMetadataTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/PaymentMethodMetadataTest.kt @@ -790,6 +790,7 @@ internal class PaymentMethodMetadataTest { linkInlineConfiguration = linkInlineConfiguration, linkMode = null, cardBrandFilter = PaymentSheetCardBrandFilter(cardBrandAcceptance), + paymentMethodIncentive = null, ) assertThat(metadata).isEqualTo(expectedMetadata) @@ -854,6 +855,7 @@ internal class PaymentMethodMetadataTest { linkInlineConfiguration = null, linkMode = null, cardBrandFilter = PaymentSheetCardBrandFilter(cardBrandAcceptance), + paymentMethodIncentive = null, ) assertThat(metadata).isEqualTo(expectedMetadata) diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/PaymentMethodsUITest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/PaymentMethodsUITest.kt index a5bea2ca12d..ba54af473d5 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/PaymentMethodsUITest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/PaymentMethodsUITest.kt @@ -89,6 +89,7 @@ class PaymentMethodsUITest { paymentMethods = paymentMethods, selectedIndex = 0, isEnabled = true, + incentive = null, onItemSelectedListener = {}, imageLoader = imageLoader, ) diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/model/PaymentMethodIncentiveTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/model/PaymentMethodIncentiveTest.kt new file mode 100644 index 00000000000..3cf4ff16349 --- /dev/null +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/model/PaymentMethodIncentiveTest.kt @@ -0,0 +1,44 @@ +package com.stripe.android.paymentsheet.model + +import com.google.common.truth.Truth.assertThat +import com.stripe.android.model.PaymentMethod +import org.junit.Test + +class PaymentMethodIncentiveTest { + + @Test + fun `Instant Debits incentive matches Link payment method`() { + val paymentMethodIncentive = PaymentMethodIncentive( + identifier = "link_instant_debits", + displayText = "$5" + ) + + val matchesLink = paymentMethodIncentive.matches(PaymentMethod.Type.Link.code) + assertThat(matchesLink).isTrue() + } + + @Test + fun `Instant Debits incentive does not match other payment methods`() { + val paymentMethodIncentive = PaymentMethodIncentive( + identifier = "link_instant_debits", + displayText = "$5" + ) + + val matchesLink = paymentMethodIncentive.matches(PaymentMethod.Type.USBankAccount.code) + assertThat(matchesLink).isFalse() + } + + @Test + fun `Unknown incentive does not match any payment method`() { + val paymentMethodIncentive = PaymentMethodIncentive( + identifier = "a_weird_payment_method", + displayText = "$5" + ) + + val matchesAny = PaymentMethod.Type.entries.any { + paymentMethodIncentive.matches(it.code) + } + + assertThat(matchesAny).isFalse() + } +} diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultPaymentElementLoaderTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultPaymentElementLoaderTest.kt index d583b02575b..deec2e92fa8 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultPaymentElementLoaderTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultPaymentElementLoaderTest.kt @@ -123,7 +123,7 @@ internal class DefaultPaymentElementLoaderTest { config = config.asCommonConfiguration(), customer = CustomerState( id = config.customer!!.id, - ephemeralKeySecret = config.customer.ephemeralKeySecret, + ephemeralKeySecret = config.customer!!.ephemeralKeySecret, paymentMethods = PAYMENT_METHODS, permissions = CustomerState.Permissions( canRemovePaymentMethods = true, diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/AddPaymentMethodTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/AddPaymentMethodTest.kt index a27cba15b92..a437fead214 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/AddPaymentMethodTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/AddPaymentMethodTest.kt @@ -251,6 +251,7 @@ internal class AddPaymentMethodTest { paymentSelection = null, processing = false, usBankAccountFormArguments = mock(), + incentive = null, ) val viewActionRecorder = ViewActionRecorder() diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/DefaultAddPaymentMethodInteractorTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/DefaultAddPaymentMethodInteractorTest.kt index ad3de2adefa..a904219d40d 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/DefaultAddPaymentMethodInteractorTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/DefaultAddPaymentMethodInteractorTest.kt @@ -7,6 +7,7 @@ import com.stripe.android.lpmfoundations.paymentmethod.PaymentMethodSaveConsentB import com.stripe.android.model.PaymentMethod import com.stripe.android.model.PaymentMethodCode import com.stripe.android.paymentsheet.forms.FormFieldValues +import com.stripe.android.paymentsheet.model.PaymentMethodIncentive import com.stripe.android.paymentsheet.model.PaymentSelection import com.stripe.android.paymentsheet.paymentdatacollection.FormArguments import com.stripe.android.paymentsheet.paymentdatacollection.ach.USBankAccountFormArguments @@ -230,6 +231,7 @@ class DefaultAddPaymentMethodInteractorTest { initiallySelectedPaymentMethodType: PaymentMethodCode = PaymentMethod.Type.Card.code, selection: StateFlow = MutableStateFlow(null), processing: StateFlow = MutableStateFlow(false), + incentive: StateFlow = MutableStateFlow(null), supportedPaymentMethods: List = emptyList(), createFormArguments: (PaymentMethodCode) -> FormArguments = { FormArguments( @@ -257,6 +259,7 @@ class DefaultAddPaymentMethodInteractorTest { initiallySelectedPaymentMethodType = initiallySelectedPaymentMethodType, selection = selection, processing = processing, + incentive = incentive, supportedPaymentMethods = supportedPaymentMethods, createFormArguments = createFormArguments, formElementsForCode = formElementsForCode, diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/FakeAddPaymentMethodInteractor.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/FakeAddPaymentMethodInteractor.kt index a9786a65696..386997bd0dd 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/FakeAddPaymentMethodInteractor.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/FakeAddPaymentMethodInteractor.kt @@ -52,6 +52,7 @@ internal class FakeAddPaymentMethodInteractor( paymentSelection = null, processing = false, usBankAccountFormArguments = mock(), + incentive = null, ) } } diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentMethodsUIScreenshotTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentMethodsUIScreenshotTest.kt index de3cc7475a9..53841b5db55 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentMethodsUIScreenshotTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentMethodsUIScreenshotTest.kt @@ -27,6 +27,7 @@ class PaymentMethodsUIScreenshotTest { paymentMethods = paymentMethods, selectedIndex = 0, isEnabled = true, + incentive = null, onItemSelectedListener = {}, imageLoader = mock(), ) @@ -48,6 +49,7 @@ class PaymentMethodsUIScreenshotTest { paymentMethods = paymentMethods, selectedIndex = 0, isEnabled = true, + incentive = null, onItemSelectedListener = {}, imageLoader = mock(), ) @@ -61,6 +63,7 @@ class PaymentMethodsUIScreenshotTest { paymentMethods = paymentMethods, selectedIndex = 3, isEnabled = true, + incentive = null, state = LazyListState(firstVisibleItemIndex = 3), onItemSelectedListener = {}, imageLoader = mock(), @@ -76,6 +79,7 @@ class PaymentMethodsUIScreenshotTest { paymentMethods = paymentMethods, selectedIndex = 0, isEnabled = true, + incentive = null, onItemSelectedListener = {}, imageLoader = mock(), ) @@ -94,6 +98,7 @@ class PaymentMethodsUIScreenshotTest { paymentMethods = paymentMethods, selectedIndex = 0, isEnabled = true, + incentive = null, onItemSelectedListener = {}, imageLoader = mock(), ) @@ -117,6 +122,7 @@ class PaymentMethodsUIScreenshotTest { paymentMethods = paymentMethods, selectedIndex = 0, isEnabled = true, + incentive = null, onItemSelectedListener = {}, imageLoader = mock(), ) diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/verticalmode/DefaultPaymentMethodVerticalLayoutInteractorTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/verticalmode/DefaultPaymentMethodVerticalLayoutInteractorTest.kt index 22ff5e09571..905eb7dc249 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/verticalmode/DefaultPaymentMethodVerticalLayoutInteractorTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/verticalmode/DefaultPaymentMethodVerticalLayoutInteractorTest.kt @@ -17,6 +17,7 @@ import com.stripe.android.paymentsheet.DisplayableSavedPaymentMethod import com.stripe.android.paymentsheet.analytics.code import com.stripe.android.paymentsheet.forms.FormFieldValues import com.stripe.android.paymentsheet.model.GooglePayButtonType +import com.stripe.android.paymentsheet.model.PaymentMethodIncentive import com.stripe.android.paymentsheet.model.PaymentSelection import com.stripe.android.paymentsheet.state.WalletsState import com.stripe.android.paymentsheet.verticalmode.DefaultPaymentMethodVerticalLayoutInteractor.FormType @@ -225,6 +226,38 @@ class DefaultPaymentMethodVerticalLayoutInteractorTest { } } + @Test + fun `Passes promo badge information along to affected payment method`() { + val incentive = PaymentMethodIncentive( + identifier = "link_instant_debits", + displayText = "$5", + ) + + runScenario(incentive = incentive) { + interactor.state.test { + val paymentMethods = awaitItem().displayablePaymentMethods + val instantDebits = paymentMethods.first { it.code == "link" } + assertThat(instantDebits.promoBadge).isEqualTo("$5") + } + } + } + + @Test + fun `Does not pass promo badge information along to non-affected payment methods`() { + val incentive = PaymentMethodIncentive( + identifier = "a_weird_payment_method", + displayText = "$5", + ) + + runScenario(incentive = incentive) { + interactor.state.test { + val paymentMethods = awaitItem().displayablePaymentMethods + val instantDebits = paymentMethods.first { it.code == "link" } + assertThat(instantDebits.promoBadge).isNull() + } + } + } + @Test fun `saved PM selection is removed if only saved pm is removed`() { val displayedPM = PaymentMethodFixtures.CARD_PAYMENT_METHOD @@ -976,6 +1009,7 @@ class DefaultPaymentMethodVerticalLayoutInteractorTest { initialProcessing: Boolean = false, initialSelection: PaymentSelection? = null, initialIsCurrentScreen: Boolean = false, + incentive: PaymentMethodIncentive? = null, formTypeForCode: (code: String) -> FormType = { notImplemented() }, onFormFieldValuesChanged: (formValues: FormFieldValues, selectedPaymentMethodCode: String) -> Unit = { _, _ -> notImplemented() @@ -1005,11 +1039,13 @@ class DefaultPaymentMethodVerticalLayoutInteractorTest { val walletsState = MutableStateFlow(null) val canRemove = MutableStateFlow(true) val isCurrentScreen: MutableStateFlow = MutableStateFlow(initialIsCurrentScreen) + val paymentMethodIncentiveInteractor = PaymentMethodIncentiveInteractor(incentive) val interactor = DefaultPaymentMethodVerticalLayoutInteractor( paymentMethodMetadata = paymentMethodMetadata, processing = processing, selection = selection, + paymentMethodIncentiveInteractor = paymentMethodIncentiveInteractor, formTypeForCode = formTypeForCode, onFormFieldValuesChanged = onFormFieldValuesChanged, transitionToManageScreen = transitionToManageScreen, diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/verticalmode/FakePaymentMethodVerticalLayoutInteractor.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/verticalmode/FakePaymentMethodVerticalLayoutInteractor.kt index 9a143489cf7..9eb31a262f1 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/verticalmode/FakePaymentMethodVerticalLayoutInteractor.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/verticalmode/FakePaymentMethodVerticalLayoutInteractor.kt @@ -22,9 +22,11 @@ internal class FakePaymentMethodVerticalLayoutInteractor( ): FakePaymentMethodVerticalLayoutInteractor { val displayablePaymentMethods = paymentMethodMetadata.sortedSupportedPaymentMethods() .map { supportedPaymentMethod -> - supportedPaymentMethod.asDisplayablePaymentMethod(emptyList()) { - throw AssertionError("Not expected.") - } + supportedPaymentMethod.asDisplayablePaymentMethod( + customerSavedPaymentMethods = emptyList(), + incentive = null, + onClick = { throw AssertionError("Not expected.") }, + ) } val initialState = PaymentMethodVerticalLayoutInteractor.State( displayablePaymentMethods = displayablePaymentMethods, diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/verticalmode/NewPaymentMethodVerticalLayoutUIScreenshotTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/verticalmode/NewPaymentMethodVerticalLayoutUIScreenshotTest.kt index 973f73c99bf..18efda58876 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/verticalmode/NewPaymentMethodVerticalLayoutUIScreenshotTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/verticalmode/NewPaymentMethodVerticalLayoutUIScreenshotTest.kt @@ -15,7 +15,13 @@ internal class NewPaymentMethodVerticalLayoutUIScreenshotTest { val paparazziRule = PaparazziRule() private val paymentMethods: List by lazy { - MockPaymentMethodsFactory.create().map { it.asDisplayablePaymentMethod(emptyList()) { } } + MockPaymentMethodsFactory.create().map { + it.asDisplayablePaymentMethod( + customerSavedPaymentMethods = emptyList(), + incentive = null, + onClick = {}, + ) + } } @Test @@ -37,7 +43,12 @@ internal class NewPaymentMethodVerticalLayoutUIScreenshotTest { displayNameResource = R.string.stripe_paymentsheet_payment_method_us_bank_account, iconResource = R.drawable.stripe_ic_paymentsheet_pm_bank, iconRequiresTinting = true - ).asDisplayablePaymentMethod(emptyList()) { } + ).asDisplayablePaymentMethod( + customerSavedPaymentMethods = emptyList(), + incentive = null, + onClick = {}, + ) + val paymentMethods = paymentMethods.toMutableList() paymentMethods.add(1, bankPaymentMethod) paparazziRule.snapshot { @@ -68,7 +79,11 @@ internal class NewPaymentMethodVerticalLayoutUIScreenshotTest { val paymentMethods = listOf( ExternalPaymentMethodUiDefinitionFactory( PaymentMethodFixtures.PAYPAL_EXTERNAL_PAYMENT_METHOD_SPEC - ).createSupportedPaymentMethod().asDisplayablePaymentMethod(emptyList()) { } + ).createSupportedPaymentMethod().asDisplayablePaymentMethod( + customerSavedPaymentMethods = emptyList(), + incentive = null, + onClick = {}, + ) ).plus(paymentMethods) paparazziRule.snapshot { NewPaymentMethodVerticalLayoutUI( diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/verticalmode/PaymentMethodVerticalLayoutUIScreenshotTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/verticalmode/PaymentMethodVerticalLayoutUIScreenshotTest.kt index 39d0513ab34..a0ef71dab1e 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/verticalmode/PaymentMethodVerticalLayoutUIScreenshotTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/verticalmode/PaymentMethodVerticalLayoutUIScreenshotTest.kt @@ -15,7 +15,13 @@ internal class PaymentMethodVerticalLayoutUIScreenshotTest { val paparazziRule = PaparazziRule(PaymentSheetAppearance.entries) private val paymentMethods: List by lazy { - MockPaymentMethodsFactory.create().map { it.asDisplayablePaymentMethod(emptyList()) { } } + MockPaymentMethodsFactory.create().map { + it.asDisplayablePaymentMethod( + customerSavedPaymentMethods = emptyList(), + incentive = null, + onClick = {}, + ) + } } private val savedPaymentMethod: DisplayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard() diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/verticalmode/PaymentMethodVerticalLayoutUITest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/verticalmode/PaymentMethodVerticalLayoutUITest.kt index 7b15bb44b5f..d8a40949898 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/verticalmode/PaymentMethodVerticalLayoutUITest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/verticalmode/PaymentMethodVerticalLayoutUITest.kt @@ -116,7 +116,11 @@ internal class PaymentMethodVerticalLayoutUITest { PaymentMethodVerticalLayoutInteractor.State( displayablePaymentMethods = listOf( CardDefinition.uiDefinitionFactory().supportedPaymentMethod(CardDefinition, emptyList())!! - .asDisplayablePaymentMethod(emptyList()) { onClickCalled = true }, + .asDisplayablePaymentMethod( + customerSavedPaymentMethods = emptyList(), + incentive = null, + onClick = { onClickCalled = true }, + ), ), isProcessing = false, selection = null, @@ -164,7 +168,13 @@ internal class PaymentMethodVerticalLayoutUITest { PaymentIntentFixtures.PI_WITH_PAYMENT_METHOD!!.copy( paymentMethodTypes = listOf("card", "cashapp", "klarna") ) - ).sortedSupportedPaymentMethods().map { it.asDisplayablePaymentMethod(emptyList()) { } }, + ).sortedSupportedPaymentMethods().map { + it.asDisplayablePaymentMethod( + customerSavedPaymentMethods = emptyList(), + incentive = null, + onClick = {}, + ) + }, isProcessing = false, selection = null, displayedSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), @@ -193,7 +203,13 @@ internal class PaymentMethodVerticalLayoutUITest { PaymentIntentFixtures.PI_WITH_PAYMENT_METHOD!!.copy( paymentMethodTypes = listOf("card", "cashapp", "klarna") ) - ).sortedSupportedPaymentMethods().map { it.asDisplayablePaymentMethod(emptyList()) { } }, + ).sortedSupportedPaymentMethods().map { + it.asDisplayablePaymentMethod( + customerSavedPaymentMethods = emptyList(), + incentive = null, + onClick = {}, + ) + }, isProcessing = false, selection = PaymentSelection.Saved(PaymentMethodFixtures.displayableCard().paymentMethod), displayedSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), @@ -234,7 +250,11 @@ internal class PaymentMethodVerticalLayoutUITest { runScenario( PaymentMethodVerticalLayoutInteractor.State( displayablePaymentMethods = supportedPaymentMethods.map { - it.asDisplayablePaymentMethod(emptyList()) { } + it.asDisplayablePaymentMethod( + customerSavedPaymentMethods = emptyList(), + incentive = null, + onClick = {}, + ) }, isProcessing = false, selection = selection,