From 683c3538d4535f9f965834a6634c37029e907629 Mon Sep 17 00:00:00 2001 From: Chengtin Tsai Date: Thu, 2 Jul 2026 13:41:23 -0700 Subject: [PATCH 1/7] Clarify card payment method update capability Committed-By-Agent: codex Co-authored-by: codex --- .../customersheet/CustomerPermissions.kt | 2 +- .../customersheet/CustomerSheetViewModel.kt | 8 ++--- .../customersheet/CustomerSheetViewState.kt | 4 +-- .../data/CustomerAdapterDataSource.kt | 2 +- ...CustomerSessionInitializationDataSource.kt | 2 +- .../paymentmethod/CustomerMetadata.kt | 22 +++++++------- .../embedded/content/EmbeddedContentHelper.kt | 2 +- .../EmbeddedUpdateScreenInteractorFactory.kt | 2 +- .../paymentsheet/CustomerStateHolder.kt | 2 +- .../DefaultCustomerStateHolder.kt | 4 +-- .../DisplayableSavedPaymentMethod.kt | 11 +++++++ .../SavedPaymentMethodEditability.kt | 4 +-- .../paymentsheet/SavedPaymentMethodMutator.kt | 10 +++---- .../ui/UpdatePaymentMethodInteractor.kt | 22 ++++---------- .../paymentsheet/ui/UpdatePaymentMethodUI.kt | 4 +-- .../PaymentMethodVerticalLayoutInteractor.kt | 23 ++++++-------- .../customersheet/CustomerSheetFixtures.kt | 2 +- .../CustomerSheetScreenshotTest.kt | 2 +- .../CustomerSheetViewModelTest.kt | 30 +++++++++---------- .../data/CustomerAdapterDataSourceTest.kt | 2 +- ...omerSessionInitializationDataSourceTest.kt | 4 +-- .../state/DefaultCustomerSheetLoaderTest.kt | 2 +- .../utils/CustomerSheetTestHelper.kt | 2 +- .../utils/FakeCustomerSheetLoader.kt | 2 +- .../paymentmethod/CustomerMetadataTest.kt | 2 +- .../PaymentMethodMetadataFactory.kt | 6 ++-- .../PaymentMethodMetadataFixtures.kt | 12 ++++---- .../sheet/EmbeddedSheetActivityTest.kt | 4 +-- .../DefaultCustomerStateHolderTest.kt | 2 +- .../paymentsheet/FakeCustomerStateHolder.kt | 2 +- .../SavedPaymentMethodMutatorTest.kt | 10 +++---- ...DefaultSavedPaymentMethodRepositoryTest.kt | 5 ++-- .../state/CreateCustomerStateTest.kt | 4 +-- .../DefaultAnalyticsMetadataFactoryTest.kt | 2 +- .../state/DefaultPaymentElementLoaderTest.kt | 16 +++++----- .../state/DefaultPaymentMethodFilterTest.kt | 2 +- .../state/DefaultRetrieveCustomerEmailTest.kt | 4 +-- ...efaultUpdatePaymentMethodInteractorTest.kt | 20 ++++++------- .../ui/FakeUpdatePaymentMethodInteractor.kt | 16 ++++------ ...ScreenUpdatePaymentMethodScreenshotTest.kt | 14 ++++----- ...ymentMethodVerticalLayoutInteractorTest.kt | 4 +-- 41 files changed, 142 insertions(+), 153 deletions(-) diff --git a/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerPermissions.kt b/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerPermissions.kt index 00ab6ba8ea4..e6aed774d7f 100644 --- a/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerPermissions.kt +++ b/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerPermissions.kt @@ -5,7 +5,7 @@ import com.stripe.android.common.model.PaymentMethodRemovePermission internal data class CustomerPermissions( val removePaymentMethod: PaymentMethodRemovePermission, val canRemoveLastPaymentMethod: Boolean, - val canUpdateFullPaymentMethodDetails: Boolean + val canUpdateCardPaymentMethodDetails: Boolean ) { val canRemovePaymentMethods: Boolean get() = removePaymentMethod == PaymentMethodRemovePermission.Full || diff --git a/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewModel.kt b/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewModel.kt index 71cf4939e7e..1c00055c014 100644 --- a/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewModel.kt +++ b/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewModel.kt @@ -157,7 +157,7 @@ internal class CustomerSheetViewModel( permissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.None, canRemoveLastPaymentMethod = false, - canUpdateFullPaymentMethodDetails = false, + canUpdateCardPaymentMethodDetails = false, ), metadata = null, ) @@ -570,7 +570,7 @@ internal class CustomerSheetViewModel( updatePaymentMethodInteractor = DefaultUpdatePaymentMethodInteractor( isLiveMode = isLiveMode, canRemove = customerState.canRemove, - canUpdateFullPaymentMethodDetails = customerState.canUpdateFullPaymentMethodDetails, + canUpdateCardPaymentMethodDetails = customerState.canUpdateCardPaymentMethodDetails, displayableSavedPaymentMethod = paymentMethod, addressCollectionMode = configuration.billingDetailsCollectionConfiguration.address, allowedBillingCountries = @@ -1274,12 +1274,12 @@ internal class CustomerSheetViewModel( else -> permissions.canRemovePaymentMethods } - val canUpdateFullPaymentMethodDetails = permissions.canUpdateFullPaymentMethodDetails + val canUpdateCardPaymentMethodDetails = permissions.canUpdateCardPaymentMethodDetails val cbcEligibility = metadata?.cbcEligibility ?: CardBrandChoiceEligibility.Ineligible val canEdit = canRemove || paymentMethods.any { method -> - isModifiable(method, cbcEligibility, canUpdateFullPaymentMethodDetails) + isModifiable(method, cbcEligibility, canUpdateCardPaymentMethodDetails) } val canShowSavedPaymentMethods = paymentMethods.isNotEmpty() || shouldShowGooglePay(metadata) diff --git a/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewState.kt b/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewState.kt index b5cef3de27e..721bd2818ed 100644 --- a/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewState.kt +++ b/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewState.kt @@ -144,10 +144,10 @@ internal sealed class CustomerSheetViewState( internal fun isModifiable( paymentMethod: PaymentMethod, cbcEligibility: CardBrandChoiceEligibility, - canUpdateFullPaymentMethodDetails: Boolean + canUpdateCardPaymentMethodDetails: Boolean ): Boolean { return paymentMethod.isModifiable( - canUpdateFullPaymentMethodDetails = canUpdateFullPaymentMethodDetails, + canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, isCbcEligible = cbcEligibility is CardBrandChoiceEligibility.Eligible, ) } diff --git a/paymentsheet/src/main/java/com/stripe/android/customersheet/data/CustomerAdapterDataSource.kt b/paymentsheet/src/main/java/com/stripe/android/customersheet/data/CustomerAdapterDataSource.kt index 22756d9fb4c..36b91df4bc2 100644 --- a/paymentsheet/src/main/java/com/stripe/android/customersheet/data/CustomerAdapterDataSource.kt +++ b/paymentsheet/src/main/java/com/stripe/android/customersheet/data/CustomerAdapterDataSource.kt @@ -67,7 +67,7 @@ internal class CustomerAdapterDataSource @Inject constructor( // Always `Full` for `Adapter` use case removePaymentMethod = PaymentMethodRemovePermission.Full, // Payment Method Update is customer sessions-only feature, so this value is unused. - canUpdateFullPaymentMethodDetails = false, + canUpdateCardPaymentMethodDetails = false, ), // Default payment methods are a customer sessions-only feature, so this value is unused. defaultPaymentMethodId = null, diff --git a/paymentsheet/src/main/java/com/stripe/android/customersheet/data/CustomerSessionInitializationDataSource.kt b/paymentsheet/src/main/java/com/stripe/android/customersheet/data/CustomerSessionInitializationDataSource.kt index 3e5acda2ead..a1965bec139 100644 --- a/paymentsheet/src/main/java/com/stripe/android/customersheet/data/CustomerSessionInitializationDataSource.kt +++ b/paymentsheet/src/main/java/com/stripe/android/customersheet/data/CustomerSessionInitializationDataSource.kt @@ -68,7 +68,7 @@ internal class CustomerSessionInitializationDataSource @Inject constructor( PaymentMethodRemovePermission.None }, // Should always be enabled when using `customer_session` - canUpdateFullPaymentMethodDetails = true + canUpdateCardPaymentMethodDetails = true ), defaultPaymentMethodId = customer.defaultPaymentMethod, customerId = customer.session.customerId, diff --git a/paymentsheet/src/main/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadata.kt b/paymentsheet/src/main/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadata.kt index 984dcd510a8..7087b4fc394 100644 --- a/paymentsheet/src/main/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadata.kt +++ b/paymentsheet/src/main/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadata.kt @@ -13,7 +13,7 @@ internal sealed class CustomerMetadata : Parcelable { abstract val removePaymentMethod: PaymentMethodRemovePermission abstract val saveConsent: PaymentMethodSaveConsentBehavior abstract val canRemoveLastPaymentMethod: Boolean - abstract val canUpdateFullPaymentMethodDetails: Boolean + abstract val canUpdateCardPaymentMethodDetails: Boolean val canRemovePaymentMethods: Boolean get() = removePaymentMethod == PaymentMethodRemovePermission.Full || @@ -27,7 +27,7 @@ internal sealed class CustomerMetadata : Parcelable { override val removePaymentMethod: PaymentMethodRemovePermission, override val saveConsent: PaymentMethodSaveConsentBehavior, override val canRemoveLastPaymentMethod: Boolean, - override val canUpdateFullPaymentMethodDetails: Boolean, + override val canUpdateCardPaymentMethodDetails: Boolean, ) : CustomerMetadata() @Parcelize @@ -39,7 +39,7 @@ internal sealed class CustomerMetadata : Parcelable { override val removePaymentMethod: PaymentMethodRemovePermission, override val saveConsent: PaymentMethodSaveConsentBehavior, override val canRemoveLastPaymentMethod: Boolean, - override val canUpdateFullPaymentMethodDetails: Boolean, + override val canUpdateCardPaymentMethodDetails: Boolean, ) : CustomerMetadata() @Parcelize @@ -55,8 +55,8 @@ internal sealed class CustomerMetadata : Parcelable { // When removal is permitted, CheckoutSession doesn't restrict removing the last one. override val canRemoveLastPaymentMethod: Boolean get() = true - // CheckoutSession doesn't support updating full payment method details. - override val canUpdateFullPaymentMethodDetails: Boolean get() = false + // CheckoutSession card detail updates are wired in a separate change. + override val canUpdateCardPaymentMethodDetails: Boolean get() = false } companion object { @@ -112,7 +112,7 @@ internal sealed class CustomerMetadata : Parcelable { saveConsent = saveConsent, canRemoveLastPaymentMethod = canRemoveLastPaymentMethod, // Should always be enabled when using `customer_session` - canUpdateFullPaymentMethodDetails = true, + canUpdateCardPaymentMethodDetails = true, ) } @@ -143,7 +143,7 @@ internal sealed class CustomerMetadata : Parcelable { * sessions. */ canRemoveLastPaymentMethod = configuration.allowsRemovalOfLastSavedPaymentMethod, - canUpdateFullPaymentMethodDetails = false, + canUpdateCardPaymentMethodDetails = false, ) } @@ -158,8 +158,8 @@ internal sealed class CustomerMetadata : Parcelable { val removePaymentMethod = customerSheetSession.permissions.removePaymentMethod val saveConsent = customerSheetSession.paymentMethodSaveConsentBehavior val canRemoveLastPaymentMethod = configuration.allowsRemovalOfLastSavedPaymentMethod - val canUpdateFullPaymentMethodDetails = - customerSheetSession.permissions.canUpdateFullPaymentMethodDetails + val canUpdateCardPaymentMethodDetails = + customerSheetSession.permissions.canUpdateCardPaymentMethodDetails return if (customerSessionClientSecret != null) { CustomerSession( @@ -170,7 +170,7 @@ internal sealed class CustomerMetadata : Parcelable { removePaymentMethod = removePaymentMethod, saveConsent = saveConsent, canRemoveLastPaymentMethod = canRemoveLastPaymentMethod, - canUpdateFullPaymentMethodDetails = canUpdateFullPaymentMethodDetails, + canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, ) } else { LegacyEphemeralKey( @@ -180,7 +180,7 @@ internal sealed class CustomerMetadata : Parcelable { removePaymentMethod = removePaymentMethod, saveConsent = saveConsent, canRemoveLastPaymentMethod = canRemoveLastPaymentMethod, - canUpdateFullPaymentMethodDetails = canUpdateFullPaymentMethodDetails, + canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, ) } } diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/content/EmbeddedContentHelper.kt b/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/content/EmbeddedContentHelper.kt index afd9370742a..e147b4ddb90 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/content/EmbeddedContentHelper.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/content/EmbeddedContentHelper.kt @@ -252,7 +252,7 @@ internal class DefaultEmbeddedContentHelper @Inject constructor( paymentMethods = customerStateHolder.paymentMethods, mostRecentlySelectedSavedPaymentMethod = customerStateHolder.mostRecentlySelectedSavedPaymentMethod, canRemove = customerStateHolder.canRemove, - canUpdateFullPaymentMethodDetails = customerStateHolder.canUpdateFullPaymentMethodDetails, + canUpdateCardPaymentMethodDetails = customerStateHolder.canUpdateCardPaymentMethodDetails, walletsState = walletsState, updateSelection = { updatedSelection, requiresConfirmation -> setSelection(updatedSelection) diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/manage/EmbeddedUpdateScreenInteractorFactory.kt b/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/manage/EmbeddedUpdateScreenInteractorFactory.kt index fba6ba8ef52..e794098039e 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/manage/EmbeddedUpdateScreenInteractorFactory.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/manage/EmbeddedUpdateScreenInteractorFactory.kt @@ -33,7 +33,7 @@ internal class DefaultEmbeddedUpdateScreenInteractorFactory @Inject constructor( return DefaultUpdatePaymentMethodInteractor( isLiveMode = paymentMethodMetadata.stripeIntent.isLiveMode, canRemove = customerStateHolder.canRemove.value, - canUpdateFullPaymentMethodDetails = customerStateHolder.canUpdateFullPaymentMethodDetails.value, + canUpdateCardPaymentMethodDetails = customerStateHolder.canUpdateCardPaymentMethodDetails.value, displayableSavedPaymentMethod = displayableSavedPaymentMethod, cardBrandFilter = paymentMethodMetadata.cardBrandFilter, addressCollectionMode = paymentMethodMetadata.billingDetailsCollectionConfiguration.address, diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/CustomerStateHolder.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/CustomerStateHolder.kt index 3a2c1ba36cc..1bfbc862468 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/CustomerStateHolder.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/CustomerStateHolder.kt @@ -21,7 +21,7 @@ internal interface CustomerStateHolder { val canRemove: StateFlow - val canUpdateFullPaymentMethodDetails: StateFlow + val canUpdateCardPaymentMethodDetails: StateFlow fun setCustomerState(customerState: CustomerState?) diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DefaultCustomerStateHolder.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DefaultCustomerStateHolder.kt index 3f2a9c9dcab..ff33631fdbf 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DefaultCustomerStateHolder.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DefaultCustomerStateHolder.kt @@ -48,8 +48,8 @@ internal class DefaultCustomerStateHolder( } ?: false } - override val canUpdateFullPaymentMethodDetails: StateFlow = customerMetadata.mapAsStateFlow { - it?.canUpdateFullPaymentMethodDetails ?: false + override val canUpdateCardPaymentMethodDetails: StateFlow = customerMetadata.mapAsStateFlow { + it?.canUpdateCardPaymentMethodDetails ?: false } override fun setCustomerState(customerState: CustomerState?) { diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethod.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethod.kt index 03df5f2b5bb..b7187181f72 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethod.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethod.kt @@ -27,6 +27,17 @@ internal data class DisplayableSavedPaymentMethod private constructor( SavedPaymentMethod.Unexpected -> false } + fun canChangeCbc(): Boolean { + return paymentMethod.canChangeCbc(isCbcEligible) + } + + fun isModifiable(canUpdateCardPaymentMethodDetails: Boolean): Boolean { + return paymentMethod.isModifiable( + canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + isCbcEligible = isCbcEligible, + ) + } + fun getDescription() = when (savedPaymentMethod) { is SavedPaymentMethod.Card -> { resolvableString( diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodEditability.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodEditability.kt index cdeeaa880b8..ffd08064aeb 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodEditability.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodEditability.kt @@ -4,12 +4,12 @@ import com.stripe.android.core.utils.DateUtils import com.stripe.android.model.PaymentMethod internal fun PaymentMethod.isModifiable( - canUpdateFullPaymentMethodDetails: Boolean, + canUpdateCardPaymentMethodDetails: Boolean, isCbcEligible: Boolean, ): Boolean { val card = editableSavedCard() ?: return false - return canUpdateFullPaymentMethodDetails || (card.isExpired().not() && canChangeCbc(isCbcEligible)) + return canUpdateCardPaymentMethodDetails || (card.isExpired().not() && canChangeCbc(isCbcEligible)) } internal fun PaymentMethod.canChangeCbc(isCbcEligible: Boolean): Boolean { diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodMutator.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodMutator.kt index 57866ead050..977fcf887de 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodMutator.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodMutator.kt @@ -95,10 +95,8 @@ internal class SavedPaymentMethodMutator( paymentOptionsItems ) { canRemove, items -> canRemove || items.filterIsInstance().any { item -> - val displayableSavedPaymentMethod = item.displayableSavedPaymentMethod - displayableSavedPaymentMethod.paymentMethod.isModifiable( - canUpdateFullPaymentMethodDetails = customerStateHolder.canUpdateFullPaymentMethodDetails.value, - isCbcEligible = displayableSavedPaymentMethod.isCbcEligible, + item.displayableSavedPaymentMethod.isModifiable( + customerStateHolder.canUpdateCardPaymentMethodDetails.value ) } } @@ -379,8 +377,8 @@ internal class SavedPaymentMethodMutator( DefaultUpdatePaymentMethodInteractor( isLiveMode = isLiveMode, canRemove = canRemove, - canUpdateFullPaymentMethodDetails = viewModel.customerStateHolder - .canUpdateFullPaymentMethodDetails.value, + canUpdateCardPaymentMethodDetails = viewModel.customerStateHolder + .canUpdateCardPaymentMethodDetails.value, displayableSavedPaymentMethod = displayableSavedPaymentMethod, cardBrandFilter = PaymentSheetCardBrandFilter(viewModel.config.cardBrandAcceptance), addressCollectionMode = viewModel.config.billingDetailsCollectionConfiguration.address, diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodInteractor.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodInteractor.kt index 2dba518e7da..6400d63b95b 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodInteractor.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodInteractor.kt @@ -15,8 +15,6 @@ import com.stripe.android.paymentsheet.PaymentSheet.BillingDetailsCollectionConf import com.stripe.android.paymentsheet.PaymentSheet.BillingDetailsCollectionConfiguration.CollectionMode import com.stripe.android.paymentsheet.R import com.stripe.android.paymentsheet.SavedPaymentMethod -import com.stripe.android.paymentsheet.canChangeCbc -import com.stripe.android.paymentsheet.isModifiable import com.stripe.android.uicore.elements.AutocompleteAddressInteractor import com.stripe.android.uicore.utils.combineAsStateFlow import com.stripe.android.uicore.utils.mapAsStateFlow @@ -41,7 +39,7 @@ internal interface UpdatePaymentMethodInteractor { val shouldShowSetAsDefaultCheckbox: Boolean val setAsDefaultCheckboxEnabled: Boolean val shouldShowSaveButton: Boolean - val canUpdateFullPaymentMethodDetails: Boolean + val canUpdateCardPaymentMethodDetails: Boolean val addressCollectionMode: AddressCollectionMode val allowedBillingCountries: Set val editCardDetailsInteractor: EditCardDetailsInteractor @@ -116,7 +114,7 @@ internal class DefaultUpdatePaymentMethodInteractor( override val cardBrandFilter: CardBrandFilter, override val addressCollectionMode: AddressCollectionMode, override val allowedBillingCountries: Set, - override val canUpdateFullPaymentMethodDetails: Boolean, + override val canUpdateCardPaymentMethodDetails: Boolean, override val removeMessage: ResolvableString?, val isDefaultPaymentMethod: Boolean, override val shouldShowSetAsDefaultCheckbox: Boolean, @@ -142,10 +140,7 @@ internal class DefaultUpdatePaymentMethodInteractor( displayableSavedPaymentMethod ) override val isModifiablePaymentMethod: Boolean - get() = displayableSavedPaymentMethod.paymentMethod.isModifiable( - canUpdateFullPaymentMethodDetails = canUpdateFullPaymentMethodDetails, - isCbcEligible = displayableSavedPaymentMethod.isCbcEligible, - ) + get() = displayableSavedPaymentMethod.isModifiable(canUpdateCardPaymentMethodDetails) override val topBarState: PaymentSheetTopBarState = PaymentSheetTopBarStateFactory.create( isLiveMode = isLiveMode, @@ -180,17 +175,12 @@ internal class DefaultUpdatePaymentMethodInteractor( private fun createEditCardDetailsInteractorForCard( savedPaymentMethodCard: SavedPaymentMethod.Card, ): EditCardDetailsInteractor { - val isModifiable = displayableSavedPaymentMethod.paymentMethod.isModifiable( - canUpdateFullPaymentMethodDetails = canUpdateFullPaymentMethodDetails, - isCbcEligible = displayableSavedPaymentMethod.isCbcEligible, - ) + val isModifiable = displayableSavedPaymentMethod.isModifiable(canUpdateCardPaymentMethodDetails) val payload = EditCardPayload.create(savedPaymentMethodCard.card, savedPaymentMethodCard.billingDetails) val cardEditConfiguration = CardEditConfiguration( cardBrandFilter = cardBrandFilter, - isCbcModifiable = isModifiable && displayableSavedPaymentMethod.paymentMethod.canChangeCbc( - displayableSavedPaymentMethod.isCbcEligible - ), - areExpiryDateAndAddressModificationSupported = isModifiable && canUpdateFullPaymentMethodDetails, + isCbcModifiable = isModifiable && displayableSavedPaymentMethod.canChangeCbc(), + areExpiryDateAndAddressModificationSupported = isModifiable && canUpdateCardPaymentMethodDetails, ) return editCardDetailsInteractorFactory.create( payload = payload, diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUI.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUI.kt index 888e89b8882..9f31ec2f12f 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUI.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUI.kt @@ -102,7 +102,7 @@ internal fun UpdatePaymentMethodUI(interactor: UpdatePaymentMethodInteractor, mo } val showCardDetailsCannotBeChanged = interactor.isExpiredCard.not() && - (interactor.isModifiablePaymentMethod.not() || interactor.canUpdateFullPaymentMethodDetails.not()) + (interactor.isModifiablePaymentMethod.not() || interactor.canUpdateCardPaymentMethodDetails.not()) if (showCardDetailsCannotBeChanged) { DetailsCannotBeChangedText(interactor, shouldShowCardBrandDropdown, context) } @@ -359,7 +359,7 @@ private fun PreviewUpdatePaymentMethodUI() { interactor = DefaultUpdatePaymentMethodInteractor( isLiveMode = false, canRemove = true, - canUpdateFullPaymentMethodDetails = true, + canUpdateCardPaymentMethodDetails = true, displayableSavedPaymentMethod = exampleCard, addressCollectionMode = AddressCollectionMode.Automatic, allowedBillingCountries = emptySet(), 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 b72e84c0abe..058544d0d49 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 @@ -18,7 +18,6 @@ import com.stripe.android.paymentsheet.R import com.stripe.android.paymentsheet.analytics.code import com.stripe.android.paymentsheet.forms.FormArgumentsFactory import com.stripe.android.paymentsheet.forms.FormFieldValues -import com.stripe.android.paymentsheet.isModifiable import com.stripe.android.paymentsheet.model.PaymentMethodIncentive import com.stripe.android.paymentsheet.model.PaymentSelection import com.stripe.android.paymentsheet.model.mandateTextFromPaymentMethodMetadata @@ -104,7 +103,7 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( private val mostRecentlySelectedSavedPaymentMethod: StateFlow, private val canRemove: StateFlow, private val walletsState: StateFlow, - private val canUpdateFullPaymentMethodDetails: StateFlow, + private val canUpdateCardPaymentMethodDetails: StateFlow, private val updateSelection: (PaymentSelection?, Boolean) -> Unit, private val isCurrentScreen: StateFlow, private val reportPaymentMethodTypeSelected: (PaymentMethodCode) -> Unit, @@ -179,7 +178,7 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( } }, walletsState = viewModel.walletsState, - canUpdateFullPaymentMethodDetails = viewModel.customerStateHolder.canUpdateFullPaymentMethodDetails, + canUpdateCardPaymentMethodDetails = viewModel.customerStateHolder.canUpdateCardPaymentMethodDetails, isCurrentScreen = isCurrentScreen, reportPaymentMethodTypeSelected = viewModel.eventReporter::onSelectPaymentMethod, reportFormShown = viewModel.eventReporter::onPaymentMethodFormShown, @@ -242,13 +241,13 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( paymentMethods, displayedSavedPaymentMethod, canRemove, - canUpdateFullPaymentMethodDetails, - ) { paymentMethods, displayedSavedPaymentMethod, canRemove, canUpdateFullPaymentMethodDetails -> + canUpdateCardPaymentMethodDetails, + ) { paymentMethods, displayedSavedPaymentMethod, canRemove, canUpdateCardPaymentMethodDetails -> getAvailableSavedPaymentMethodAction( paymentMethods = paymentMethods, savedPaymentMethod = displayedSavedPaymentMethod, canRemove = canRemove, - canUpdateFullPaymentMethodDetails = canUpdateFullPaymentMethodDetails, + canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, ) } @@ -504,7 +503,7 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( paymentMethods: List?, savedPaymentMethod: DisplayableSavedPaymentMethod?, canRemove: Boolean, - canUpdateFullPaymentMethodDetails: Boolean, + canUpdateCardPaymentMethodDetails: Boolean, ): PaymentMethodVerticalLayoutInteractor.SavedPaymentMethodAction { if (paymentMethods == null || savedPaymentMethod == null) { return PaymentMethodVerticalLayoutInteractor.SavedPaymentMethodAction.NONE @@ -516,7 +515,7 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( getSavedPaymentMethodActionForOnePaymentMethod( canRemove = canRemove, savedPaymentMethod = savedPaymentMethod, - canUpdateFullPaymentMethodDetails = canUpdateFullPaymentMethodDetails, + canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, ) } else -> @@ -527,13 +526,9 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( private fun getSavedPaymentMethodActionForOnePaymentMethod( canRemove: Boolean, savedPaymentMethod: DisplayableSavedPaymentMethod?, - canUpdateFullPaymentMethodDetails: Boolean, + canUpdateCardPaymentMethodDetails: Boolean, ): PaymentMethodVerticalLayoutInteractor.SavedPaymentMethodAction { - val canUpdatePaymentMethod = savedPaymentMethod?.paymentMethod?.isModifiable( - canUpdateFullPaymentMethodDetails = canUpdateFullPaymentMethodDetails, - isCbcEligible = savedPaymentMethod.isCbcEligible, - ) == true - return if (canUpdatePaymentMethod || canRemove) { + return if (savedPaymentMethod?.isModifiable(canUpdateCardPaymentMethodDetails) == true || canRemove) { PaymentMethodVerticalLayoutInteractor.SavedPaymentMethodAction.MANAGE_ONE } else { PaymentMethodVerticalLayoutInteractor.SavedPaymentMethodAction.NONE diff --git a/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetFixtures.kt b/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetFixtures.kt index 53b4151d881..a2865c52697 100644 --- a/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetFixtures.kt +++ b/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetFixtures.kt @@ -103,7 +103,7 @@ internal object CustomerSheetFixtures { permissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.Full, canRemoveLastPaymentMethod = true, - canUpdateFullPaymentMethodDetails = true, + canUpdateCardPaymentMethodDetails = true, ), defaultPaymentMethodId = null, customerId = customer?.session?.customerId ?: "unused_for_customer_adapter_data_source", diff --git a/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetScreenshotTest.kt b/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetScreenshotTest.kt index ee1d9459610..cda32cd0427 100644 --- a/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetScreenshotTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetScreenshotTest.kt @@ -376,7 +376,7 @@ internal class CustomerSheetScreenshotTest { ): CustomerSheetViewState { return CustomerSheetViewState.UpdatePaymentMethod( updatePaymentMethodInteractor = DefaultUpdatePaymentMethodInteractor( - canUpdateFullPaymentMethodDetails = false, + canUpdateCardPaymentMethodDetails = false, displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), removeExecutor = { null }, updatePaymentMethodExecutor = { paymentMethod, _ -> Result.success(paymentMethod) }, diff --git a/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetViewModelTest.kt b/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetViewModelTest.kt index 151aef17a25..d155557b453 100644 --- a/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetViewModelTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetViewModelTest.kt @@ -520,7 +520,7 @@ class CustomerSheetViewModelTest { customerPermissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.Full, canRemoveLastPaymentMethod = false, - canUpdateFullPaymentMethodDetails = false, + canUpdateCardPaymentMethodDetails = false, ) ) viewModel.viewState.test { @@ -553,14 +553,14 @@ class CustomerSheetViewModelTest { } @Test - fun `When canUpdateFullPaymentMethodDetails=true, showEditMenu should be true`() = runTest(testDispatcher) { + fun `When canUpdateCardPaymentMethodDetails=true, showEditMenu should be true`() = runTest(testDispatcher) { val viewModel = createViewModel( workContext = testDispatcher, customerPaymentMethods = listOf(CARD_PAYMENT_METHOD), customerPermissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.None, canRemoveLastPaymentMethod = false, - canUpdateFullPaymentMethodDetails = true, + canUpdateCardPaymentMethodDetails = true, ) ) viewModel.viewState.test { @@ -576,14 +576,14 @@ class CustomerSheetViewModelTest { } @Test - fun `When canUpdateFullPaymentMethodDetails=false, showEditMenu should be false`() = runTest(testDispatcher) { + fun `When canUpdateCardPaymentMethodDetails=false, showEditMenu should be false`() = runTest(testDispatcher) { val viewModel = createViewModel( workContext = testDispatcher, customerPaymentMethods = listOf(CARD_PAYMENT_METHOD), customerPermissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.None, canRemoveLastPaymentMethod = false, - canUpdateFullPaymentMethodDetails = false, + canUpdateCardPaymentMethodDetails = false, ) ) viewModel.viewState.test { @@ -598,7 +598,7 @@ class CustomerSheetViewModelTest { } @Test - fun `When canUpdateFullPaymentMethodDetails=false, card is cbc eligible, showEditMenu should be true`() = + fun `When canUpdateCardPaymentMethodDetails=false, card is cbc eligible, showEditMenu should be true`() = runTest(testDispatcher) { val viewModel = createViewModel( workContext = testDispatcher, @@ -606,7 +606,7 @@ class CustomerSheetViewModelTest { customerPermissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.None, canRemoveLastPaymentMethod = false, - canUpdateFullPaymentMethodDetails = false, + canUpdateCardPaymentMethodDetails = false, ), cbcEligibility = CardBrandChoiceEligibility.Eligible( preferredNetworks = listOf(CardBrand.CartesBancaires) @@ -2911,7 +2911,7 @@ class CustomerSheetViewModelTest { permissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.Full, canRemoveLastPaymentMethod = false, - canUpdateFullPaymentMethodDetails = false, + canUpdateCardPaymentMethodDetails = false, ) ) @@ -3051,7 +3051,7 @@ class CustomerSheetViewModelTest { customerPermissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.Full, canRemoveLastPaymentMethod = true, - canUpdateFullPaymentMethodDetails = true, + canUpdateCardPaymentMethodDetails = true, ), ) @@ -3070,7 +3070,7 @@ class CustomerSheetViewModelTest { customerPermissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.None, canRemoveLastPaymentMethod = false, - canUpdateFullPaymentMethodDetails = false + canUpdateCardPaymentMethodDetails = false ), ) @@ -3089,7 +3089,7 @@ class CustomerSheetViewModelTest { customerPermissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.Partial, canRemoveLastPaymentMethod = true, - canUpdateFullPaymentMethodDetails = true, + canUpdateCardPaymentMethodDetails = true, ), ) @@ -3112,7 +3112,7 @@ class CustomerSheetViewModelTest { customerPermissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.None, canRemoveLastPaymentMethod = false, - canUpdateFullPaymentMethodDetails = true, + canUpdateCardPaymentMethodDetails = true, ), ) @@ -3132,7 +3132,7 @@ class CustomerSheetViewModelTest { customerPermissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.Full, canRemoveLastPaymentMethod = false, - canUpdateFullPaymentMethodDetails = false, + canUpdateCardPaymentMethodDetails = false, ), ) @@ -3155,7 +3155,7 @@ class CustomerSheetViewModelTest { customerPermissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.Full, canRemoveLastPaymentMethod = false, - canUpdateFullPaymentMethodDetails = true, + canUpdateCardPaymentMethodDetails = true, ), ) @@ -3642,7 +3642,7 @@ class CustomerSheetViewModelTest { permissions: CustomerPermissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.Full, canRemoveLastPaymentMethod = true, - canUpdateFullPaymentMethodDetails = true, + canUpdateCardPaymentMethodDetails = true, ) ): CustomerSheetViewModel { return createViewModel( diff --git a/paymentsheet/src/test/java/com/stripe/android/customersheet/data/CustomerAdapterDataSourceTest.kt b/paymentsheet/src/test/java/com/stripe/android/customersheet/data/CustomerAdapterDataSourceTest.kt index 486bf866318..10afda1f85c 100644 --- a/paymentsheet/src/test/java/com/stripe/android/customersheet/data/CustomerAdapterDataSourceTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/customersheet/data/CustomerAdapterDataSourceTest.kt @@ -533,7 +533,7 @@ class CustomerAdapterDataSourceTest { assertThat(customerSheetSession.paymentMethods).containsExactlyElementsIn(paymentMethods) assertThat(customerSheetSession.savedSelection).isEqualTo(SavedSelection.PaymentMethod(id = "pm_1")) assertThat(customerSheetSession.permissions.removePaymentMethod).isEqualTo(PaymentMethodRemovePermission.Full) - assertThat(customerSheetSession.permissions.canUpdateFullPaymentMethodDetails).isFalse() + assertThat(customerSheetSession.permissions.canUpdateCardPaymentMethodDetails).isFalse() assertThat(customerSheetSession.paymentMethodSaveConsentBehavior).isEqualTo( PaymentMethodSaveConsentBehavior.Legacy ) diff --git a/paymentsheet/src/test/java/com/stripe/android/customersheet/data/CustomerSessionInitializationDataSourceTest.kt b/paymentsheet/src/test/java/com/stripe/android/customersheet/data/CustomerSessionInitializationDataSourceTest.kt index c0b15ea38e4..b2604bc1812 100644 --- a/paymentsheet/src/test/java/com/stripe/android/customersheet/data/CustomerSessionInitializationDataSourceTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/customersheet/data/CustomerSessionInitializationDataSourceTest.kt @@ -124,7 +124,7 @@ class CustomerSessionInitializationDataSourceTest { } @Test - fun `on load, canUpdateFullPaymentMethodDetails should be enabled`() = runTest { + fun `on load, canUpdateCardPaymentMethodDetails should be enabled`() = runTest { val dataSource = createInitializationDataSource( elementsSessionManager = FakeCustomerSessionElementsSessionManager( customerSheetComponent = ElementsSession.Customer.Components.CustomerSheet.Disabled, @@ -134,7 +134,7 @@ class CustomerSessionInitializationDataSourceTest { val result = dataSource.loadCustomerSheetSession(createConfiguration()) val customerSheetSession = result.asSuccess().value - assertThat(customerSheetSession.permissions.canUpdateFullPaymentMethodDetails).isTrue() + assertThat(customerSheetSession.permissions.canUpdateCardPaymentMethodDetails).isTrue() } @Test diff --git a/paymentsheet/src/test/java/com/stripe/android/customersheet/state/DefaultCustomerSheetLoaderTest.kt b/paymentsheet/src/test/java/com/stripe/android/customersheet/state/DefaultCustomerSheetLoaderTest.kt index 68c26d82318..1e5f91852f0 100644 --- a/paymentsheet/src/test/java/com/stripe/android/customersheet/state/DefaultCustomerSheetLoaderTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/customersheet/state/DefaultCustomerSheetLoaderTest.kt @@ -789,7 +789,7 @@ internal class DefaultCustomerSheetLoaderTest { permissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.Full, canRemoveLastPaymentMethod = true, - canUpdateFullPaymentMethodDetails = true, + canUpdateCardPaymentMethodDetails = true, ), defaultPaymentMethodId = defaultPaymentMethodId, customerId = "unused_for_customer_adapter_data_source", diff --git a/paymentsheet/src/test/java/com/stripe/android/customersheet/utils/CustomerSheetTestHelper.kt b/paymentsheet/src/test/java/com/stripe/android/customersheet/utils/CustomerSheetTestHelper.kt index a96d2eb52ad..2bc55037779 100644 --- a/paymentsheet/src/test/java/com/stripe/android/customersheet/utils/CustomerSheetTestHelper.kt +++ b/paymentsheet/src/test/java/com/stripe/android/customersheet/utils/CustomerSheetTestHelper.kt @@ -66,7 +66,7 @@ internal object CustomerSheetTestHelper { customerPermissions: CustomerPermissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.Full, canRemoveLastPaymentMethod = true, - canUpdateFullPaymentMethodDetails = true, + canUpdateCardPaymentMethodDetails = true, ), cbcEligibility: CardBrandChoiceEligibility = CardBrandChoiceEligibility.Ineligible, supportedPaymentMethods: List = listOf( diff --git a/paymentsheet/src/test/java/com/stripe/android/customersheet/utils/FakeCustomerSheetLoader.kt b/paymentsheet/src/test/java/com/stripe/android/customersheet/utils/FakeCustomerSheetLoader.kt index 2fa69a2c75f..598e8c2a377 100644 --- a/paymentsheet/src/test/java/com/stripe/android/customersheet/utils/FakeCustomerSheetLoader.kt +++ b/paymentsheet/src/test/java/com/stripe/android/customersheet/utils/FakeCustomerSheetLoader.kt @@ -38,7 +38,7 @@ internal class FakeCustomerSheetLoader( private val permissions: CustomerPermissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.Full, canRemoveLastPaymentMethod = true, - canUpdateFullPaymentMethodDetails = true, + canUpdateCardPaymentMethodDetails = true, ), private val isPaymentMethodSyncDefaultEnabled: Boolean = false, private val passiveCaptchaParams: PassiveCaptchaParams? = null, diff --git a/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadataTest.kt b/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadataTest.kt index b3cdbe1969b..9e67e0ed6a7 100644 --- a/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadataTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadataTest.kt @@ -326,7 +326,7 @@ internal class CustomerMetadataTest { permissions = CustomerPermissions( removePaymentMethod = removePermission, canRemoveLastPaymentMethod = true, - canUpdateFullPaymentMethodDetails = true + canUpdateCardPaymentMethodDetails = true ), defaultPaymentMethodId = null, customerId = "unused_for_customer_adapter_data_source", 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 4ad726189e1..aef54707a32 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 @@ -59,7 +59,7 @@ internal object PaymentMethodMetadataFactory { saveConsent: PaymentMethodSaveConsentBehavior = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod: Boolean = true, - canUpdateFullPaymentMethodDetails: Boolean = false, + canUpdateCardPaymentMethodDetails: Boolean = false, customerSessionClientSecret: String? = null, termsDisplay: Map = emptyMap(), forceSetupFutureUseBehaviorAndNewMandate: Boolean = false, @@ -105,7 +105,7 @@ internal object PaymentMethodMetadataFactory { removePaymentMethod = removePaymentMethod, saveConsent = saveConsent, canRemoveLastPaymentMethod = canRemoveLastPaymentMethod, - canUpdateFullPaymentMethodDetails = canUpdateFullPaymentMethodDetails, + canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, ) } else { CustomerMetadata.LegacyEphemeralKey( @@ -115,7 +115,7 @@ internal object PaymentMethodMetadataFactory { removePaymentMethod = removePaymentMethod, saveConsent = saveConsent, canRemoveLastPaymentMethod = canRemoveLastPaymentMethod, - canUpdateFullPaymentMethodDetails = canUpdateFullPaymentMethodDetails, + canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, ) } } else { diff --git a/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/PaymentMethodMetadataFixtures.kt b/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/PaymentMethodMetadataFixtures.kt index 30ed1be57a0..ee311ed27ec 100644 --- a/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/PaymentMethodMetadataFixtures.kt +++ b/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/PaymentMethodMetadataFixtures.kt @@ -16,7 +16,7 @@ internal object PaymentMethodMetadataFixtures { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, - canUpdateFullPaymentMethodDetails = false, + canUpdateCardPaymentMethodDetails = false, ) internal val DEFAULT_CUSTOMER_INTEGRATION_METADATA = IntegrationMetadata.CustomerSheet( @@ -38,7 +38,7 @@ internal object PaymentMethodMetadataFixtures { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, - canUpdateFullPaymentMethodDetails = false, + canUpdateCardPaymentMethodDetails = false, ) internal fun getDefaultCustomerMetadata( @@ -47,7 +47,7 @@ internal object PaymentMethodMetadataFixtures { removePaymentMethod: PaymentMethodRemovePermission = PaymentMethodRemovePermission.Full, saveConsent: PaymentMethodSaveConsentBehavior = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod: Boolean = true, - canUpdateFullPaymentMethodDetails: Boolean = false, + canUpdateCardPaymentMethodDetails: Boolean = false, ): CustomerMetadata? { return if (hasCustomerConfiguration) { DEFAULT_CUSTOMER_METADATA.copy( @@ -55,7 +55,7 @@ internal object PaymentMethodMetadataFixtures { removePaymentMethod = removePaymentMethod, saveConsent = saveConsent, canRemoveLastPaymentMethod = canRemoveLastPaymentMethod, - canUpdateFullPaymentMethodDetails = canUpdateFullPaymentMethodDetails, + canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, ) } else { null @@ -68,7 +68,7 @@ internal object PaymentMethodMetadataFixtures { removePaymentMethod: PaymentMethodRemovePermission = PaymentMethodRemovePermission.Full, saveConsent: PaymentMethodSaveConsentBehavior = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod: Boolean = true, - canUpdateFullPaymentMethodDetails: Boolean = false, + canUpdateCardPaymentMethodDetails: Boolean = false, ): StateFlow { return stateFlowOf( getDefaultCustomerMetadata( @@ -77,7 +77,7 @@ internal object PaymentMethodMetadataFixtures { removePaymentMethod = removePaymentMethod, saveConsent = saveConsent, canRemoveLastPaymentMethod = canRemoveLastPaymentMethod, - canUpdateFullPaymentMethodDetails = canUpdateFullPaymentMethodDetails, + canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, ) ) } diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/sheet/EmbeddedSheetActivityTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/sheet/EmbeddedSheetActivityTest.kt index 97acacd45fb..d8d9e244dcc 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/sheet/EmbeddedSheetActivityTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/sheet/EmbeddedSheetActivityTest.kt @@ -214,7 +214,7 @@ internal class EmbeddedSheetActivityTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, - canUpdateFullPaymentMethodDetails = false, + canUpdateCardPaymentMethodDetails = false, integrationMetadata = IntegrationMetadata.CheckoutSession( id = "cs_test", instancesKey = CheckoutStateFactory.DEFAULT_KEY, @@ -242,7 +242,7 @@ internal class EmbeddedSheetActivityTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, - canUpdateFullPaymentMethodDetails = false, + canUpdateCardPaymentMethodDetails = false, ), paymentMethods: List = defaultPaymentMethods(), selection: PaymentSelection? = null, diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/DefaultCustomerStateHolderTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/DefaultCustomerStateHolderTest.kt index 457da8e1432..d18a2a176d2 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/DefaultCustomerStateHolderTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/DefaultCustomerStateHolderTest.kt @@ -477,7 +477,7 @@ internal class DefaultCustomerStateHolderTest { removePaymentMethod = paymentMethodRemovePermission, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = canRemoveLastPaymentMethod, - canUpdateFullPaymentMethodDetails = false, + canUpdateCardPaymentMethodDetails = false, ) ) diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/FakeCustomerStateHolder.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/FakeCustomerStateHolder.kt index 7c8958e0b01..7d9969dbbbf 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/FakeCustomerStateHolder.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/FakeCustomerStateHolder.kt @@ -20,7 +20,7 @@ internal class FakeCustomerStateHolder : CustomerStateHolder { override val canRemove: StateFlow get() = stateFlowOf(false) - override val canUpdateFullPaymentMethodDetails: StateFlow + override val canUpdateCardPaymentMethodDetails: StateFlow get() = stateFlowOf(false) val setCustomerStateCalls = Turbine() diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/SavedPaymentMethodMutatorTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/SavedPaymentMethodMutatorTest.kt index 2d09d04d333..36e073acf74 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/SavedPaymentMethodMutatorTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/SavedPaymentMethodMutatorTest.kt @@ -58,7 +58,7 @@ class SavedPaymentMethodMutatorTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, - canUpdateFullPaymentMethodDetails = false, + canUpdateCardPaymentMethodDetails = false, ) ) { savedPaymentMethodMutator.canEdit.test { @@ -80,7 +80,7 @@ class SavedPaymentMethodMutatorTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = false, - canUpdateFullPaymentMethodDetails = false, + canUpdateCardPaymentMethodDetails = false, ) ) { savedPaymentMethodMutator.canEdit.test { @@ -237,7 +237,7 @@ class SavedPaymentMethodMutatorTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, - canUpdateFullPaymentMethodDetails = false, + canUpdateCardPaymentMethodDetails = false, ) ) { val customerPaymentMethods = PaymentMethodFixtures.createCards(1) @@ -267,7 +267,7 @@ class SavedPaymentMethodMutatorTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, - canUpdateFullPaymentMethodDetails = true, + canUpdateCardPaymentMethodDetails = true, ) ) { val cards = PaymentMethodFixtures.createCards(3) @@ -293,7 +293,7 @@ class SavedPaymentMethodMutatorTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = false, - canUpdateFullPaymentMethodDetails = true, + canUpdateCardPaymentMethodDetails = true, ) ) { val cards = PaymentMethodFixtures.createCards(1) diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/repositories/DefaultSavedPaymentMethodRepositoryTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/repositories/DefaultSavedPaymentMethodRepositoryTest.kt index cad10a78230..d8ffd34a001 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/repositories/DefaultSavedPaymentMethodRepositoryTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/repositories/DefaultSavedPaymentMethodRepositoryTest.kt @@ -294,7 +294,7 @@ class DefaultSavedPaymentMethodRepositoryTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, - canUpdateFullPaymentMethodDetails = false, + canUpdateCardPaymentMethodDetails = false, ) private val LEGACY_METADATA = CustomerMetadata.LegacyEphemeralKey( @@ -304,7 +304,8 @@ class DefaultSavedPaymentMethodRepositoryTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, - canUpdateFullPaymentMethodDetails = false, + canUpdateCardPaymentMethodDetails = false, ) + } } diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/CreateCustomerStateTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/CreateCustomerStateTest.kt index 03c39caf06c..671d2ae1f71 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/CreateCustomerStateTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/CreateCustomerStateTest.kt @@ -272,7 +272,7 @@ internal class CreateCustomerStateTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Enabled, canRemoveLastPaymentMethod = true, - canUpdateFullPaymentMethodDetails = true, + canUpdateCardPaymentMethodDetails = true, ) val LEGACY_EK_METADATA = CustomerMetadata.LegacyEphemeralKey( @@ -282,7 +282,7 @@ internal class CreateCustomerStateTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, - canUpdateFullPaymentMethodDetails = false, + canUpdateCardPaymentMethodDetails = false, ) fun createElementsSessionCustomer( diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultAnalyticsMetadataFactoryTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultAnalyticsMetadataFactoryTest.kt index 338b4bfc026..55c4d001690 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultAnalyticsMetadataFactoryTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultAnalyticsMetadataFactoryTest.kt @@ -839,7 +839,7 @@ class DefaultAnalyticsMetadataFactoryTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, - canUpdateFullPaymentMethodDetails = true, + canUpdateCardPaymentMethodDetails = true, ) private fun createElementsSessionCustomer(): ElementsSession.Customer { 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 27904311cd8..a3602a625a7 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 @@ -165,7 +165,7 @@ internal class DefaultPaymentElementLoaderTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, - canUpdateFullPaymentMethodDetails = false, + canUpdateCardPaymentMethodDetails = false, clientAttributionMetadata = ClientAttributionMetadata( elementsSessionConfigId = DEFAULT_ELEMENTS_SESSION_CONFIG_ID, paymentIntentCreationFlow = PaymentIntentCreationFlow.Standard, @@ -2850,7 +2850,7 @@ internal class DefaultPaymentElementLoaderTest { .isEqualTo(PaymentMethodSaveConsentBehavior.Disabled(overrideAllowRedisplay = null)) assertThat(state.paymentMethodMetadata.customerMetadata?.canRemoveLastPaymentMethod) .isEqualTo(true) - assertThat(state.paymentMethodMetadata.customerMetadata?.canUpdateFullPaymentMethodDetails) + assertThat(state.paymentMethodMetadata.customerMetadata?.canUpdateCardPaymentMethodDetails) .isEqualTo(true) consumeLoadingEvents() @@ -2901,7 +2901,7 @@ internal class DefaultPaymentElementLoaderTest { .isEqualTo(PaymentMethodSaveConsentBehavior.Disabled(overrideAllowRedisplay = null)) assertThat(state.paymentMethodMetadata.customerMetadata?.canRemoveLastPaymentMethod) .isEqualTo(true) - assertThat(state.paymentMethodMetadata.customerMetadata?.canUpdateFullPaymentMethodDetails) + assertThat(state.paymentMethodMetadata.customerMetadata?.canUpdateCardPaymentMethodDetails) .isEqualTo(true) consumeLoadingEvents() @@ -2952,7 +2952,7 @@ internal class DefaultPaymentElementLoaderTest { .isEqualTo(PaymentMethodSaveConsentBehavior.Disabled(overrideAllowRedisplay = null)) assertThat(state.paymentMethodMetadata.customerMetadata?.canRemoveLastPaymentMethod) .isEqualTo(true) - assertThat(state.paymentMethodMetadata.customerMetadata?.canUpdateFullPaymentMethodDetails) + assertThat(state.paymentMethodMetadata.customerMetadata?.canUpdateCardPaymentMethodDetails) .isEqualTo(true) consumeLoadingEvents() @@ -3003,7 +3003,7 @@ internal class DefaultPaymentElementLoaderTest { .isEqualTo(PaymentMethodSaveConsentBehavior.Disabled(overrideAllowRedisplay = null)) assertThat(state.paymentMethodMetadata.customerMetadata?.canRemoveLastPaymentMethod) .isEqualTo(true) - assertThat(state.paymentMethodMetadata.customerMetadata?.canUpdateFullPaymentMethodDetails) + assertThat(state.paymentMethodMetadata.customerMetadata?.canUpdateCardPaymentMethodDetails) .isEqualTo(true) consumeLoadingEvents() @@ -3013,7 +3013,7 @@ internal class DefaultPaymentElementLoaderTest { } @Test - fun `customer session should have canUpdateFullPaymentMethodDetails permission enabled`() = + fun `customer session should have canUpdateCardPaymentMethodDetails permission enabled`() = runScenario { val loader = createPaymentElementLoader( customer = createElementsSessionCustomer( @@ -3054,7 +3054,7 @@ internal class DefaultPaymentElementLoaderTest { .isEqualTo(PaymentMethodSaveConsentBehavior.Disabled(overrideAllowRedisplay = null)) assertThat(state.paymentMethodMetadata.customerMetadata?.canRemoveLastPaymentMethod) .isEqualTo(true) - assertThat(state.paymentMethodMetadata.customerMetadata?.canUpdateFullPaymentMethodDetails) + assertThat(state.paymentMethodMetadata.customerMetadata?.canUpdateCardPaymentMethodDetails) .isEqualTo(true) consumeLoadingEvents() @@ -3088,7 +3088,7 @@ internal class DefaultPaymentElementLoaderTest { .isEqualTo(PaymentMethodSaveConsentBehavior.Legacy) assertThat(state.paymentMethodMetadata.customerMetadata?.canRemoveLastPaymentMethod) .isEqualTo(true) - assertThat(state.paymentMethodMetadata.customerMetadata?.canUpdateFullPaymentMethodDetails) + assertThat(state.paymentMethodMetadata.customerMetadata?.canUpdateCardPaymentMethodDetails) .isEqualTo(false) consumeLoadingEvents() diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultPaymentMethodFilterTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultPaymentMethodFilterTest.kt index 120364f2eff..667e9faaf08 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultPaymentMethodFilterTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultPaymentMethodFilterTest.kt @@ -216,7 +216,7 @@ class DefaultPaymentMethodFilterTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = false, - canUpdateFullPaymentMethodDetails = false, + canUpdateCardPaymentMethodDetails = false, ), remoteDefaultPaymentMethodId = remoteDefaultPaymentMethodId, localSavedSelection = CompletableDeferred(localSavedSelection), diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultRetrieveCustomerEmailTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultRetrieveCustomerEmailTest.kt index bb26666b303..58d18f65de8 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultRetrieveCustomerEmailTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultRetrieveCustomerEmailTest.kt @@ -157,7 +157,7 @@ internal class DefaultRetrieveCustomerEmailTest { removePaymentMethod = PaymentMethodRemovePermission.None, saveConsent = PaymentMethodSaveConsentBehavior.Disabled(overrideAllowRedisplay = null), canRemoveLastPaymentMethod = false, - canUpdateFullPaymentMethodDetails = false, + canUpdateCardPaymentMethodDetails = false, ) val LEGACY_EK_METADATA = CustomerMetadata.LegacyEphemeralKey( @@ -167,7 +167,7 @@ internal class DefaultRetrieveCustomerEmailTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, - canUpdateFullPaymentMethodDetails = false, + canUpdateCardPaymentMethodDetails = false, ) val CHECKOUT_SESSION_METADATA = CustomerMetadata.CheckoutSession( diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/DefaultUpdatePaymentMethodInteractorTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/DefaultUpdatePaymentMethodInteractorTest.kt index 9a331aab4a2..f2f8390b3c7 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/DefaultUpdatePaymentMethodInteractorTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/DefaultUpdatePaymentMethodInteractorTest.kt @@ -516,12 +516,12 @@ class DefaultUpdatePaymentMethodInteractorTest { } @Test - fun shouldCreateEditCardInteractorCorrectly_whenCbcEligible_andCanUpdateFullPaymentMethodDetails() { + fun shouldCreateEditCardInteractorCorrectly_whenCbcEligible_andCanUpdateCardPaymentMethodDetails() { val displayableSavedPaymentMethod = PaymentMethodFixtures.CARD_WITH_NETWORKS_PAYMENT_METHOD .toDisplayableSavedPaymentMethod() runScenario( displayableSavedPaymentMethod = displayableSavedPaymentMethod, - canUpdateFullPaymentMethodDetails = true + canUpdateCardPaymentMethodDetails = true ) { val state = interactor.editCardDetailsInteractor.state.value assertThat(state.cardDetailsState?.shouldShowCardBrandDropdown).isTrue() @@ -531,12 +531,12 @@ class DefaultUpdatePaymentMethodInteractorTest { } @Test - fun shouldCreateEditCardInteractorCorrectly_whenCbcEligible_andCanNotUpdateFullPaymentMethodDetails() { + fun shouldCreateEditCardInteractorCorrectly_whenCbcEligible_andCanNotUpdateCardPaymentMethodDetails() { val displayableSavedPaymentMethod = PaymentMethodFixtures.CARD_WITH_NETWORKS_PAYMENT_METHOD .toDisplayableSavedPaymentMethod() runScenario( displayableSavedPaymentMethod = displayableSavedPaymentMethod, - canUpdateFullPaymentMethodDetails = false + canUpdateCardPaymentMethodDetails = false ) { val state = interactor.editCardDetailsInteractor.state.value assertThat(state.cardDetailsState?.shouldShowCardBrandDropdown).isTrue() @@ -546,9 +546,9 @@ class DefaultUpdatePaymentMethodInteractorTest { } @Test - fun shouldCreateEditCardInteractorCorrectly_whenCbcIneligible_andCanUpdateFullPaymentMethodDetails() { + fun shouldCreateEditCardInteractorCorrectly_whenCbcIneligible_andCanUpdateCardPaymentMethodDetails() { runScenario( - canUpdateFullPaymentMethodDetails = true + canUpdateCardPaymentMethodDetails = true ) { val state = interactor.editCardDetailsInteractor.state.value assertThat(state.cardDetailsState?.shouldShowCardBrandDropdown).isFalse() @@ -558,9 +558,9 @@ class DefaultUpdatePaymentMethodInteractorTest { } @Test - fun shouldCreateEditCardInteractorCorrectly_whenCbcIneligible_andCanNotUpdateFullPaymentMethodDetails() { + fun shouldCreateEditCardInteractorCorrectly_whenCbcIneligible_andCanNotUpdateCardPaymentMethodDetails() { runScenario( - canUpdateFullPaymentMethodDetails = false + canUpdateCardPaymentMethodDetails = false ) { val state = interactor.editCardDetailsInteractor.state.value assertThat(state.cardDetailsState?.shouldShowCardBrandDropdown).isFalse() @@ -711,7 +711,7 @@ class DefaultUpdatePaymentMethodInteractorTest { onSetDefaultPaymentMethod: (PaymentMethod) -> Result = { _ -> notImplemented() }, shouldShowSetAsDefaultCheckbox: Boolean = false, isDefaultPaymentMethod: Boolean = false, - canUpdateFullPaymentMethodDetails: Boolean = false, + canUpdateCardPaymentMethodDetails: Boolean = false, addressCollectionMode: AddressCollectionMode = AddressCollectionMode.Automatic, allowedBillingCountries: Set = setOf("US", "CA"), editCardDetailsInteractorFactory: EditCardDetailsInteractor.Factory = DefaultEditCardDetailsInteractor @@ -723,7 +723,7 @@ class DefaultUpdatePaymentMethodInteractorTest { val interactor = DefaultUpdatePaymentMethodInteractor( isLiveMode = isLiveMode, canRemove = canRemove, - canUpdateFullPaymentMethodDetails = canUpdateFullPaymentMethodDetails, + canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, displayableSavedPaymentMethod = displayableSavedPaymentMethod, addressCollectionMode = addressCollectionMode, removeExecutor = onRemovePaymentMethod, diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/FakeUpdatePaymentMethodInteractor.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/FakeUpdatePaymentMethodInteractor.kt index 98e6c945033..8ecdbf2a058 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/FakeUpdatePaymentMethodInteractor.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/FakeUpdatePaymentMethodInteractor.kt @@ -9,8 +9,6 @@ import com.stripe.android.paymentsheet.DisplayableSavedPaymentMethod import com.stripe.android.paymentsheet.PaymentSheet import com.stripe.android.paymentsheet.PaymentSheet.BillingDetailsCollectionConfiguration.AddressCollectionMode import com.stripe.android.paymentsheet.ViewActionRecorder -import com.stripe.android.paymentsheet.canChangeCbc -import com.stripe.android.paymentsheet.isModifiable import com.stripe.android.testing.PaymentMethodFactory import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -38,7 +36,7 @@ internal class FakeUpdatePaymentMethodInteractor( isSaveButtonEnabled = false, ), override val setAsDefaultCheckboxEnabled: Boolean = true, - override val canUpdateFullPaymentMethodDetails: Boolean = false, + override val canUpdateCardPaymentMethodDetails: Boolean = false, private val editCardDetailsInteractorFactory: EditCardDetailsInteractor.Factory = DefaultEditCardDetailsInteractor .Factory(), ) : UpdatePaymentMethodInteractor { @@ -47,18 +45,14 @@ internal class FakeUpdatePaymentMethodInteractor( displayableSavedPaymentMethod ) override val editCardDetailsInteractor: EditCardDetailsInteractor by lazy { - val isModifiable = displayableSavedPaymentMethod.paymentMethod.isModifiable( - canUpdateFullPaymentMethodDetails = canUpdateFullPaymentMethodDetails, - isCbcEligible = displayableSavedPaymentMethod.isCbcEligible, - ) + val isModifiable = + displayableSavedPaymentMethod.isModifiable(canUpdateCardPaymentMethodDetails) editCardDetailsInteractorFactory.create( coroutineScope = TestScope(), cardEditConfiguration = CardEditConfiguration( cardBrandFilter = cardBrandFilter, - isCbcModifiable = isModifiable && displayableSavedPaymentMethod.paymentMethod.canChangeCbc( - displayableSavedPaymentMethod.isCbcEligible - ), - areExpiryDateAndAddressModificationSupported = isModifiable && canUpdateFullPaymentMethodDetails + isCbcModifiable = isModifiable && displayableSavedPaymentMethod.canChangeCbc(), + areExpiryDateAndAddressModificationSupported = isModifiable && canUpdateCardPaymentMethodDetails ), requiresModification = true, payload = EditCardPayload.create( diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentSheetScreenUpdatePaymentMethodScreenshotTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentSheetScreenUpdatePaymentMethodScreenshotTest.kt index 248c1914502..68731462558 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentSheetScreenUpdatePaymentMethodScreenshotTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentSheetScreenUpdatePaymentMethodScreenshotTest.kt @@ -114,7 +114,7 @@ internal class PaymentSheetScreenUpdatePaymentMethodScreenshotTest { .toDisplayableSavedPaymentMethod(), canRemove = true, shouldShowSetAsDefaultCheckbox = true, - canUpdateFullPaymentMethodDetails = true, + canUpdateCardPaymentMethodDetails = true, addressCollectionMode = AddressCollectionMode.Automatic ) } @@ -130,7 +130,7 @@ internal class PaymentSheetScreenUpdatePaymentMethodScreenshotTest { isModifiablePaymentMethod = true, canRemove = true, shouldShowSetAsDefaultCheckbox = true, - canUpdateFullPaymentMethodDetails = true, + canUpdateCardPaymentMethodDetails = true, addressCollectionMode = AddressCollectionMode.Full, ) } @@ -146,7 +146,7 @@ internal class PaymentSheetScreenUpdatePaymentMethodScreenshotTest { isModifiablePaymentMethod = true, canRemove = true, shouldShowSetAsDefaultCheckbox = true, - canUpdateFullPaymentMethodDetails = true, + canUpdateCardPaymentMethodDetails = true, addressCollectionMode = AddressCollectionMode.Never, ) } @@ -162,7 +162,7 @@ internal class PaymentSheetScreenUpdatePaymentMethodScreenshotTest { isModifiablePaymentMethod = true, canRemove = true, shouldShowSetAsDefaultCheckbox = true, - canUpdateFullPaymentMethodDetails = true, + canUpdateCardPaymentMethodDetails = true, addressCollectionMode = AddressCollectionMode.Automatic, ) } @@ -178,7 +178,7 @@ internal class PaymentSheetScreenUpdatePaymentMethodScreenshotTest { isModifiablePaymentMethod = true, canRemove = true, shouldShowSetAsDefaultCheckbox = false, - canUpdateFullPaymentMethodDetails = true, + canUpdateCardPaymentMethodDetails = true, addressCollectionMode = AddressCollectionMode.Full, useDefaultBillingDetails = false, validating = true, @@ -204,7 +204,7 @@ internal class PaymentSheetScreenUpdatePaymentMethodScreenshotTest { isExpiredCard: Boolean = false, error: String? = null, shouldShowSetAsDefaultCheckbox: Boolean = false, - canUpdateFullPaymentMethodDetails: Boolean = false, + canUpdateCardPaymentMethodDetails: Boolean = false, addressCollectionMode: AddressCollectionMode = AddressCollectionMode.Never, useDefaultBillingDetails: Boolean = true, validating: Boolean = false, @@ -226,7 +226,7 @@ internal class PaymentSheetScreenUpdatePaymentMethodScreenshotTest { useDefaultBillingDetails = useDefaultBillingDetails, shouldShowSaveButton = isModifiablePaymentMethod || shouldShowSetAsDefaultCheckbox, addressCollectionMode = addressCollectionMode, - canUpdateFullPaymentMethodDetails = canUpdateFullPaymentMethodDetails + canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails ).apply { if (validating) { editCardDetailsInteractor.handleViewAction(EditCardDetailsInteractor.ViewAction.Validate) 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 ff7cd0756e1..a5634e0a804 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 @@ -1812,7 +1812,7 @@ class DefaultPaymentMethodVerticalLayoutInteractorTest { formTypeForCode: (code: String) -> FormHelper.FormType = { FormHelper.FormType.Empty }, initialPaymentMethods: List = emptyList(), initialMostRecentlySelectedSavedPaymentMethod: PaymentMethod? = null, - canUpdateFullPaymentMethodDetails: Boolean = false, + canUpdateCardPaymentMethodDetails: Boolean = false, shouldUpdateVerticalModeSelection: (String?) -> Boolean = { paymentMethodCode -> val requiresFormScreen = paymentMethodCode != null && formTypeForCode(paymentMethodCode) == FormHelper.FormType.UserInteractionRequired @@ -1864,7 +1864,7 @@ class DefaultPaymentMethodVerticalLayoutInteractorTest { mostRecentlySelectedSavedPaymentMethod = mostRecentlySelectedSavedPaymentMethod, canRemove = canRemove, walletsState = walletsState, - canUpdateFullPaymentMethodDetails = stateFlowOf(canUpdateFullPaymentMethodDetails), + canUpdateCardPaymentMethodDetails = stateFlowOf(canUpdateCardPaymentMethodDetails), updateSelection = { paymentSelection, isFormScreen -> selection.value = paymentSelection updateSelectionTurbine.add(isFormScreen) From edeca9f898fc306f7188a26b132083f08299e19e Mon Sep 17 00:00:00 2001 From: Chengtin Tsai Date: Thu, 2 Jul 2026 14:33:11 -0700 Subject: [PATCH 2/7] Split saved card update capabilities Committed-By-Agent: codex Co-authored-by: codex Committed-By-Agent: codex Co-authored-by: codex Committed-By-Agent: codex Co-authored-by: codex --- .../customersheet/CustomerSheetViewModel.kt | 8 +- .../customersheet/CustomerSheetViewState.kt | 3 +- .../paymentmethod/CustomerMetadata.kt | 10 ++ .../embedded/content/EmbeddedContentHelper.kt | 1 + .../EmbeddedUpdateScreenInteractorFactory.kt | 1 + .../paymentsheet/CustomerStateHolder.kt | 2 + .../DefaultCustomerStateHolder.kt | 4 + .../DisplayableSavedPaymentMethod.kt | 6 +- .../SavedPaymentMethodEditability.kt | 4 +- .../paymentsheet/SavedPaymentMethodMutator.kt | 10 +- .../ui/UpdatePaymentMethodInteractor.kt | 17 ++- .../paymentsheet/ui/UpdatePaymentMethodUI.kt | 7 +- .../PaymentMethodVerticalLayoutInteractor.kt | 19 ++- .../paymentmethod/CustomerMetadataTest.kt | 13 ++ .../PaymentMethodMetadataFactory.kt | 2 + .../PaymentMethodMetadataFixtures.kt | 2 + .../embedded/manage/EmbeddedNavigatorTest.kt | 22 ++- .../manage/InitialManageScreenFactoryTest.kt | 1 + .../paymentsheet/FakeCustomerStateHolder.kt | 3 + .../PaymentOptionsStateFactoryTest.kt | 6 +- .../SavedPaymentMethodEditabilityTest.kt | 134 +++++++----------- ...DefaultSavedPaymentMethodRepositoryTest.kt | 3 +- .../state/CreateCustomerStateTest.kt | 2 + .../DefaultAnalyticsMetadataFactoryTest.kt | 1 + .../state/DefaultPaymentMethodFilterTest.kt | 1 + .../state/DefaultRetrieveCustomerEmailTest.kt | 2 + ...efaultUpdatePaymentMethodInteractorTest.kt | 97 ++++++++++--- .../ui/FakeUpdatePaymentMethodInteractor.kt | 12 +- ...ScreenUpdatePaymentMethodScreenshotTest.kt | 3 +- .../ui/UpdatePaymentMethodUIScreenshotTest.kt | 1 + .../ui/UpdatePaymentMethodUITest.kt | 1 + 31 files changed, 270 insertions(+), 128 deletions(-) diff --git a/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewModel.kt b/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewModel.kt index 1c00055c014..eda815a5445 100644 --- a/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewModel.kt +++ b/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewModel.kt @@ -571,6 +571,7 @@ internal class CustomerSheetViewModel( isLiveMode = isLiveMode, canRemove = customerState.canRemove, canUpdateCardPaymentMethodDetails = customerState.canUpdateCardPaymentMethodDetails, + canUpdateCardBrandChoice = true, displayableSavedPaymentMethod = paymentMethod, addressCollectionMode = configuration.billingDetailsCollectionConfiguration.address, allowedBillingCountries = @@ -1275,11 +1276,14 @@ internal class CustomerSheetViewModel( } val canUpdateCardPaymentMethodDetails = permissions.canUpdateCardPaymentMethodDetails - val cbcEligibility = metadata?.cbcEligibility ?: CardBrandChoiceEligibility.Ineligible val canEdit = canRemove || paymentMethods.any { method -> - isModifiable(method, cbcEligibility, canUpdateCardPaymentMethodDetails) + isModifiable( + paymentMethod = method, + cbcEligibility = cbcEligibility, + canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + ) } val canShowSavedPaymentMethods = paymentMethods.isNotEmpty() || shouldShowGooglePay(metadata) diff --git a/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewState.kt b/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewState.kt index 721bd2818ed..d8c8d80e046 100644 --- a/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewState.kt +++ b/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewState.kt @@ -144,10 +144,11 @@ internal sealed class CustomerSheetViewState( internal fun isModifiable( paymentMethod: PaymentMethod, cbcEligibility: CardBrandChoiceEligibility, - canUpdateCardPaymentMethodDetails: Boolean + canUpdateCardPaymentMethodDetails: Boolean, ): Boolean { return paymentMethod.isModifiable( canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardBrandChoice = true, isCbcEligible = cbcEligibility is CardBrandChoiceEligibility.Eligible, ) } diff --git a/paymentsheet/src/main/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadata.kt b/paymentsheet/src/main/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadata.kt index 7087b4fc394..f216bab8e7d 100644 --- a/paymentsheet/src/main/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadata.kt +++ b/paymentsheet/src/main/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadata.kt @@ -14,6 +14,7 @@ internal sealed class CustomerMetadata : Parcelable { abstract val saveConsent: PaymentMethodSaveConsentBehavior abstract val canRemoveLastPaymentMethod: Boolean abstract val canUpdateCardPaymentMethodDetails: Boolean + abstract val canUpdateCardBrandChoice: Boolean val canRemovePaymentMethods: Boolean get() = removePaymentMethod == PaymentMethodRemovePermission.Full || @@ -28,6 +29,7 @@ internal sealed class CustomerMetadata : Parcelable { override val saveConsent: PaymentMethodSaveConsentBehavior, override val canRemoveLastPaymentMethod: Boolean, override val canUpdateCardPaymentMethodDetails: Boolean, + override val canUpdateCardBrandChoice: Boolean, ) : CustomerMetadata() @Parcelize @@ -40,6 +42,7 @@ internal sealed class CustomerMetadata : Parcelable { override val saveConsent: PaymentMethodSaveConsentBehavior, override val canRemoveLastPaymentMethod: Boolean, override val canUpdateCardPaymentMethodDetails: Boolean, + override val canUpdateCardBrandChoice: Boolean, ) : CustomerMetadata() @Parcelize @@ -57,6 +60,9 @@ internal sealed class CustomerMetadata : Parcelable { // CheckoutSession card detail updates are wired in a separate change. override val canUpdateCardPaymentMethodDetails: Boolean get() = false + + // CheckoutSession doesn't support updating preferred card networks. + override val canUpdateCardBrandChoice: Boolean get() = false } companion object { @@ -113,6 +119,7 @@ internal sealed class CustomerMetadata : Parcelable { canRemoveLastPaymentMethod = canRemoveLastPaymentMethod, // Should always be enabled when using `customer_session` canUpdateCardPaymentMethodDetails = true, + canUpdateCardBrandChoice = true, ) } @@ -144,6 +151,7 @@ internal sealed class CustomerMetadata : Parcelable { */ canRemoveLastPaymentMethod = configuration.allowsRemovalOfLastSavedPaymentMethod, canUpdateCardPaymentMethodDetails = false, + canUpdateCardBrandChoice = true, ) } @@ -171,6 +179,7 @@ internal sealed class CustomerMetadata : Parcelable { saveConsent = saveConsent, canRemoveLastPaymentMethod = canRemoveLastPaymentMethod, canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardBrandChoice = true, ) } else { LegacyEphemeralKey( @@ -181,6 +190,7 @@ internal sealed class CustomerMetadata : Parcelable { saveConsent = saveConsent, canRemoveLastPaymentMethod = canRemoveLastPaymentMethod, canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardBrandChoice = true, ) } } diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/content/EmbeddedContentHelper.kt b/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/content/EmbeddedContentHelper.kt index e147b4ddb90..662c13396b3 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/content/EmbeddedContentHelper.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/content/EmbeddedContentHelper.kt @@ -253,6 +253,7 @@ internal class DefaultEmbeddedContentHelper @Inject constructor( mostRecentlySelectedSavedPaymentMethod = customerStateHolder.mostRecentlySelectedSavedPaymentMethod, canRemove = customerStateHolder.canRemove, canUpdateCardPaymentMethodDetails = customerStateHolder.canUpdateCardPaymentMethodDetails, + canUpdateCardBrandChoice = customerStateHolder.canUpdateCardBrandChoice, walletsState = walletsState, updateSelection = { updatedSelection, requiresConfirmation -> setSelection(updatedSelection) diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/manage/EmbeddedUpdateScreenInteractorFactory.kt b/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/manage/EmbeddedUpdateScreenInteractorFactory.kt index e794098039e..2c162045f45 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/manage/EmbeddedUpdateScreenInteractorFactory.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/manage/EmbeddedUpdateScreenInteractorFactory.kt @@ -34,6 +34,7 @@ internal class DefaultEmbeddedUpdateScreenInteractorFactory @Inject constructor( isLiveMode = paymentMethodMetadata.stripeIntent.isLiveMode, canRemove = customerStateHolder.canRemove.value, canUpdateCardPaymentMethodDetails = customerStateHolder.canUpdateCardPaymentMethodDetails.value, + canUpdateCardBrandChoice = customerStateHolder.canUpdateCardBrandChoice.value, displayableSavedPaymentMethod = displayableSavedPaymentMethod, cardBrandFilter = paymentMethodMetadata.cardBrandFilter, addressCollectionMode = paymentMethodMetadata.billingDetailsCollectionConfiguration.address, diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/CustomerStateHolder.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/CustomerStateHolder.kt index 1bfbc862468..48b44437e6a 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/CustomerStateHolder.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/CustomerStateHolder.kt @@ -23,6 +23,8 @@ internal interface CustomerStateHolder { val canUpdateCardPaymentMethodDetails: StateFlow + val canUpdateCardBrandChoice: StateFlow + fun setCustomerState(customerState: CustomerState?) fun setDefaultPaymentMethod(paymentMethod: PaymentMethod?) diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DefaultCustomerStateHolder.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DefaultCustomerStateHolder.kt index ff33631fdbf..57b2cd5d5c1 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DefaultCustomerStateHolder.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DefaultCustomerStateHolder.kt @@ -52,6 +52,10 @@ internal class DefaultCustomerStateHolder( it?.canUpdateCardPaymentMethodDetails ?: false } + override val canUpdateCardBrandChoice: StateFlow = customerMetadata.mapAsStateFlow { + it?.canUpdateCardBrandChoice ?: false + } + override fun setCustomerState(customerState: CustomerState?) { savedStateHandle[SAVED_CUSTOMER] = customerState diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethod.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethod.kt index b7187181f72..3e8c79cd960 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethod.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethod.kt @@ -31,9 +31,13 @@ internal data class DisplayableSavedPaymentMethod private constructor( return paymentMethod.canChangeCbc(isCbcEligible) } - fun isModifiable(canUpdateCardPaymentMethodDetails: Boolean): Boolean { + fun isModifiable( + canUpdateCardPaymentMethodDetails: Boolean, + canUpdateCardBrandChoice: Boolean, + ): Boolean { return paymentMethod.isModifiable( canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardBrandChoice = canUpdateCardBrandChoice, isCbcEligible = isCbcEligible, ) } diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodEditability.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodEditability.kt index ffd08064aeb..334d7645b61 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodEditability.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodEditability.kt @@ -5,11 +5,13 @@ import com.stripe.android.model.PaymentMethod internal fun PaymentMethod.isModifiable( canUpdateCardPaymentMethodDetails: Boolean, + canUpdateCardBrandChoice: Boolean, isCbcEligible: Boolean, ): Boolean { val card = editableSavedCard() ?: return false - return canUpdateCardPaymentMethodDetails || (card.isExpired().not() && canChangeCbc(isCbcEligible)) + return canUpdateCardPaymentMethodDetails || + (canUpdateCardBrandChoice && card.isExpired().not() && canChangeCbc(isCbcEligible)) } internal fun PaymentMethod.canChangeCbc(isCbcEligible: Boolean): Boolean { diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodMutator.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodMutator.kt index 977fcf887de..01947ace6bd 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodMutator.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodMutator.kt @@ -92,11 +92,14 @@ internal class SavedPaymentMethodMutator( val canEdit: StateFlow = combineAsStateFlow( customerStateHolder.canRemove, - paymentOptionsItems - ) { canRemove, items -> + paymentOptionsItems, + customerStateHolder.canUpdateCardPaymentMethodDetails, + customerStateHolder.canUpdateCardBrandChoice, + ) { canRemove, items, canUpdateCardPaymentMethodDetails, canUpdateCardBrandChoice -> canRemove || items.filterIsInstance().any { item -> item.displayableSavedPaymentMethod.isModifiable( - customerStateHolder.canUpdateCardPaymentMethodDetails.value + canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardBrandChoice = canUpdateCardBrandChoice, ) } } @@ -379,6 +382,7 @@ internal class SavedPaymentMethodMutator( canRemove = canRemove, canUpdateCardPaymentMethodDetails = viewModel.customerStateHolder .canUpdateCardPaymentMethodDetails.value, + canUpdateCardBrandChoice = viewModel.customerStateHolder.canUpdateCardBrandChoice.value, displayableSavedPaymentMethod = displayableSavedPaymentMethod, cardBrandFilter = PaymentSheetCardBrandFilter(viewModel.config.cardBrandAcceptance), addressCollectionMode = viewModel.config.billingDetailsCollectionConfiguration.address, diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodInteractor.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodInteractor.kt index 6400d63b95b..0f9242406bd 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodInteractor.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodInteractor.kt @@ -36,10 +36,12 @@ internal interface UpdatePaymentMethodInteractor { val isExpiredCard: Boolean val isModifiablePaymentMethod: Boolean val hasValidBrandChoices: Boolean + val shouldShowCardBrandDropdown: Boolean val shouldShowSetAsDefaultCheckbox: Boolean val setAsDefaultCheckboxEnabled: Boolean val shouldShowSaveButton: Boolean val canUpdateCardPaymentMethodDetails: Boolean + val canUpdateCardBrandChoice: Boolean val addressCollectionMode: AddressCollectionMode val allowedBillingCountries: Set val editCardDetailsInteractor: EditCardDetailsInteractor @@ -115,6 +117,7 @@ internal class DefaultUpdatePaymentMethodInteractor( override val addressCollectionMode: AddressCollectionMode, override val allowedBillingCountries: Set, override val canUpdateCardPaymentMethodDetails: Boolean, + override val canUpdateCardBrandChoice: Boolean, override val removeMessage: ResolvableString?, val isDefaultPaymentMethod: Boolean, override val shouldShowSetAsDefaultCheckbox: Boolean, @@ -140,7 +143,12 @@ internal class DefaultUpdatePaymentMethodInteractor( displayableSavedPaymentMethod ) override val isModifiablePaymentMethod: Boolean - get() = displayableSavedPaymentMethod.isModifiable(canUpdateCardPaymentMethodDetails) + get() = displayableSavedPaymentMethod.isModifiable( + canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardBrandChoice = canUpdateCardBrandChoice, + ) + override val shouldShowCardBrandDropdown: Boolean + get() = isModifiablePaymentMethod && canUpdateCardBrandChoice && displayableSavedPaymentMethod.canChangeCbc() override val topBarState: PaymentSheetTopBarState = PaymentSheetTopBarStateFactory.create( isLiveMode = isLiveMode, @@ -175,11 +183,14 @@ internal class DefaultUpdatePaymentMethodInteractor( private fun createEditCardDetailsInteractorForCard( savedPaymentMethodCard: SavedPaymentMethod.Card, ): EditCardDetailsInteractor { - val isModifiable = displayableSavedPaymentMethod.isModifiable(canUpdateCardPaymentMethodDetails) + val isModifiable = displayableSavedPaymentMethod.isModifiable( + canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardBrandChoice = canUpdateCardBrandChoice, + ) val payload = EditCardPayload.create(savedPaymentMethodCard.card, savedPaymentMethodCard.billingDetails) val cardEditConfiguration = CardEditConfiguration( cardBrandFilter = cardBrandFilter, - isCbcModifiable = isModifiable && displayableSavedPaymentMethod.canChangeCbc(), + isCbcModifiable = isModifiable && canUpdateCardBrandChoice && displayableSavedPaymentMethod.canChangeCbc(), areExpiryDateAndAddressModificationSupported = isModifiable && canUpdateCardPaymentMethodDetails, ) return editCardDetailsInteractorFactory.create( diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUI.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUI.kt index 9f31ec2f12f..9f920263b91 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUI.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUI.kt @@ -31,7 +31,6 @@ import com.stripe.android.model.PaymentMethod import com.stripe.android.paymentsheet.DisplayableSavedPaymentMethod import com.stripe.android.paymentsheet.PaymentSheet.BillingDetailsCollectionConfiguration.AddressCollectionMode import com.stripe.android.paymentsheet.SavedPaymentMethod -import com.stripe.android.paymentsheet.canChangeCbc import com.stripe.android.paymentsheet.utils.testMetadata import com.stripe.android.uicore.StripeTheme import com.stripe.android.uicore.elements.CheckboxElementUI @@ -48,10 +47,7 @@ internal fun UpdatePaymentMethodUI(interactor: UpdatePaymentMethodInteractor, mo val context = LocalContext.current val horizontalPadding = StripeTheme.getOuterFormInsets() val state by interactor.state.collectAsState() - val shouldShowCardBrandDropdown = interactor.isModifiablePaymentMethod && - interactor.displayableSavedPaymentMethod.paymentMethod.canChangeCbc( - interactor.displayableSavedPaymentMethod.isCbcEligible - ) + val shouldShowCardBrandDropdown = interactor.shouldShowCardBrandDropdown Column( modifier = modifier @@ -360,6 +356,7 @@ private fun PreviewUpdatePaymentMethodUI() { isLiveMode = false, canRemove = true, canUpdateCardPaymentMethodDetails = true, + canUpdateCardBrandChoice = true, displayableSavedPaymentMethod = exampleCard, addressCollectionMode = AddressCollectionMode.Automatic, allowedBillingCountries = emptySet(), 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 058544d0d49..669ff14c9a8 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 @@ -104,6 +104,7 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( private val canRemove: StateFlow, private val walletsState: StateFlow, private val canUpdateCardPaymentMethodDetails: StateFlow, + private val canUpdateCardBrandChoice: StateFlow, private val updateSelection: (PaymentSelection?, Boolean) -> Unit, private val isCurrentScreen: StateFlow, private val reportPaymentMethodTypeSelected: (PaymentMethodCode) -> Unit, @@ -179,6 +180,7 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( }, walletsState = viewModel.walletsState, canUpdateCardPaymentMethodDetails = viewModel.customerStateHolder.canUpdateCardPaymentMethodDetails, + canUpdateCardBrandChoice = viewModel.customerStateHolder.canUpdateCardBrandChoice, isCurrentScreen = isCurrentScreen, reportPaymentMethodTypeSelected = viewModel.eventReporter::onSelectPaymentMethod, reportFormShown = viewModel.eventReporter::onPaymentMethodFormShown, @@ -242,12 +244,18 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( displayedSavedPaymentMethod, canRemove, canUpdateCardPaymentMethodDetails, - ) { paymentMethods, displayedSavedPaymentMethod, canRemove, canUpdateCardPaymentMethodDetails -> + canUpdateCardBrandChoice, + ) { paymentMethods, + displayedSavedPaymentMethod, + canRemove, + canUpdateCardPaymentMethodDetails, + canUpdateCardBrandChoice -> getAvailableSavedPaymentMethodAction( paymentMethods = paymentMethods, savedPaymentMethod = displayedSavedPaymentMethod, canRemove = canRemove, canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardBrandChoice = canUpdateCardBrandChoice, ) } @@ -504,6 +512,7 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( savedPaymentMethod: DisplayableSavedPaymentMethod?, canRemove: Boolean, canUpdateCardPaymentMethodDetails: Boolean, + canUpdateCardBrandChoice: Boolean, ): PaymentMethodVerticalLayoutInteractor.SavedPaymentMethodAction { if (paymentMethods == null || savedPaymentMethod == null) { return PaymentMethodVerticalLayoutInteractor.SavedPaymentMethodAction.NONE @@ -516,6 +525,7 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( canRemove = canRemove, savedPaymentMethod = savedPaymentMethod, canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardBrandChoice = canUpdateCardBrandChoice, ) } else -> @@ -527,8 +537,13 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( canRemove: Boolean, savedPaymentMethod: DisplayableSavedPaymentMethod?, canUpdateCardPaymentMethodDetails: Boolean, + canUpdateCardBrandChoice: Boolean, ): PaymentMethodVerticalLayoutInteractor.SavedPaymentMethodAction { - return if (savedPaymentMethod?.isModifiable(canUpdateCardPaymentMethodDetails) == true || canRemove) { + return if (savedPaymentMethod?.isModifiable( + canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardBrandChoice = canUpdateCardBrandChoice, + ) == true || canRemove + ) { PaymentMethodVerticalLayoutInteractor.SavedPaymentMethodAction.MANAGE_ONE } else { PaymentMethodVerticalLayoutInteractor.SavedPaymentMethodAction.NONE diff --git a/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadataTest.kt b/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadataTest.kt index 9e67e0ed6a7..132906b4aaf 100644 --- a/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadataTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadataTest.kt @@ -17,6 +17,19 @@ import org.junit.Test internal class CustomerMetadataTest { + @Test + fun `CheckoutSession should support card details but not card brand updates`() { + val metadata = CustomerMetadata.CheckoutSession( + sessionId = "cs_123", + customerId = "cus_123", + removePaymentMethod = PaymentMethodRemovePermission.Full, + saveConsent = PaymentMethodSaveConsentBehavior.Legacy, + ) + + assertThat(metadata.canUpdateCardPaymentMethodDetails).isTrue() + assertThat(metadata.canUpdateCardBrandChoice).isFalse() + } + @Test fun `Should create 'Permissions' for customer session properly with permissions disabled`() { customerSessionPermissionsTest( 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 aef54707a32..9b1a1d1a500 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 @@ -106,6 +106,7 @@ internal object PaymentMethodMetadataFactory { saveConsent = saveConsent, canRemoveLastPaymentMethod = canRemoveLastPaymentMethod, canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardBrandChoice = true, ) } else { CustomerMetadata.LegacyEphemeralKey( @@ -116,6 +117,7 @@ internal object PaymentMethodMetadataFactory { saveConsent = saveConsent, canRemoveLastPaymentMethod = canRemoveLastPaymentMethod, canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardBrandChoice = true, ) } } else { diff --git a/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/PaymentMethodMetadataFixtures.kt b/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/PaymentMethodMetadataFixtures.kt index ee311ed27ec..b3834cd1312 100644 --- a/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/PaymentMethodMetadataFixtures.kt +++ b/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/PaymentMethodMetadataFixtures.kt @@ -17,6 +17,7 @@ internal object PaymentMethodMetadataFixtures { saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, canUpdateCardPaymentMethodDetails = false, + canUpdateCardBrandChoice = true, ) internal val DEFAULT_CUSTOMER_INTEGRATION_METADATA = IntegrationMetadata.CustomerSheet( @@ -39,6 +40,7 @@ internal object PaymentMethodMetadataFixtures { saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, canUpdateCardPaymentMethodDetails = false, + canUpdateCardBrandChoice = true, ) internal fun getDefaultCustomerMetadata( diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/manage/EmbeddedNavigatorTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/manage/EmbeddedNavigatorTest.kt index 916a7f0df99..b5bce360a16 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/manage/EmbeddedNavigatorTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/manage/EmbeddedNavigatorTest.kt @@ -39,7 +39,9 @@ internal class EmbeddedNavigatorTest { assertThat(awaitItem()).isEqualTo(initialScreen) assertThat(navigator.canGoBack).isFalse() - val newScreen = EmbeddedNavigator.Screen.ManageUpdate(FakeUpdatePaymentMethodInteractor()) + val newScreen = EmbeddedNavigator.Screen.ManageUpdate( + FakeUpdatePaymentMethodInteractor(canUpdateCardBrandChoice = true) + ) navigator.performAction(EmbeddedNavigator.Action.GoToScreen(newScreen)) assertThat(awaitItem()).isEqualTo(newScreen) assertThat(navigator.canGoBack).isTrue() @@ -63,7 +65,9 @@ internal class EmbeddedNavigatorTest { navigator.screen.test { assertThat(awaitItem()).isEqualTo(initialScreen) - val newScreen = EmbeddedNavigator.Screen.ManageUpdate(FakeUpdatePaymentMethodInteractor()) + val newScreen = EmbeddedNavigator.Screen.ManageUpdate( + FakeUpdatePaymentMethodInteractor(canUpdateCardBrandChoice = true) + ) navigator.performAction(EmbeddedNavigator.Action.GoToScreen(newScreen)) assertThat(awaitItem()).isEqualTo(newScreen) assertThat(eventReporter.showEditablePaymentOptionCalls.awaitItem()).isEqualTo(Unit) @@ -136,7 +140,9 @@ internal class EmbeddedNavigatorTest { @Test fun `Close while on ManageUpdate calls onHideEditablePaymentOption`() = testScenario { - val manageUpdateScreen = EmbeddedNavigator.Screen.ManageUpdate(FakeUpdatePaymentMethodInteractor()) + val manageUpdateScreen = EmbeddedNavigator.Screen.ManageUpdate( + FakeUpdatePaymentMethodInteractor(canUpdateCardBrandChoice = true) + ) navigator.screen.test { assertThat(awaitItem()).isEqualTo(initialScreen) navigator.performAction(EmbeddedNavigator.Action.GoToScreen(manageUpdateScreen)) @@ -154,7 +160,9 @@ internal class EmbeddedNavigatorTest { EmbeddedNavigator( coroutineScope = this, eventReporter = eventReporter, - initialScreen = EmbeddedNavigator.Screen.ManageUpdate(FakeUpdatePaymentMethodInteractor()), + initialScreen = EmbeddedNavigator.Screen.ManageUpdate( + FakeUpdatePaymentMethodInteractor(canUpdateCardBrandChoice = true) + ), ) assertThat(eventReporter.showEditablePaymentOptionCalls.awaitItem()).isEqualTo(Unit) eventReporter.validate() @@ -214,7 +222,7 @@ internal class EmbeddedNavigatorTest { @Test fun `ManageUpdate topBarState returns interactor topBarState`() { - val interactor = FakeUpdatePaymentMethodInteractor() + val interactor = FakeUpdatePaymentMethodInteractor(canUpdateCardBrandChoice = true) val screen = EmbeddedNavigator.Screen.ManageUpdate(interactor) val topBarState = screen.topBarState().value @@ -223,7 +231,7 @@ internal class EmbeddedNavigatorTest { @Test fun `ManageUpdate title returns interactor screenTitle`() { - val interactor = FakeUpdatePaymentMethodInteractor() + val interactor = FakeUpdatePaymentMethodInteractor(canUpdateCardBrandChoice = true) val screen = EmbeddedNavigator.Screen.ManageUpdate(interactor) val title = screen.title().value @@ -233,6 +241,7 @@ internal class EmbeddedNavigatorTest { @Test fun `ManageUpdate isPerformingNetworkOperation when idle returns false`() { val interactor = FakeUpdatePaymentMethodInteractor( + canUpdateCardBrandChoice = true, initialState = UpdatePaymentMethodInteractor.State( error = null, status = UpdatePaymentMethodInteractor.Status.Idle, @@ -247,6 +256,7 @@ internal class EmbeddedNavigatorTest { @Test fun `ManageUpdate isPerformingNetworkOperation when updating returns true`() { val interactor = FakeUpdatePaymentMethodInteractor( + canUpdateCardBrandChoice = true, initialState = UpdatePaymentMethodInteractor.State( error = null, status = UpdatePaymentMethodInteractor.Status.Updating, diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/manage/InitialManageScreenFactoryTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/manage/InitialManageScreenFactoryTest.kt index d8fe9ac5aae..5ed01c04c0e 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/manage/InitialManageScreenFactoryTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/manage/InitialManageScreenFactoryTest.kt @@ -57,6 +57,7 @@ internal class InitialManageScreenFactoryTest { FakeUpdatePaymentMethodInteractor( displayableSavedPaymentMethod = displayableSavedPaymentMethod, canRemove = customerStateHolder.canRemove.value, + canUpdateCardBrandChoice = true, isExpiredCard = false, isModifiablePaymentMethod = true, viewActionRecorder = ViewActionRecorder(), diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/FakeCustomerStateHolder.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/FakeCustomerStateHolder.kt index 7d9969dbbbf..53d2732f3ce 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/FakeCustomerStateHolder.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/FakeCustomerStateHolder.kt @@ -23,6 +23,9 @@ internal class FakeCustomerStateHolder : CustomerStateHolder { override val canUpdateCardPaymentMethodDetails: StateFlow get() = stateFlowOf(false) + override val canUpdateCardBrandChoice: StateFlow + get() = stateFlowOf(false) + val setCustomerStateCalls = Turbine() val setDefaultPaymentMethodCalls = Turbine() diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/PaymentOptionsStateFactoryTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/PaymentOptionsStateFactoryTest.kt index 802ac75641e..251578c0289 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/PaymentOptionsStateFactoryTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/PaymentOptionsStateFactoryTest.kt @@ -136,9 +136,9 @@ class PaymentOptionsStateFactoryTest { val displayableSavedPaymentMethod = (state.items.last() as PaymentOptionsItem.SavedPaymentMethod) .displayableSavedPaymentMethod assertThat( - displayableSavedPaymentMethod.paymentMethod.isModifiable( - canUpdateFullPaymentMethodDetails = canUpdatePaymentMethod, - isCbcEligible = displayableSavedPaymentMethod.isCbcEligible, + displayableSavedPaymentMethod.isModifiable( + canUpdateCardPaymentMethodDetails = canUpdatePaymentMethod, + canUpdateCardBrandChoice = true, ) ).isEqualTo(expectedResult) } diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/SavedPaymentMethodEditabilityTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/SavedPaymentMethodEditabilityTest.kt index 9a05b2b8447..3b02dcc3f7c 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/SavedPaymentMethodEditabilityTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/SavedPaymentMethodEditabilityTest.kt @@ -1,15 +1,16 @@ package com.stripe.android.paymentsheet import com.google.common.truth.Truth.assertThat -import com.google.common.truth.Truth.assertWithMessage +import com.stripe.android.core.strings.resolvableString import com.stripe.android.model.PaymentMethod import com.stripe.android.model.PaymentMethodFixtures +import junit.framework.TestCase.assertEquals import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.Parameterized @RunWith(Parameterized::class) -class SavedPaymentMethodEditabilityTest(private val params: IsModifiableParams) { +class DisplayableSavedPaymentMethodModifiableTest(private val params: IsModifiableParams) { @Test fun `test isModifiable logic`() { @@ -19,23 +20,56 @@ class SavedPaymentMethodEditabilityTest(private val params: IsModifiableParams) expiryYear = if (params.cardExpired) 2005 else 2099 ) ) + val displayableSavedPaymentMethod = DisplayableSavedPaymentMethod.create( + displayName = "unused".resolvableString, + paymentMethod = paymentMethod, + isCbcEligible = params.isCbcEligible, + ) - assertWithMessage( - "Expected isModifiable for parameters: " + + assertEquals( + "Expected isModifiable to be ${params.expectedResult} for parameters: " + "canUpdatePaymentMethod=${params.canUpdatePaymentMethod}, " + "isCbcEligible=${params.isCbcEligible}, " + "availableNetworks=${params.availableNetworks}, " + - "cardExpired=${params.cardExpired}" - ).that( + "cardExpired=${params.cardExpired}", + params.expectedResult, + displayableSavedPaymentMethod.isModifiable( + canUpdateCardPaymentMethodDetails = params.canUpdatePaymentMethod, + canUpdateCardBrandChoice = params.canUpdateCardBrandChoice, + ) + ) + + assertThat( + displayableSavedPaymentMethod.isModifiable( + canUpdateCardPaymentMethodDetails = params.canUpdatePaymentMethod, + canUpdateCardBrandChoice = params.canUpdateCardBrandChoice, + ) + ) + .isEqualTo(params.expectedResult) + + assertThat( paymentMethod.isModifiable( - canUpdateFullPaymentMethodDetails = params.canUpdatePaymentMethod, + canUpdateCardPaymentMethodDetails = params.canUpdatePaymentMethod, + canUpdateCardBrandChoice = params.canUpdateCardBrandChoice, isCbcEligible = params.isCbcEligible, ) ).isEqualTo(params.expectedResult) } + @Test + fun `isModifiable returns false for non-card payment methods`() { + assertThat( + PaymentMethodFixtures.LINK_PAYMENT_METHOD.isModifiable( + canUpdateCardPaymentMethodDetails = true, + canUpdateCardBrandChoice = true, + isCbcEligible = true, + ) + ).isFalse() + } + data class IsModifiableParams( val canUpdatePaymentMethod: Boolean = false, + val canUpdateCardBrandChoice: Boolean, val isCbcEligible: Boolean = false, val availableNetworks: Set = setOf("visa"), val cardExpired: Boolean = false, @@ -48,115 +82,57 @@ class SavedPaymentMethodEditabilityTest(private val params: IsModifiableParams) fun testCases() = listOf( IsModifiableParams( canUpdatePaymentMethod = true, - isCbcEligible = false, - availableNetworks = setOf("visa"), - cardExpired = false, + canUpdateCardBrandChoice = true, expectedResult = true ), IsModifiableParams( canUpdatePaymentMethod = true, - isCbcEligible = false, - availableNetworks = setOf("visa"), + canUpdateCardBrandChoice = true, cardExpired = true, expectedResult = true ), IsModifiableParams( canUpdatePaymentMethod = true, + canUpdateCardBrandChoice = true, isCbcEligible = true, availableNetworks = setOf("visa", "mastercard"), cardExpired = false, expectedResult = true ), IsModifiableParams( - canUpdatePaymentMethod = false, + canUpdateCardBrandChoice = true, isCbcEligible = true, availableNetworks = setOf("visa", "cartes_bancaires"), - cardExpired = false, expectedResult = true ), IsModifiableParams( - canUpdatePaymentMethod = false, - isCbcEligible = false, + canUpdateCardBrandChoice = false, + isCbcEligible = true, + availableNetworks = setOf("visa", "cartes_bancaires"), + expectedResult = false + ), + IsModifiableParams( + canUpdateCardBrandChoice = true, availableNetworks = setOf("visa", "cartes_bancaires"), - cardExpired = false, expectedResult = false ), IsModifiableParams( - canUpdatePaymentMethod = false, + canUpdateCardBrandChoice = true, isCbcEligible = true, - availableNetworks = setOf("visa"), - cardExpired = false, expectedResult = false ), IsModifiableParams( - canUpdatePaymentMethod = false, + canUpdateCardBrandChoice = true, isCbcEligible = true, availableNetworks = setOf("visa", "cartes_bancaires"), cardExpired = true, expectedResult = false ), IsModifiableParams( - canUpdatePaymentMethod = false, - isCbcEligible = false, - availableNetworks = setOf("visa"), + canUpdateCardBrandChoice = true, cardExpired = true, expectedResult = false ) ) } } - -class SavedPaymentMethodEditabilityStandaloneTest { - @Test - fun `canChangeCbc returns false for single network card when cbc eligible`() { - val paymentMethod = PaymentMethodFixtures.CARD_PAYMENT_METHOD.copy( - card = PaymentMethodFixtures.CARD_PAYMENT_METHOD.card?.copy( - networks = PaymentMethod.Card.Networks(setOf("visa")) - ) - ) - - assertThat(paymentMethod.canChangeCbc(isCbcEligible = true)).isFalse() - } - - @Test - fun `canChangeCbc returns false for multiple network card when cbc not eligible`() { - val paymentMethod = PaymentMethodFixtures.CARD_PAYMENT_METHOD.copy( - card = PaymentMethodFixtures.CARD_PAYMENT_METHOD.card?.copy( - networks = PaymentMethod.Card.Networks(setOf("visa", "cartes_bancaires")) - ) - ) - - assertThat(paymentMethod.canChangeCbc(isCbcEligible = false)).isFalse() - } - - @Test - fun `canChangeCbc returns true for multiple network card when cbc eligible`() { - val paymentMethod = PaymentMethodFixtures.CARD_PAYMENT_METHOD.copy( - card = PaymentMethodFixtures.CARD_PAYMENT_METHOD.card?.copy( - networks = PaymentMethod.Card.Networks(setOf("visa", "cartes_bancaires")) - ) - ) - - assertThat(paymentMethod.canChangeCbc(isCbcEligible = true)).isTrue() - } - - @Test - fun `canChangeCbc returns false for non-card payment methods`() { - assertThat(PaymentMethodFixtures.US_BANK_ACCOUNT.canChangeCbc(isCbcEligible = true)).isFalse() - } - - @Test - fun `isModifiable returns false for non-card payment methods`() { - listOf( - PaymentMethodFixtures.LINK_PAYMENT_METHOD, - PaymentMethodFixtures.US_BANK_ACCOUNT, - ).forEach { paymentMethod -> - assertThat( - paymentMethod.isModifiable( - canUpdateFullPaymentMethodDetails = true, - isCbcEligible = true, - ) - ).isFalse() - } - } -} diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/repositories/DefaultSavedPaymentMethodRepositoryTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/repositories/DefaultSavedPaymentMethodRepositoryTest.kt index d8ffd34a001..3a21f7501d7 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/repositories/DefaultSavedPaymentMethodRepositoryTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/repositories/DefaultSavedPaymentMethodRepositoryTest.kt @@ -295,6 +295,7 @@ class DefaultSavedPaymentMethodRepositoryTest { saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, canUpdateCardPaymentMethodDetails = false, + canUpdateCardBrandChoice = true, ) private val LEGACY_METADATA = CustomerMetadata.LegacyEphemeralKey( @@ -305,7 +306,7 @@ class DefaultSavedPaymentMethodRepositoryTest { saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, canUpdateCardPaymentMethodDetails = false, + canUpdateCardBrandChoice = true, ) - } } diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/CreateCustomerStateTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/CreateCustomerStateTest.kt index 671d2ae1f71..73f141f8980 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/CreateCustomerStateTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/CreateCustomerStateTest.kt @@ -273,6 +273,7 @@ internal class CreateCustomerStateTest { saveConsent = PaymentMethodSaveConsentBehavior.Enabled, canRemoveLastPaymentMethod = true, canUpdateCardPaymentMethodDetails = true, + canUpdateCardBrandChoice = true, ) val LEGACY_EK_METADATA = CustomerMetadata.LegacyEphemeralKey( @@ -283,6 +284,7 @@ internal class CreateCustomerStateTest { saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, canUpdateCardPaymentMethodDetails = false, + canUpdateCardBrandChoice = true, ) fun createElementsSessionCustomer( diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultAnalyticsMetadataFactoryTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultAnalyticsMetadataFactoryTest.kt index 55c4d001690..c4053f90332 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultAnalyticsMetadataFactoryTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultAnalyticsMetadataFactoryTest.kt @@ -840,6 +840,7 @@ class DefaultAnalyticsMetadataFactoryTest { saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, canUpdateCardPaymentMethodDetails = true, + canUpdateCardBrandChoice = true, ) private fun createElementsSessionCustomer(): ElementsSession.Customer { diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultPaymentMethodFilterTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultPaymentMethodFilterTest.kt index 667e9faaf08..1a2527c2d6d 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultPaymentMethodFilterTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultPaymentMethodFilterTest.kt @@ -217,6 +217,7 @@ class DefaultPaymentMethodFilterTest { saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = false, canUpdateCardPaymentMethodDetails = false, + canUpdateCardBrandChoice = true, ), remoteDefaultPaymentMethodId = remoteDefaultPaymentMethodId, localSavedSelection = CompletableDeferred(localSavedSelection), diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultRetrieveCustomerEmailTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultRetrieveCustomerEmailTest.kt index 58d18f65de8..1c092956ccd 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultRetrieveCustomerEmailTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultRetrieveCustomerEmailTest.kt @@ -158,6 +158,7 @@ internal class DefaultRetrieveCustomerEmailTest { saveConsent = PaymentMethodSaveConsentBehavior.Disabled(overrideAllowRedisplay = null), canRemoveLastPaymentMethod = false, canUpdateCardPaymentMethodDetails = false, + canUpdateCardBrandChoice = true, ) val LEGACY_EK_METADATA = CustomerMetadata.LegacyEphemeralKey( @@ -168,6 +169,7 @@ internal class DefaultRetrieveCustomerEmailTest { saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, canUpdateCardPaymentMethodDetails = false, + canUpdateCardBrandChoice = true, ) val CHECKOUT_SESSION_METADATA = CustomerMetadata.CheckoutSession( diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/DefaultUpdatePaymentMethodInteractorTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/DefaultUpdatePaymentMethodInteractorTest.kt index f2f8390b3c7..7f7e0129eac 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/DefaultUpdatePaymentMethodInteractorTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/DefaultUpdatePaymentMethodInteractorTest.kt @@ -47,6 +47,7 @@ class DefaultUpdatePaymentMethodInteractorTest { canRemove = true, displayableSavedPaymentMethod = paymentMethod, onRemovePaymentMethod = ::onRemovePaymentMethod, + canUpdateCardBrandChoice = true, ) { interactor.handleViewAction(UpdatePaymentMethodInteractor.ViewAction.RemovePaymentMethod) @@ -57,6 +58,7 @@ class DefaultUpdatePaymentMethodInteractorTest { @Test fun creatingInteractorInLiveMode_setsTopBarStateCorrectly() = runScenario( isLiveMode = true, + canUpdateCardBrandChoice = true, ) { assertThat(interactor.topBarState.showTestModeLabel).isFalse() } @@ -64,6 +66,7 @@ class DefaultUpdatePaymentMethodInteractorTest { @Test fun creatingInteractorInTestMode_setsTopBarStateCorrectly() = runScenario( isLiveMode = false, + canUpdateCardBrandChoice = true, ) { assertThat(interactor.topBarState.showTestModeLabel).isTrue() } @@ -81,6 +84,7 @@ class DefaultUpdatePaymentMethodInteractorTest { canRemove = true, displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), onRemovePaymentMethod = ::onRemovePaymentMethod, + canUpdateCardBrandChoice = true, ) { interactor.handleViewAction(UpdatePaymentMethodInteractor.ViewAction.RemovePaymentMethod) @@ -95,7 +99,8 @@ class DefaultUpdatePaymentMethodInteractorTest { runScenario( displayableSavedPaymentMethod = PaymentMethodFixtures .EXPIRED_CARD_PAYMENT_METHOD - .toDisplayableSavedPaymentMethod() + .toDisplayableSavedPaymentMethod(), + canUpdateCardBrandChoice = true, ) { interactor.state.test { assertThat(awaitItem().error).isEqualTo( @@ -110,7 +115,8 @@ class DefaultUpdatePaymentMethodInteractorTest { runScenario( displayableSavedPaymentMethod = PaymentMethodFixtures .EXPIRED_CARD_PAYMENT_METHOD - .toDisplayableSavedPaymentMethod() + .toDisplayableSavedPaymentMethod(), + canUpdateCardBrandChoice = true, ) { assertThat(interactor.isModifiablePaymentMethod).isFalse() } @@ -119,7 +125,8 @@ class DefaultUpdatePaymentMethodInteractorTest { @Test fun nonExpiredCard_hasNoInitialError() { runScenario( - displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard() + displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), + canUpdateCardBrandChoice = true, ) { interactor.state.test { assertThat(awaitItem().error).isNull() @@ -132,7 +139,8 @@ class DefaultUpdatePaymentMethodInteractorTest { runScenario( displayableSavedPaymentMethod = PaymentMethodFixtures .CARD_WITH_NETWORKS_PAYMENT_METHOD - .toDisplayableSavedPaymentMethod() + .toDisplayableSavedPaymentMethod(), + canUpdateCardBrandChoice = true, ) { assertThat(interactor.isModifiablePaymentMethod).isTrue() } @@ -144,6 +152,7 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures.CARD_WITH_NETWORKS_PAYMENT_METHOD.toDisplayableSavedPaymentMethod(), updatePaymentMethodExecutor = { paymentMethod, _ -> Result.success(paymentMethod) }, + canUpdateCardBrandChoice = true, ) { interactor.cardParamsUpdateAction(CardBrand.Visa) @@ -167,6 +176,7 @@ class DefaultUpdatePaymentMethodInteractorTest { updatedPaymentMethod = paymentMethod Result.success(paymentMethod) }, + canUpdateCardBrandChoice = true, ) { interactor.cardParamsUpdateAction(CardBrand.CartesBancaires) @@ -210,6 +220,7 @@ class DefaultUpdatePaymentMethodInteractorTest { runScenario( displayableSavedPaymentMethod = initialPaymentMethod.toDisplayableSavedPaymentMethod(), updatePaymentMethodExecutor = ::updatePaymentMethodExecutor, + canUpdateCardBrandChoice = true, ) { interactor.handleViewAction(UpdatePaymentMethodInteractor.ViewAction.SaveButtonPressed) @@ -232,6 +243,7 @@ class DefaultUpdatePaymentMethodInteractorTest { .CARD_WITH_NETWORKS_PAYMENT_METHOD .toDisplayableSavedPaymentMethod(), updatePaymentMethodExecutor = ::updatePaymentMethodExecutor, + canUpdateCardBrandChoice = true, ) { interactor.cardParamsUpdateAction(CardBrand.CartesBancaires) interactor.handleViewAction(UpdatePaymentMethodInteractor.ViewAction.SaveButtonPressed) @@ -250,6 +262,7 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures.SEPA_DEBIT_PAYMENT_METHOD.toDisplayableSavedPaymentMethod(), shouldShowSetAsDefaultCheckbox = true, + canUpdateCardBrandChoice = true, ) { assertThat(interactor.shouldShowSetAsDefaultCheckbox).isTrue() } @@ -258,6 +271,7 @@ class DefaultUpdatePaymentMethodInteractorTest { fun setAsDefaultCheckbox_shownForCards() = runScenario( displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), shouldShowSetAsDefaultCheckbox = true, + canUpdateCardBrandChoice = true, ) { assertThat(interactor.shouldShowSetAsDefaultCheckbox).isTrue() } @@ -266,6 +280,7 @@ class DefaultUpdatePaymentMethodInteractorTest { fun setAsDefaultCheckbox_shownForUsBankAccount() = runScenario( displayableSavedPaymentMethod = PaymentMethodFixtures.US_BANK_ACCOUNT.toDisplayableSavedPaymentMethod(), shouldShowSetAsDefaultCheckbox = true, + canUpdateCardBrandChoice = true, ) { assertThat(interactor.shouldShowSetAsDefaultCheckbox).isTrue() } @@ -275,6 +290,7 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), shouldShowSetAsDefaultCheckbox = true, isDefaultPaymentMethod = true, + canUpdateCardBrandChoice = true, ) { assertThat(interactor.shouldShowSaveButton).isFalse() } @@ -286,6 +302,7 @@ class DefaultUpdatePaymentMethodInteractorTest { .toDisplayableSavedPaymentMethod(), shouldShowSetAsDefaultCheckbox = true, isDefaultPaymentMethod = true, + canUpdateCardBrandChoice = true, ) { assertThat(interactor.shouldShowSaveButton).isTrue() } @@ -297,6 +314,7 @@ class DefaultUpdatePaymentMethodInteractorTest { .toDisplayableSavedPaymentMethod(), shouldShowSetAsDefaultCheckbox = true, isDefaultPaymentMethod = true, + canUpdateCardBrandChoice = true, ) { interactor.state.test { assertThat(awaitItem().isSaveButtonEnabled).isFalse() @@ -314,6 +332,7 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), shouldShowSetAsDefaultCheckbox = true, isDefaultPaymentMethod = true, + canUpdateCardBrandChoice = true, ) { interactor.state.test { assertThat(awaitItem().setAsDefaultCheckboxChecked).isTrue() @@ -325,6 +344,7 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), shouldShowSetAsDefaultCheckbox = true, isDefaultPaymentMethod = true, + canUpdateCardBrandChoice = true, ) { assertThat(interactor.setAsDefaultCheckboxEnabled).isFalse() } @@ -334,6 +354,7 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), shouldShowSetAsDefaultCheckbox = true, isDefaultPaymentMethod = false, + canUpdateCardBrandChoice = true, ) { assertThat(interactor.setAsDefaultCheckboxEnabled).isTrue() } @@ -341,6 +362,7 @@ class DefaultUpdatePaymentMethodInteractorTest { @Test fun setAsDefaultCheckboxChangedViewAction_updatesState() = runScenario( shouldShowSetAsDefaultCheckbox = true, + canUpdateCardBrandChoice = true, ) { val expectedInitialCheckedValue = false val expectedUpdatedCheckedValue = true @@ -367,6 +389,7 @@ class DefaultUpdatePaymentMethodInteractorTest { runScenario( shouldShowSetAsDefaultCheckbox = true, onSetDefaultPaymentMethod = { Result.success(Unit) }, + canUpdateCardBrandChoice = true, ) { interactor.handleViewAction(UpdatePaymentMethodInteractor.ViewAction.SaveButtonPressed) } @@ -377,6 +400,7 @@ class DefaultUpdatePaymentMethodInteractorTest { runScenario( shouldShowSetAsDefaultCheckbox = true, onSetDefaultPaymentMethod = { Result.success(Unit) }, + canUpdateCardBrandChoice = true, ) { interactor.handleViewAction( UpdatePaymentMethodInteractor.ViewAction.SetAsDefaultCheckboxChanged( @@ -393,7 +417,8 @@ class DefaultUpdatePaymentMethodInteractorTest { @Test fun setAsDefault_failure_displaysErrorMessage() = runScenario( shouldShowSetAsDefaultCheckbox = true, - onSetDefaultPaymentMethod = { Result.failure(IllegalStateException("Fake error")) } + onSetDefaultPaymentMethod = { Result.failure(IllegalStateException("Fake error")) }, + canUpdateCardBrandChoice = true, ) { interactor.handleViewAction( UpdatePaymentMethodInteractor.ViewAction.SetAsDefaultCheckboxChanged( @@ -419,6 +444,7 @@ class DefaultUpdatePaymentMethodInteractorTest { shouldShowSetAsDefaultCheckbox = true, onSetDefaultPaymentMethod = { Result.success(Unit) }, updatePaymentMethodExecutor = { _, _ -> Result.failure(expectedError) }, + canUpdateCardBrandChoice = true, ) { updateCardAndDefaultPaymentMethod(interactor) @@ -437,6 +463,7 @@ class DefaultUpdatePaymentMethodInteractorTest { shouldShowSetAsDefaultCheckbox = true, onSetDefaultPaymentMethod = { Result.failure(IllegalStateException("Fake error")) }, updatePaymentMethodExecutor = { paymentMethod, _ -> Result.success(paymentMethod) }, + canUpdateCardBrandChoice = true, ) { updateCardAndDefaultPaymentMethod(interactor) @@ -455,6 +482,7 @@ class DefaultUpdatePaymentMethodInteractorTest { shouldShowSetAsDefaultCheckbox = true, onSetDefaultPaymentMethod = { Result.failure(IllegalStateException("Fake error")) }, updatePaymentMethodExecutor = { _, _ -> Result.failure(IllegalStateException("Fake error")) }, + canUpdateCardBrandChoice = true, ) { updateCardAndDefaultPaymentMethod(interactor) @@ -469,6 +497,7 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures .CARD_WITH_NETWORKS_PAYMENT_METHOD .toDisplayableSavedPaymentMethod(), + canUpdateCardBrandChoice = true, ) { assertThat(interactor.shouldShowSaveButton).isTrue() } @@ -477,6 +506,7 @@ class DefaultUpdatePaymentMethodInteractorTest { fun shouldShowSaveButton_whenSetAsDefaultCheckboxShown() = runScenario( displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), shouldShowSetAsDefaultCheckbox = true, + canUpdateCardBrandChoice = true, ) { assertThat(interactor.shouldShowSaveButton).isTrue() } @@ -487,6 +517,7 @@ class DefaultUpdatePaymentMethodInteractorTest { .CARD_WITH_NETWORKS_PAYMENT_METHOD .toDisplayableSavedPaymentMethod(), shouldShowSetAsDefaultCheckbox = true, + canUpdateCardBrandChoice = true, ) { assertThat(interactor.shouldShowSaveButton).isTrue() } @@ -495,6 +526,7 @@ class DefaultUpdatePaymentMethodInteractorTest { fun shouldNotShowSaveButton_whenNothingIsChangeable() = runScenario( displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), shouldShowSetAsDefaultCheckbox = false, + canUpdateCardBrandChoice = true, ) { assertThat(interactor.shouldShowSaveButton).isFalse() } @@ -503,7 +535,8 @@ class DefaultUpdatePaymentMethodInteractorTest { fun shouldNotCallSetDefaultPaymentMethod_ifPaymentMethodIsAlreadyDefault() = runScenario( isDefaultPaymentMethod = true, onSetDefaultPaymentMethod = { _ -> notImplemented() }, - updatePaymentMethodExecutor = { _, _ -> notImplemented() } + updatePaymentMethodExecutor = { _, _ -> notImplemented() }, + canUpdateCardBrandChoice = true, ) { interactor.handleViewAction(UpdatePaymentMethodInteractor.ViewAction.SaveButtonPressed) @@ -511,7 +544,9 @@ class DefaultUpdatePaymentMethodInteractorTest { } @Test - fun shouldCreateEditCardInteractor_whenPaymentMethodIsCard() = runScenario { + fun shouldCreateEditCardInteractor_whenPaymentMethodIsCard() = runScenario( + canUpdateCardBrandChoice = true, + ) { assertThat(interactor.editCardDetailsInteractor).isNotNull() } @@ -521,7 +556,8 @@ class DefaultUpdatePaymentMethodInteractorTest { .toDisplayableSavedPaymentMethod() runScenario( displayableSavedPaymentMethod = displayableSavedPaymentMethod, - canUpdateCardPaymentMethodDetails = true + canUpdateCardPaymentMethodDetails = true, + canUpdateCardBrandChoice = true, ) { val state = interactor.editCardDetailsInteractor.state.value assertThat(state.cardDetailsState?.shouldShowCardBrandDropdown).isTrue() @@ -530,13 +566,30 @@ class DefaultUpdatePaymentMethodInteractorTest { } } + @Test + fun shouldCreateEditCardInteractorCorrectly_whenCbcEligible_andCanNotUpdateCardBrandChoice() { + val displayableSavedPaymentMethod = PaymentMethodFixtures.CARD_WITH_NETWORKS_PAYMENT_METHOD + .toDisplayableSavedPaymentMethod() + runScenario( + displayableSavedPaymentMethod = displayableSavedPaymentMethod, + canUpdateCardPaymentMethodDetails = true, + canUpdateCardBrandChoice = false, + ) { + val state = interactor.editCardDetailsInteractor.state.value + assertThat(state.cardDetailsState?.shouldShowCardBrandDropdown).isFalse() + assertThat(state.cardDetailsState?.expiryDateState?.enabled).isTrue() + assertThat(state.billingDetailsForm).isNotNull() + } + } + @Test fun shouldCreateEditCardInteractorCorrectly_whenCbcEligible_andCanNotUpdateCardPaymentMethodDetails() { val displayableSavedPaymentMethod = PaymentMethodFixtures.CARD_WITH_NETWORKS_PAYMENT_METHOD .toDisplayableSavedPaymentMethod() runScenario( displayableSavedPaymentMethod = displayableSavedPaymentMethod, - canUpdateCardPaymentMethodDetails = false + canUpdateCardPaymentMethodDetails = false, + canUpdateCardBrandChoice = true, ) { val state = interactor.editCardDetailsInteractor.state.value assertThat(state.cardDetailsState?.shouldShowCardBrandDropdown).isTrue() @@ -548,7 +601,8 @@ class DefaultUpdatePaymentMethodInteractorTest { @Test fun shouldCreateEditCardInteractorCorrectly_whenCbcIneligible_andCanUpdateCardPaymentMethodDetails() { runScenario( - canUpdateCardPaymentMethodDetails = true + canUpdateCardPaymentMethodDetails = true, + canUpdateCardBrandChoice = true, ) { val state = interactor.editCardDetailsInteractor.state.value assertThat(state.cardDetailsState?.shouldShowCardBrandDropdown).isFalse() @@ -560,7 +614,8 @@ class DefaultUpdatePaymentMethodInteractorTest { @Test fun shouldCreateEditCardInteractorCorrectly_whenCbcIneligible_andCanNotUpdateCardPaymentMethodDetails() { runScenario( - canUpdateCardPaymentMethodDetails = false + canUpdateCardPaymentMethodDetails = false, + canUpdateCardBrandChoice = true, ) { val state = interactor.editCardDetailsInteractor.state.value assertThat(state.cardDetailsState?.shouldShowCardBrandDropdown).isFalse() @@ -571,7 +626,8 @@ class DefaultUpdatePaymentMethodInteractorTest { @Test fun shouldNotCreateEditCardInteractor_whenPaymentMethodIsNotCard() = runScenario( - displayableSavedPaymentMethod = PaymentMethodFixtures.US_BANK_ACCOUNT.toDisplayableSavedPaymentMethod() + displayableSavedPaymentMethod = PaymentMethodFixtures.US_BANK_ACCOUNT.toDisplayableSavedPaymentMethod(), + canUpdateCardBrandChoice = true, ) { val exception = assertThrows(IllegalArgumentException::class.java) { interactor.editCardDetailsInteractor @@ -585,7 +641,8 @@ class DefaultUpdatePaymentMethodInteractorTest { fun editCardDetailsInteractorCallback_updatesSaveButtonStateCorrectly() { val editCardDetailsInteractorFactory = FakeEditCardDetailsInteractorFactory() runScenario( - editCardDetailsInteractorFactory = editCardDetailsInteractorFactory + editCardDetailsInteractorFactory = editCardDetailsInteractorFactory, + canUpdateCardBrandChoice = true, ) { interactor.editCardDetailsInteractor editCardDetailsInteractorFactory.onCardUpdateParamsChanged?.invoke( @@ -600,7 +657,8 @@ class DefaultUpdatePaymentMethodInteractorTest { fun editCardDetailsInteractorCallback_nullValue_updatesSaveButtonStateCorrectly() { val editCardDetailsInteractorFactory = FakeEditCardDetailsInteractorFactory() runScenario( - editCardDetailsInteractorFactory = editCardDetailsInteractorFactory + editCardDetailsInteractorFactory = editCardDetailsInteractorFactory, + canUpdateCardBrandChoice = true, ) { editCardDetailsInteractorFactory.onCardUpdateParamsChanged?.invoke( CardUpdateParams(cardBrand = CardBrand.Visa) @@ -618,7 +676,8 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), addressCollectionMode = AddressCollectionMode.Full, allowedBillingCountries = setOf("us", "CA"), - editCardDetailsInteractorFactory = editCardDetailsInteractorFactory + editCardDetailsInteractorFactory = editCardDetailsInteractorFactory, + canUpdateCardBrandChoice = true, ) { assertThat(interactor.editCardDetailsInteractor.state.value).isNotNull() @@ -644,7 +703,8 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures.displayableLinkPaymentMethod(), addressCollectionMode = AddressCollectionMode.Full, allowedBillingCountries = setOf("us", "CA"), - editCardDetailsInteractorFactory = editCardDetailsInteractorFactory + editCardDetailsInteractorFactory = editCardDetailsInteractorFactory, + canUpdateCardBrandChoice = true, ) { assertThat(interactor.editCardDetailsInteractor.state.value).isNotNull() @@ -669,7 +729,8 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures.displayableLinkPaymentMethod(), addressCollectionMode = AddressCollectionMode.Full, allowedBillingCountries = setOf("us", "CA"), - editCardDetailsInteractorFactory = FakeEditCardDetailsInteractorFactory() + editCardDetailsInteractorFactory = FakeEditCardDetailsInteractorFactory(), + canUpdateCardBrandChoice = true, ) { assertThat(interactor.editCardDetailsInteractor).isInstanceOf() @@ -712,6 +773,7 @@ class DefaultUpdatePaymentMethodInteractorTest { shouldShowSetAsDefaultCheckbox: Boolean = false, isDefaultPaymentMethod: Boolean = false, canUpdateCardPaymentMethodDetails: Boolean = false, + canUpdateCardBrandChoice: Boolean, addressCollectionMode: AddressCollectionMode = AddressCollectionMode.Automatic, allowedBillingCountries: Set = setOf("US", "CA"), editCardDetailsInteractorFactory: EditCardDetailsInteractor.Factory = DefaultEditCardDetailsInteractor @@ -724,6 +786,7 @@ class DefaultUpdatePaymentMethodInteractorTest { isLiveMode = isLiveMode, canRemove = canRemove, canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardBrandChoice = canUpdateCardBrandChoice, displayableSavedPaymentMethod = displayableSavedPaymentMethod, addressCollectionMode = addressCollectionMode, removeExecutor = onRemovePaymentMethod, diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/FakeUpdatePaymentMethodInteractor.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/FakeUpdatePaymentMethodInteractor.kt index 8ecdbf2a058..b6cd253462a 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/FakeUpdatePaymentMethodInteractor.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/FakeUpdatePaymentMethodInteractor.kt @@ -21,6 +21,7 @@ internal class FakeUpdatePaymentMethodInteractor( override val isExpiredCard: Boolean = false, override val isModifiablePaymentMethod: Boolean = false, override val hasValidBrandChoices: Boolean = true, + override val shouldShowCardBrandDropdown: Boolean = false, override val cardBrandFilter: CardBrandFilter = DefaultCardBrandFilter, override val shouldShowSetAsDefaultCheckbox: Boolean = false, override val shouldShowSaveButton: Boolean = false, @@ -37,6 +38,7 @@ internal class FakeUpdatePaymentMethodInteractor( ), override val setAsDefaultCheckboxEnabled: Boolean = true, override val canUpdateCardPaymentMethodDetails: Boolean = false, + override val canUpdateCardBrandChoice: Boolean, private val editCardDetailsInteractorFactory: EditCardDetailsInteractor.Factory = DefaultEditCardDetailsInteractor .Factory(), ) : UpdatePaymentMethodInteractor { @@ -45,13 +47,17 @@ internal class FakeUpdatePaymentMethodInteractor( displayableSavedPaymentMethod ) override val editCardDetailsInteractor: EditCardDetailsInteractor by lazy { - val isModifiable = - displayableSavedPaymentMethod.isModifiable(canUpdateCardPaymentMethodDetails) + val isModifiable = displayableSavedPaymentMethod.isModifiable( + canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardBrandChoice = canUpdateCardBrandChoice, + ) editCardDetailsInteractorFactory.create( coroutineScope = TestScope(), cardEditConfiguration = CardEditConfiguration( cardBrandFilter = cardBrandFilter, - isCbcModifiable = isModifiable && displayableSavedPaymentMethod.canChangeCbc(), + isCbcModifiable = isModifiable && + canUpdateCardBrandChoice && + displayableSavedPaymentMethod.canChangeCbc(), areExpiryDateAndAddressModificationSupported = isModifiable && canUpdateCardPaymentMethodDetails ), requiresModification = true, diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentSheetScreenUpdatePaymentMethodScreenshotTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentSheetScreenUpdatePaymentMethodScreenshotTest.kt index 68731462558..c03c090b6d6 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentSheetScreenUpdatePaymentMethodScreenshotTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentSheetScreenUpdatePaymentMethodScreenshotTest.kt @@ -226,7 +226,8 @@ internal class PaymentSheetScreenUpdatePaymentMethodScreenshotTest { useDefaultBillingDetails = useDefaultBillingDetails, shouldShowSaveButton = isModifiablePaymentMethod || shouldShowSetAsDefaultCheckbox, addressCollectionMode = addressCollectionMode, - canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails + canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardBrandChoice = true, ).apply { if (validating) { editCardDetailsInteractor.handleViewAction(EditCardDetailsInteractor.ViewAction.Validate) diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUIScreenshotTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUIScreenshotTest.kt index 6ec3210d46f..7bc93a3f5d9 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUIScreenshotTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUIScreenshotTest.kt @@ -54,6 +54,7 @@ class UpdatePaymentMethodUIScreenshotTest { shouldShowSetAsDefaultCheckbox = false, shouldShowSaveButton = true, setAsDefaultCheckboxEnabled = false, + canUpdateCardBrandChoice = true, initialState = UpdatePaymentMethodInteractor.State( error = null, status = status, diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUITest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUITest.kt index 29d9c106583..1a60571052a 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUITest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUITest.kt @@ -339,6 +339,7 @@ class UpdatePaymentMethodUITest { shouldShowSetAsDefaultCheckbox = shouldShowSetAsDefaultCheckbox, shouldShowSaveButton = shouldShowSaveButton, setAsDefaultCheckboxEnabled = setAsDefaultCheckboxEnabled, + canUpdateCardBrandChoice = true, initialState = UpdatePaymentMethodInteractor.State( error = errorMessage, status = UpdatePaymentMethodInteractor.Status.Idle, From 53251ad94d78eb8f5495b65d1dc43ad395f7ab5b Mon Sep 17 00:00:00 2001 From: Chengtin Tsai Date: Thu, 2 Jul 2026 15:00:58 -0700 Subject: [PATCH 3/7] Fix missing canUpdateCardBrandChoice in tests Co-Authored-By: Claude Opus 4.6 (1M context) Committed-By-Agent: claude --- .../android/customersheet/CustomerSheetScreenshotTest.kt | 1 + .../lpmfoundations/paymentmethod/CustomerMetadataTest.kt | 4 ++-- .../DefaultPaymentMethodVerticalLayoutInteractorTest.kt | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetScreenshotTest.kt b/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetScreenshotTest.kt index cda32cd0427..5a4b44a0e80 100644 --- a/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetScreenshotTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetScreenshotTest.kt @@ -377,6 +377,7 @@ internal class CustomerSheetScreenshotTest { return CustomerSheetViewState.UpdatePaymentMethod( updatePaymentMethodInteractor = DefaultUpdatePaymentMethodInteractor( canUpdateCardPaymentMethodDetails = false, + canUpdateCardBrandChoice = true, displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), removeExecutor = { null }, updatePaymentMethodExecutor = { paymentMethod, _ -> Result.success(paymentMethod) }, diff --git a/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadataTest.kt b/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadataTest.kt index 132906b4aaf..f184a2eefe3 100644 --- a/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadataTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadataTest.kt @@ -18,7 +18,7 @@ import org.junit.Test internal class CustomerMetadataTest { @Test - fun `CheckoutSession should support card details but not card brand updates`() { + fun `CheckoutSession should not support card details or card brand updates`() { val metadata = CustomerMetadata.CheckoutSession( sessionId = "cs_123", customerId = "cus_123", @@ -26,7 +26,7 @@ internal class CustomerMetadataTest { saveConsent = PaymentMethodSaveConsentBehavior.Legacy, ) - assertThat(metadata.canUpdateCardPaymentMethodDetails).isTrue() + assertThat(metadata.canUpdateCardPaymentMethodDetails).isFalse() assertThat(metadata.canUpdateCardBrandChoice).isFalse() } 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 a5634e0a804..3bc4e91d540 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 @@ -1813,6 +1813,7 @@ class DefaultPaymentMethodVerticalLayoutInteractorTest { initialPaymentMethods: List = emptyList(), initialMostRecentlySelectedSavedPaymentMethod: PaymentMethod? = null, canUpdateCardPaymentMethodDetails: Boolean = false, + canUpdateCardBrandChoice: Boolean = true, shouldUpdateVerticalModeSelection: (String?) -> Boolean = { paymentMethodCode -> val requiresFormScreen = paymentMethodCode != null && formTypeForCode(paymentMethodCode) == FormHelper.FormType.UserInteractionRequired @@ -1865,6 +1866,7 @@ class DefaultPaymentMethodVerticalLayoutInteractorTest { canRemove = canRemove, walletsState = walletsState, canUpdateCardPaymentMethodDetails = stateFlowOf(canUpdateCardPaymentMethodDetails), + canUpdateCardBrandChoice = stateFlowOf(canUpdateCardBrandChoice), updateSelection = { paymentSelection, isFormScreen -> selection.value = paymentSelection updateSelectionTurbine.add(isFormScreen) From 6ef3ec984851516721c2a8da348915155799f9c6 Mon Sep 17 00:00:00 2001 From: Chengtin Tsai Date: Thu, 2 Jul 2026 15:09:13 -0700 Subject: [PATCH 4/7] Clarify card update capability name Committed-By-Agent: codex Co-authored-by: codex Committed-By-Agent: codex Co-authored-by: codex Committed-By-Agent: codex Co-authored-by: codex Committed-By-Agent: codex Co-authored-by: codex Committed-By-Agent: claude --- .../customersheet/CustomerPermissions.kt | 2 +- .../customersheet/CustomerSheetViewModel.kt | 8 ++--- .../customersheet/CustomerSheetViewState.kt | 4 +-- .../data/CustomerAdapterDataSource.kt | 2 +- ...CustomerSessionInitializationDataSource.kt | 2 +- .../paymentmethod/CustomerMetadata.kt | 20 +++++------ .../embedded/content/EmbeddedContentHelper.kt | 2 +- .../EmbeddedUpdateScreenInteractorFactory.kt | 2 +- .../paymentsheet/CustomerStateHolder.kt | 2 +- .../DefaultCustomerStateHolder.kt | 4 +-- .../DisplayableSavedPaymentMethod.kt | 4 +-- .../SavedPaymentMethodEditability.kt | 4 +-- .../paymentsheet/SavedPaymentMethodMutator.kt | 10 +++--- .../ui/UpdatePaymentMethodInteractor.kt | 10 +++--- .../paymentsheet/ui/UpdatePaymentMethodUI.kt | 4 +-- .../PaymentMethodVerticalLayoutInteractor.kt | 19 ++++++----- .../customersheet/CustomerSheetFixtures.kt | 2 +- .../CustomerSheetScreenshotTest.kt | 2 +- .../CustomerSheetViewModelTest.kt | 34 +++++++++---------- .../data/CustomerAdapterDataSourceTest.kt | 2 +- ...omerSessionInitializationDataSourceTest.kt | 4 +-- .../state/DefaultCustomerSheetLoaderTest.kt | 2 +- .../utils/CustomerSheetTestHelper.kt | 2 +- .../utils/FakeCustomerSheetLoader.kt | 2 +- .../paymentmethod/CustomerMetadataTest.kt | 6 ++-- .../PaymentMethodMetadataFactory.kt | 6 ++-- .../PaymentMethodMetadataFixtures.kt | 12 +++---- .../sheet/EmbeddedSheetActivityTest.kt | 4 +-- .../DefaultCustomerStateHolderTest.kt | 2 +- ...ayableSavedPaymentMethodModifiableTest.kt} | 8 ++--- .../paymentsheet/FakeCustomerStateHolder.kt | 2 +- .../PaymentOptionsStateFactoryTest.kt | 2 +- .../SavedPaymentMethodMutatorTest.kt | 10 +++--- ...DefaultSavedPaymentMethodRepositoryTest.kt | 4 +-- .../state/CreateCustomerStateTest.kt | 4 +-- .../DefaultAnalyticsMetadataFactoryTest.kt | 2 +- .../state/DefaultPaymentElementLoaderTest.kt | 16 ++++----- .../state/DefaultPaymentMethodFilterTest.kt | 2 +- .../state/DefaultRetrieveCustomerEmailTest.kt | 4 +-- ...efaultUpdatePaymentMethodInteractorTest.kt | 22 ++++++------ .../ui/FakeUpdatePaymentMethodInteractor.kt | 6 ++-- ...ScreenUpdatePaymentMethodScreenshotTest.kt | 14 ++++---- ...ymentMethodVerticalLayoutInteractorTest.kt | 4 +-- 43 files changed, 140 insertions(+), 139 deletions(-) rename paymentsheet/src/test/java/com/stripe/android/paymentsheet/{SavedPaymentMethodEditabilityTest.kt => DisplayableSavedPaymentMethodModifiableTest.kt} (93%) diff --git a/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerPermissions.kt b/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerPermissions.kt index e6aed774d7f..9950ee9116e 100644 --- a/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerPermissions.kt +++ b/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerPermissions.kt @@ -5,7 +5,7 @@ import com.stripe.android.common.model.PaymentMethodRemovePermission internal data class CustomerPermissions( val removePaymentMethod: PaymentMethodRemovePermission, val canRemoveLastPaymentMethod: Boolean, - val canUpdateCardPaymentMethodDetails: Boolean + val canUpdateCardExpiryAndBillingDetails: Boolean ) { val canRemovePaymentMethods: Boolean get() = removePaymentMethod == PaymentMethodRemovePermission.Full || diff --git a/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewModel.kt b/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewModel.kt index eda815a5445..662aac8254f 100644 --- a/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewModel.kt +++ b/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewModel.kt @@ -157,7 +157,7 @@ internal class CustomerSheetViewModel( permissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.None, canRemoveLastPaymentMethod = false, - canUpdateCardPaymentMethodDetails = false, + canUpdateCardExpiryAndBillingDetails = false, ), metadata = null, ) @@ -570,7 +570,7 @@ internal class CustomerSheetViewModel( updatePaymentMethodInteractor = DefaultUpdatePaymentMethodInteractor( isLiveMode = isLiveMode, canRemove = customerState.canRemove, - canUpdateCardPaymentMethodDetails = customerState.canUpdateCardPaymentMethodDetails, + canUpdateCardExpiryAndBillingDetails = customerState.canUpdateCardExpiryAndBillingDetails, canUpdateCardBrandChoice = true, displayableSavedPaymentMethod = paymentMethod, addressCollectionMode = configuration.billingDetailsCollectionConfiguration.address, @@ -1275,14 +1275,14 @@ internal class CustomerSheetViewModel( else -> permissions.canRemovePaymentMethods } - val canUpdateCardPaymentMethodDetails = permissions.canUpdateCardPaymentMethodDetails + val canUpdateCardExpiryAndBillingDetails = permissions.canUpdateCardExpiryAndBillingDetails val cbcEligibility = metadata?.cbcEligibility ?: CardBrandChoiceEligibility.Ineligible val canEdit = canRemove || paymentMethods.any { method -> isModifiable( paymentMethod = method, cbcEligibility = cbcEligibility, - canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, ) } diff --git a/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewState.kt b/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewState.kt index d8c8d80e046..fd297b4efd6 100644 --- a/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewState.kt +++ b/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewState.kt @@ -144,10 +144,10 @@ internal sealed class CustomerSheetViewState( internal fun isModifiable( paymentMethod: PaymentMethod, cbcEligibility: CardBrandChoiceEligibility, - canUpdateCardPaymentMethodDetails: Boolean, + canUpdateCardExpiryAndBillingDetails: Boolean, ): Boolean { return paymentMethod.isModifiable( - canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, canUpdateCardBrandChoice = true, isCbcEligible = cbcEligibility is CardBrandChoiceEligibility.Eligible, ) diff --git a/paymentsheet/src/main/java/com/stripe/android/customersheet/data/CustomerAdapterDataSource.kt b/paymentsheet/src/main/java/com/stripe/android/customersheet/data/CustomerAdapterDataSource.kt index 36b91df4bc2..57e025ba743 100644 --- a/paymentsheet/src/main/java/com/stripe/android/customersheet/data/CustomerAdapterDataSource.kt +++ b/paymentsheet/src/main/java/com/stripe/android/customersheet/data/CustomerAdapterDataSource.kt @@ -67,7 +67,7 @@ internal class CustomerAdapterDataSource @Inject constructor( // Always `Full` for `Adapter` use case removePaymentMethod = PaymentMethodRemovePermission.Full, // Payment Method Update is customer sessions-only feature, so this value is unused. - canUpdateCardPaymentMethodDetails = false, + canUpdateCardExpiryAndBillingDetails = false, ), // Default payment methods are a customer sessions-only feature, so this value is unused. defaultPaymentMethodId = null, diff --git a/paymentsheet/src/main/java/com/stripe/android/customersheet/data/CustomerSessionInitializationDataSource.kt b/paymentsheet/src/main/java/com/stripe/android/customersheet/data/CustomerSessionInitializationDataSource.kt index a1965bec139..1242b9b84e7 100644 --- a/paymentsheet/src/main/java/com/stripe/android/customersheet/data/CustomerSessionInitializationDataSource.kt +++ b/paymentsheet/src/main/java/com/stripe/android/customersheet/data/CustomerSessionInitializationDataSource.kt @@ -68,7 +68,7 @@ internal class CustomerSessionInitializationDataSource @Inject constructor( PaymentMethodRemovePermission.None }, // Should always be enabled when using `customer_session` - canUpdateCardPaymentMethodDetails = true + canUpdateCardExpiryAndBillingDetails = true ), defaultPaymentMethodId = customer.defaultPaymentMethod, customerId = customer.session.customerId, diff --git a/paymentsheet/src/main/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadata.kt b/paymentsheet/src/main/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadata.kt index f216bab8e7d..64b9f111eef 100644 --- a/paymentsheet/src/main/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadata.kt +++ b/paymentsheet/src/main/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadata.kt @@ -13,7 +13,7 @@ internal sealed class CustomerMetadata : Parcelable { abstract val removePaymentMethod: PaymentMethodRemovePermission abstract val saveConsent: PaymentMethodSaveConsentBehavior abstract val canRemoveLastPaymentMethod: Boolean - abstract val canUpdateCardPaymentMethodDetails: Boolean + abstract val canUpdateCardExpiryAndBillingDetails: Boolean abstract val canUpdateCardBrandChoice: Boolean val canRemovePaymentMethods: Boolean @@ -28,7 +28,7 @@ internal sealed class CustomerMetadata : Parcelable { override val removePaymentMethod: PaymentMethodRemovePermission, override val saveConsent: PaymentMethodSaveConsentBehavior, override val canRemoveLastPaymentMethod: Boolean, - override val canUpdateCardPaymentMethodDetails: Boolean, + override val canUpdateCardExpiryAndBillingDetails: Boolean, override val canUpdateCardBrandChoice: Boolean, ) : CustomerMetadata() @@ -41,7 +41,7 @@ internal sealed class CustomerMetadata : Parcelable { override val removePaymentMethod: PaymentMethodRemovePermission, override val saveConsent: PaymentMethodSaveConsentBehavior, override val canRemoveLastPaymentMethod: Boolean, - override val canUpdateCardPaymentMethodDetails: Boolean, + override val canUpdateCardExpiryAndBillingDetails: Boolean, override val canUpdateCardBrandChoice: Boolean, ) : CustomerMetadata() @@ -59,7 +59,7 @@ internal sealed class CustomerMetadata : Parcelable { override val canRemoveLastPaymentMethod: Boolean get() = true // CheckoutSession card detail updates are wired in a separate change. - override val canUpdateCardPaymentMethodDetails: Boolean get() = false + override val canUpdateCardExpiryAndBillingDetails: Boolean get() = false // CheckoutSession doesn't support updating preferred card networks. override val canUpdateCardBrandChoice: Boolean get() = false @@ -118,7 +118,7 @@ internal sealed class CustomerMetadata : Parcelable { saveConsent = saveConsent, canRemoveLastPaymentMethod = canRemoveLastPaymentMethod, // Should always be enabled when using `customer_session` - canUpdateCardPaymentMethodDetails = true, + canUpdateCardExpiryAndBillingDetails = true, canUpdateCardBrandChoice = true, ) } @@ -150,7 +150,7 @@ internal sealed class CustomerMetadata : Parcelable { * sessions. */ canRemoveLastPaymentMethod = configuration.allowsRemovalOfLastSavedPaymentMethod, - canUpdateCardPaymentMethodDetails = false, + canUpdateCardExpiryAndBillingDetails = false, canUpdateCardBrandChoice = true, ) } @@ -166,8 +166,8 @@ internal sealed class CustomerMetadata : Parcelable { val removePaymentMethod = customerSheetSession.permissions.removePaymentMethod val saveConsent = customerSheetSession.paymentMethodSaveConsentBehavior val canRemoveLastPaymentMethod = configuration.allowsRemovalOfLastSavedPaymentMethod - val canUpdateCardPaymentMethodDetails = - customerSheetSession.permissions.canUpdateCardPaymentMethodDetails + val canUpdateCardExpiryAndBillingDetails = + customerSheetSession.permissions.canUpdateCardExpiryAndBillingDetails return if (customerSessionClientSecret != null) { CustomerSession( @@ -178,7 +178,7 @@ internal sealed class CustomerMetadata : Parcelable { removePaymentMethod = removePaymentMethod, saveConsent = saveConsent, canRemoveLastPaymentMethod = canRemoveLastPaymentMethod, - canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, canUpdateCardBrandChoice = true, ) } else { @@ -189,7 +189,7 @@ internal sealed class CustomerMetadata : Parcelable { removePaymentMethod = removePaymentMethod, saveConsent = saveConsent, canRemoveLastPaymentMethod = canRemoveLastPaymentMethod, - canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, canUpdateCardBrandChoice = true, ) } diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/content/EmbeddedContentHelper.kt b/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/content/EmbeddedContentHelper.kt index 662c13396b3..cd7e2c4add6 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/content/EmbeddedContentHelper.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/content/EmbeddedContentHelper.kt @@ -252,7 +252,7 @@ internal class DefaultEmbeddedContentHelper @Inject constructor( paymentMethods = customerStateHolder.paymentMethods, mostRecentlySelectedSavedPaymentMethod = customerStateHolder.mostRecentlySelectedSavedPaymentMethod, canRemove = customerStateHolder.canRemove, - canUpdateCardPaymentMethodDetails = customerStateHolder.canUpdateCardPaymentMethodDetails, + canUpdateCardExpiryAndBillingDetails = customerStateHolder.canUpdateCardExpiryAndBillingDetails, canUpdateCardBrandChoice = customerStateHolder.canUpdateCardBrandChoice, walletsState = walletsState, updateSelection = { updatedSelection, requiresConfirmation -> diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/manage/EmbeddedUpdateScreenInteractorFactory.kt b/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/manage/EmbeddedUpdateScreenInteractorFactory.kt index 2c162045f45..accf1b1b100 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/manage/EmbeddedUpdateScreenInteractorFactory.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/manage/EmbeddedUpdateScreenInteractorFactory.kt @@ -33,7 +33,7 @@ internal class DefaultEmbeddedUpdateScreenInteractorFactory @Inject constructor( return DefaultUpdatePaymentMethodInteractor( isLiveMode = paymentMethodMetadata.stripeIntent.isLiveMode, canRemove = customerStateHolder.canRemove.value, - canUpdateCardPaymentMethodDetails = customerStateHolder.canUpdateCardPaymentMethodDetails.value, + canUpdateCardExpiryAndBillingDetails = customerStateHolder.canUpdateCardExpiryAndBillingDetails.value, canUpdateCardBrandChoice = customerStateHolder.canUpdateCardBrandChoice.value, displayableSavedPaymentMethod = displayableSavedPaymentMethod, cardBrandFilter = paymentMethodMetadata.cardBrandFilter, diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/CustomerStateHolder.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/CustomerStateHolder.kt index 48b44437e6a..49fd29e023a 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/CustomerStateHolder.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/CustomerStateHolder.kt @@ -21,7 +21,7 @@ internal interface CustomerStateHolder { val canRemove: StateFlow - val canUpdateCardPaymentMethodDetails: StateFlow + val canUpdateCardExpiryAndBillingDetails: StateFlow val canUpdateCardBrandChoice: StateFlow diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DefaultCustomerStateHolder.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DefaultCustomerStateHolder.kt index 57b2cd5d5c1..3fe582ac020 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DefaultCustomerStateHolder.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DefaultCustomerStateHolder.kt @@ -48,8 +48,8 @@ internal class DefaultCustomerStateHolder( } ?: false } - override val canUpdateCardPaymentMethodDetails: StateFlow = customerMetadata.mapAsStateFlow { - it?.canUpdateCardPaymentMethodDetails ?: false + override val canUpdateCardExpiryAndBillingDetails: StateFlow = customerMetadata.mapAsStateFlow { + it?.canUpdateCardExpiryAndBillingDetails ?: false } override val canUpdateCardBrandChoice: StateFlow = customerMetadata.mapAsStateFlow { diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethod.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethod.kt index 3e8c79cd960..a005d3c92c0 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethod.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethod.kt @@ -32,11 +32,11 @@ internal data class DisplayableSavedPaymentMethod private constructor( } fun isModifiable( - canUpdateCardPaymentMethodDetails: Boolean, + canUpdateCardExpiryAndBillingDetails: Boolean, canUpdateCardBrandChoice: Boolean, ): Boolean { return paymentMethod.isModifiable( - canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, canUpdateCardBrandChoice = canUpdateCardBrandChoice, isCbcEligible = isCbcEligible, ) diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodEditability.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodEditability.kt index 334d7645b61..35e974ffa82 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodEditability.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodEditability.kt @@ -4,13 +4,13 @@ import com.stripe.android.core.utils.DateUtils import com.stripe.android.model.PaymentMethod internal fun PaymentMethod.isModifiable( - canUpdateCardPaymentMethodDetails: Boolean, + canUpdateCardExpiryAndBillingDetails: Boolean, canUpdateCardBrandChoice: Boolean, isCbcEligible: Boolean, ): Boolean { val card = editableSavedCard() ?: return false - return canUpdateCardPaymentMethodDetails || + return canUpdateCardExpiryAndBillingDetails || (canUpdateCardBrandChoice && card.isExpired().not() && canChangeCbc(isCbcEligible)) } diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodMutator.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodMutator.kt index 01947ace6bd..547aabdb831 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodMutator.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodMutator.kt @@ -93,12 +93,12 @@ internal class SavedPaymentMethodMutator( val canEdit: StateFlow = combineAsStateFlow( customerStateHolder.canRemove, paymentOptionsItems, - customerStateHolder.canUpdateCardPaymentMethodDetails, + customerStateHolder.canUpdateCardExpiryAndBillingDetails, customerStateHolder.canUpdateCardBrandChoice, - ) { canRemove, items, canUpdateCardPaymentMethodDetails, canUpdateCardBrandChoice -> + ) { canRemove, items, canUpdateCardExpiryAndBillingDetails, canUpdateCardBrandChoice -> canRemove || items.filterIsInstance().any { item -> item.displayableSavedPaymentMethod.isModifiable( - canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, canUpdateCardBrandChoice = canUpdateCardBrandChoice, ) } @@ -380,8 +380,8 @@ internal class SavedPaymentMethodMutator( DefaultUpdatePaymentMethodInteractor( isLiveMode = isLiveMode, canRemove = canRemove, - canUpdateCardPaymentMethodDetails = viewModel.customerStateHolder - .canUpdateCardPaymentMethodDetails.value, + canUpdateCardExpiryAndBillingDetails = viewModel.customerStateHolder + .canUpdateCardExpiryAndBillingDetails.value, canUpdateCardBrandChoice = viewModel.customerStateHolder.canUpdateCardBrandChoice.value, displayableSavedPaymentMethod = displayableSavedPaymentMethod, cardBrandFilter = PaymentSheetCardBrandFilter(viewModel.config.cardBrandAcceptance), diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodInteractor.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodInteractor.kt index 0f9242406bd..d6c89500c77 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodInteractor.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodInteractor.kt @@ -40,7 +40,7 @@ internal interface UpdatePaymentMethodInteractor { val shouldShowSetAsDefaultCheckbox: Boolean val setAsDefaultCheckboxEnabled: Boolean val shouldShowSaveButton: Boolean - val canUpdateCardPaymentMethodDetails: Boolean + val canUpdateCardExpiryAndBillingDetails: Boolean val canUpdateCardBrandChoice: Boolean val addressCollectionMode: AddressCollectionMode val allowedBillingCountries: Set @@ -116,7 +116,7 @@ internal class DefaultUpdatePaymentMethodInteractor( override val cardBrandFilter: CardBrandFilter, override val addressCollectionMode: AddressCollectionMode, override val allowedBillingCountries: Set, - override val canUpdateCardPaymentMethodDetails: Boolean, + override val canUpdateCardExpiryAndBillingDetails: Boolean, override val canUpdateCardBrandChoice: Boolean, override val removeMessage: ResolvableString?, val isDefaultPaymentMethod: Boolean, @@ -144,7 +144,7 @@ internal class DefaultUpdatePaymentMethodInteractor( ) override val isModifiablePaymentMethod: Boolean get() = displayableSavedPaymentMethod.isModifiable( - canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, canUpdateCardBrandChoice = canUpdateCardBrandChoice, ) override val shouldShowCardBrandDropdown: Boolean @@ -184,14 +184,14 @@ internal class DefaultUpdatePaymentMethodInteractor( savedPaymentMethodCard: SavedPaymentMethod.Card, ): EditCardDetailsInteractor { val isModifiable = displayableSavedPaymentMethod.isModifiable( - canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, canUpdateCardBrandChoice = canUpdateCardBrandChoice, ) val payload = EditCardPayload.create(savedPaymentMethodCard.card, savedPaymentMethodCard.billingDetails) val cardEditConfiguration = CardEditConfiguration( cardBrandFilter = cardBrandFilter, isCbcModifiable = isModifiable && canUpdateCardBrandChoice && displayableSavedPaymentMethod.canChangeCbc(), - areExpiryDateAndAddressModificationSupported = isModifiable && canUpdateCardPaymentMethodDetails, + areExpiryDateAndAddressModificationSupported = isModifiable && canUpdateCardExpiryAndBillingDetails, ) return editCardDetailsInteractorFactory.create( payload = payload, diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUI.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUI.kt index 9f920263b91..af2f1bfe377 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUI.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUI.kt @@ -98,7 +98,7 @@ internal fun UpdatePaymentMethodUI(interactor: UpdatePaymentMethodInteractor, mo } val showCardDetailsCannotBeChanged = interactor.isExpiredCard.not() && - (interactor.isModifiablePaymentMethod.not() || interactor.canUpdateCardPaymentMethodDetails.not()) + (interactor.isModifiablePaymentMethod.not() || interactor.canUpdateCardExpiryAndBillingDetails.not()) if (showCardDetailsCannotBeChanged) { DetailsCannotBeChangedText(interactor, shouldShowCardBrandDropdown, context) } @@ -355,7 +355,7 @@ private fun PreviewUpdatePaymentMethodUI() { interactor = DefaultUpdatePaymentMethodInteractor( isLiveMode = false, canRemove = true, - canUpdateCardPaymentMethodDetails = true, + canUpdateCardExpiryAndBillingDetails = true, canUpdateCardBrandChoice = true, displayableSavedPaymentMethod = exampleCard, addressCollectionMode = AddressCollectionMode.Automatic, 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 669ff14c9a8..f86d92174e7 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 @@ -103,7 +103,7 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( private val mostRecentlySelectedSavedPaymentMethod: StateFlow, private val canRemove: StateFlow, private val walletsState: StateFlow, - private val canUpdateCardPaymentMethodDetails: StateFlow, + private val canUpdateCardExpiryAndBillingDetails: StateFlow, private val canUpdateCardBrandChoice: StateFlow, private val updateSelection: (PaymentSelection?, Boolean) -> Unit, private val isCurrentScreen: StateFlow, @@ -179,7 +179,8 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( } }, walletsState = viewModel.walletsState, - canUpdateCardPaymentMethodDetails = viewModel.customerStateHolder.canUpdateCardPaymentMethodDetails, + canUpdateCardExpiryAndBillingDetails = viewModel.customerStateHolder + .canUpdateCardExpiryAndBillingDetails, canUpdateCardBrandChoice = viewModel.customerStateHolder.canUpdateCardBrandChoice, isCurrentScreen = isCurrentScreen, reportPaymentMethodTypeSelected = viewModel.eventReporter::onSelectPaymentMethod, @@ -243,18 +244,18 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( paymentMethods, displayedSavedPaymentMethod, canRemove, - canUpdateCardPaymentMethodDetails, + canUpdateCardExpiryAndBillingDetails, canUpdateCardBrandChoice, ) { paymentMethods, displayedSavedPaymentMethod, canRemove, - canUpdateCardPaymentMethodDetails, + canUpdateCardExpiryAndBillingDetails, canUpdateCardBrandChoice -> getAvailableSavedPaymentMethodAction( paymentMethods = paymentMethods, savedPaymentMethod = displayedSavedPaymentMethod, canRemove = canRemove, - canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, canUpdateCardBrandChoice = canUpdateCardBrandChoice, ) } @@ -511,7 +512,7 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( paymentMethods: List?, savedPaymentMethod: DisplayableSavedPaymentMethod?, canRemove: Boolean, - canUpdateCardPaymentMethodDetails: Boolean, + canUpdateCardExpiryAndBillingDetails: Boolean, canUpdateCardBrandChoice: Boolean, ): PaymentMethodVerticalLayoutInteractor.SavedPaymentMethodAction { if (paymentMethods == null || savedPaymentMethod == null) { @@ -524,7 +525,7 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( getSavedPaymentMethodActionForOnePaymentMethod( canRemove = canRemove, savedPaymentMethod = savedPaymentMethod, - canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, canUpdateCardBrandChoice = canUpdateCardBrandChoice, ) } @@ -536,11 +537,11 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( private fun getSavedPaymentMethodActionForOnePaymentMethod( canRemove: Boolean, savedPaymentMethod: DisplayableSavedPaymentMethod?, - canUpdateCardPaymentMethodDetails: Boolean, + canUpdateCardExpiryAndBillingDetails: Boolean, canUpdateCardBrandChoice: Boolean, ): PaymentMethodVerticalLayoutInteractor.SavedPaymentMethodAction { return if (savedPaymentMethod?.isModifiable( - canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, canUpdateCardBrandChoice = canUpdateCardBrandChoice, ) == true || canRemove ) { diff --git a/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetFixtures.kt b/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetFixtures.kt index a2865c52697..46977ad36ad 100644 --- a/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetFixtures.kt +++ b/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetFixtures.kt @@ -103,7 +103,7 @@ internal object CustomerSheetFixtures { permissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.Full, canRemoveLastPaymentMethod = true, - canUpdateCardPaymentMethodDetails = true, + canUpdateCardExpiryAndBillingDetails = true, ), defaultPaymentMethodId = null, customerId = customer?.session?.customerId ?: "unused_for_customer_adapter_data_source", diff --git a/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetScreenshotTest.kt b/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetScreenshotTest.kt index 5a4b44a0e80..67af6c055c4 100644 --- a/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetScreenshotTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetScreenshotTest.kt @@ -376,7 +376,7 @@ internal class CustomerSheetScreenshotTest { ): CustomerSheetViewState { return CustomerSheetViewState.UpdatePaymentMethod( updatePaymentMethodInteractor = DefaultUpdatePaymentMethodInteractor( - canUpdateCardPaymentMethodDetails = false, + canUpdateCardExpiryAndBillingDetails = false, canUpdateCardBrandChoice = true, displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), removeExecutor = { null }, diff --git a/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetViewModelTest.kt b/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetViewModelTest.kt index d155557b453..f8ca244529b 100644 --- a/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetViewModelTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetViewModelTest.kt @@ -520,7 +520,7 @@ class CustomerSheetViewModelTest { customerPermissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.Full, canRemoveLastPaymentMethod = false, - canUpdateCardPaymentMethodDetails = false, + canUpdateCardExpiryAndBillingDetails = false, ) ) viewModel.viewState.test { @@ -553,14 +553,14 @@ class CustomerSheetViewModelTest { } @Test - fun `When canUpdateCardPaymentMethodDetails=true, showEditMenu should be true`() = runTest(testDispatcher) { + fun `When canUpdateCardExpiryAndBillingDetails=true, showEditMenu should be true`() = runTest(testDispatcher) { val viewModel = createViewModel( workContext = testDispatcher, customerPaymentMethods = listOf(CARD_PAYMENT_METHOD), customerPermissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.None, canRemoveLastPaymentMethod = false, - canUpdateCardPaymentMethodDetails = true, + canUpdateCardExpiryAndBillingDetails = true, ) ) viewModel.viewState.test { @@ -576,14 +576,14 @@ class CustomerSheetViewModelTest { } @Test - fun `When canUpdateCardPaymentMethodDetails=false, showEditMenu should be false`() = runTest(testDispatcher) { + fun `When canUpdateCardExpiryAndBillingDetails=false, showEditMenu should be false`() = runTest(testDispatcher) { val viewModel = createViewModel( workContext = testDispatcher, customerPaymentMethods = listOf(CARD_PAYMENT_METHOD), customerPermissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.None, canRemoveLastPaymentMethod = false, - canUpdateCardPaymentMethodDetails = false, + canUpdateCardExpiryAndBillingDetails = false, ) ) viewModel.viewState.test { @@ -598,7 +598,7 @@ class CustomerSheetViewModelTest { } @Test - fun `When canUpdateCardPaymentMethodDetails=false, card is cbc eligible, showEditMenu should be true`() = + fun `When canUpdateCardExpiryAndBillingDetails=false, card is cbc eligible, showEditMenu should be true`() = runTest(testDispatcher) { val viewModel = createViewModel( workContext = testDispatcher, @@ -606,7 +606,7 @@ class CustomerSheetViewModelTest { customerPermissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.None, canRemoveLastPaymentMethod = false, - canUpdateCardPaymentMethodDetails = false, + canUpdateCardExpiryAndBillingDetails = false, ), cbcEligibility = CardBrandChoiceEligibility.Eligible( preferredNetworks = listOf(CardBrand.CartesBancaires) @@ -626,7 +626,7 @@ class CustomerSheetViewModelTest { } @Test - fun `When canUpdateFullPaymentMethodDetails=false, expired card is cbc eligible, showEditMenu should be false`() = + fun `When canUpdateCardExpiryAndBillingDetails=false, expired card is cbc eligible, showEditMenu should be false`() = runTest(testDispatcher) { val viewModel = createViewModel( workContext = testDispatcher, @@ -634,7 +634,7 @@ class CustomerSheetViewModelTest { customerPermissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.None, canRemoveLastPaymentMethod = false, - canUpdateFullPaymentMethodDetails = false, + canUpdateCardExpiryAndBillingDetails = false, ), cbcEligibility = CardBrandChoiceEligibility.Eligible( preferredNetworks = listOf(CardBrand.CartesBancaires) @@ -2911,7 +2911,7 @@ class CustomerSheetViewModelTest { permissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.Full, canRemoveLastPaymentMethod = false, - canUpdateCardPaymentMethodDetails = false, + canUpdateCardExpiryAndBillingDetails = false, ) ) @@ -3051,7 +3051,7 @@ class CustomerSheetViewModelTest { customerPermissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.Full, canRemoveLastPaymentMethod = true, - canUpdateCardPaymentMethodDetails = true, + canUpdateCardExpiryAndBillingDetails = true, ), ) @@ -3070,7 +3070,7 @@ class CustomerSheetViewModelTest { customerPermissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.None, canRemoveLastPaymentMethod = false, - canUpdateCardPaymentMethodDetails = false + canUpdateCardExpiryAndBillingDetails = false ), ) @@ -3089,7 +3089,7 @@ class CustomerSheetViewModelTest { customerPermissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.Partial, canRemoveLastPaymentMethod = true, - canUpdateCardPaymentMethodDetails = true, + canUpdateCardExpiryAndBillingDetails = true, ), ) @@ -3112,7 +3112,7 @@ class CustomerSheetViewModelTest { customerPermissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.None, canRemoveLastPaymentMethod = false, - canUpdateCardPaymentMethodDetails = true, + canUpdateCardExpiryAndBillingDetails = true, ), ) @@ -3132,7 +3132,7 @@ class CustomerSheetViewModelTest { customerPermissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.Full, canRemoveLastPaymentMethod = false, - canUpdateCardPaymentMethodDetails = false, + canUpdateCardExpiryAndBillingDetails = false, ), ) @@ -3155,7 +3155,7 @@ class CustomerSheetViewModelTest { customerPermissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.Full, canRemoveLastPaymentMethod = false, - canUpdateCardPaymentMethodDetails = true, + canUpdateCardExpiryAndBillingDetails = true, ), ) @@ -3642,7 +3642,7 @@ class CustomerSheetViewModelTest { permissions: CustomerPermissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.Full, canRemoveLastPaymentMethod = true, - canUpdateCardPaymentMethodDetails = true, + canUpdateCardExpiryAndBillingDetails = true, ) ): CustomerSheetViewModel { return createViewModel( diff --git a/paymentsheet/src/test/java/com/stripe/android/customersheet/data/CustomerAdapterDataSourceTest.kt b/paymentsheet/src/test/java/com/stripe/android/customersheet/data/CustomerAdapterDataSourceTest.kt index 10afda1f85c..e2fca29d70b 100644 --- a/paymentsheet/src/test/java/com/stripe/android/customersheet/data/CustomerAdapterDataSourceTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/customersheet/data/CustomerAdapterDataSourceTest.kt @@ -533,7 +533,7 @@ class CustomerAdapterDataSourceTest { assertThat(customerSheetSession.paymentMethods).containsExactlyElementsIn(paymentMethods) assertThat(customerSheetSession.savedSelection).isEqualTo(SavedSelection.PaymentMethod(id = "pm_1")) assertThat(customerSheetSession.permissions.removePaymentMethod).isEqualTo(PaymentMethodRemovePermission.Full) - assertThat(customerSheetSession.permissions.canUpdateCardPaymentMethodDetails).isFalse() + assertThat(customerSheetSession.permissions.canUpdateCardExpiryAndBillingDetails).isFalse() assertThat(customerSheetSession.paymentMethodSaveConsentBehavior).isEqualTo( PaymentMethodSaveConsentBehavior.Legacy ) diff --git a/paymentsheet/src/test/java/com/stripe/android/customersheet/data/CustomerSessionInitializationDataSourceTest.kt b/paymentsheet/src/test/java/com/stripe/android/customersheet/data/CustomerSessionInitializationDataSourceTest.kt index b2604bc1812..93162dcb6b6 100644 --- a/paymentsheet/src/test/java/com/stripe/android/customersheet/data/CustomerSessionInitializationDataSourceTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/customersheet/data/CustomerSessionInitializationDataSourceTest.kt @@ -124,7 +124,7 @@ class CustomerSessionInitializationDataSourceTest { } @Test - fun `on load, canUpdateCardPaymentMethodDetails should be enabled`() = runTest { + fun `on load, canUpdateCardExpiryAndBillingDetails should be enabled`() = runTest { val dataSource = createInitializationDataSource( elementsSessionManager = FakeCustomerSessionElementsSessionManager( customerSheetComponent = ElementsSession.Customer.Components.CustomerSheet.Disabled, @@ -134,7 +134,7 @@ class CustomerSessionInitializationDataSourceTest { val result = dataSource.loadCustomerSheetSession(createConfiguration()) val customerSheetSession = result.asSuccess().value - assertThat(customerSheetSession.permissions.canUpdateCardPaymentMethodDetails).isTrue() + assertThat(customerSheetSession.permissions.canUpdateCardExpiryAndBillingDetails).isTrue() } @Test diff --git a/paymentsheet/src/test/java/com/stripe/android/customersheet/state/DefaultCustomerSheetLoaderTest.kt b/paymentsheet/src/test/java/com/stripe/android/customersheet/state/DefaultCustomerSheetLoaderTest.kt index 1e5f91852f0..ccd8cca04c8 100644 --- a/paymentsheet/src/test/java/com/stripe/android/customersheet/state/DefaultCustomerSheetLoaderTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/customersheet/state/DefaultCustomerSheetLoaderTest.kt @@ -789,7 +789,7 @@ internal class DefaultCustomerSheetLoaderTest { permissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.Full, canRemoveLastPaymentMethod = true, - canUpdateCardPaymentMethodDetails = true, + canUpdateCardExpiryAndBillingDetails = true, ), defaultPaymentMethodId = defaultPaymentMethodId, customerId = "unused_for_customer_adapter_data_source", diff --git a/paymentsheet/src/test/java/com/stripe/android/customersheet/utils/CustomerSheetTestHelper.kt b/paymentsheet/src/test/java/com/stripe/android/customersheet/utils/CustomerSheetTestHelper.kt index 2bc55037779..1fbcdb20e41 100644 --- a/paymentsheet/src/test/java/com/stripe/android/customersheet/utils/CustomerSheetTestHelper.kt +++ b/paymentsheet/src/test/java/com/stripe/android/customersheet/utils/CustomerSheetTestHelper.kt @@ -66,7 +66,7 @@ internal object CustomerSheetTestHelper { customerPermissions: CustomerPermissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.Full, canRemoveLastPaymentMethod = true, - canUpdateCardPaymentMethodDetails = true, + canUpdateCardExpiryAndBillingDetails = true, ), cbcEligibility: CardBrandChoiceEligibility = CardBrandChoiceEligibility.Ineligible, supportedPaymentMethods: List = listOf( diff --git a/paymentsheet/src/test/java/com/stripe/android/customersheet/utils/FakeCustomerSheetLoader.kt b/paymentsheet/src/test/java/com/stripe/android/customersheet/utils/FakeCustomerSheetLoader.kt index 598e8c2a377..acf02811b4f 100644 --- a/paymentsheet/src/test/java/com/stripe/android/customersheet/utils/FakeCustomerSheetLoader.kt +++ b/paymentsheet/src/test/java/com/stripe/android/customersheet/utils/FakeCustomerSheetLoader.kt @@ -38,7 +38,7 @@ internal class FakeCustomerSheetLoader( private val permissions: CustomerPermissions = CustomerPermissions( removePaymentMethod = PaymentMethodRemovePermission.Full, canRemoveLastPaymentMethod = true, - canUpdateCardPaymentMethodDetails = true, + canUpdateCardExpiryAndBillingDetails = true, ), private val isPaymentMethodSyncDefaultEnabled: Boolean = false, private val passiveCaptchaParams: PassiveCaptchaParams? = null, diff --git a/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadataTest.kt b/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadataTest.kt index f184a2eefe3..6d7ba2b1b7d 100644 --- a/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadataTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadataTest.kt @@ -18,7 +18,7 @@ import org.junit.Test internal class CustomerMetadataTest { @Test - fun `CheckoutSession should not support card details or card brand updates`() { + fun `CheckoutSession should not support card expiry and billing details or card brand updates`() { val metadata = CustomerMetadata.CheckoutSession( sessionId = "cs_123", customerId = "cus_123", @@ -26,7 +26,7 @@ internal class CustomerMetadataTest { saveConsent = PaymentMethodSaveConsentBehavior.Legacy, ) - assertThat(metadata.canUpdateCardPaymentMethodDetails).isFalse() + assertThat(metadata.canUpdateCardExpiryAndBillingDetails).isFalse() assertThat(metadata.canUpdateCardBrandChoice).isFalse() } @@ -339,7 +339,7 @@ internal class CustomerMetadataTest { permissions = CustomerPermissions( removePaymentMethod = removePermission, canRemoveLastPaymentMethod = true, - canUpdateCardPaymentMethodDetails = true + canUpdateCardExpiryAndBillingDetails = true ), defaultPaymentMethodId = null, customerId = "unused_for_customer_adapter_data_source", 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 9b1a1d1a500..9dbc2638103 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 @@ -59,7 +59,7 @@ internal object PaymentMethodMetadataFactory { saveConsent: PaymentMethodSaveConsentBehavior = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod: Boolean = true, - canUpdateCardPaymentMethodDetails: Boolean = false, + canUpdateCardExpiryAndBillingDetails: Boolean = false, customerSessionClientSecret: String? = null, termsDisplay: Map = emptyMap(), forceSetupFutureUseBehaviorAndNewMandate: Boolean = false, @@ -105,7 +105,7 @@ internal object PaymentMethodMetadataFactory { removePaymentMethod = removePaymentMethod, saveConsent = saveConsent, canRemoveLastPaymentMethod = canRemoveLastPaymentMethod, - canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, canUpdateCardBrandChoice = true, ) } else { @@ -116,7 +116,7 @@ internal object PaymentMethodMetadataFactory { removePaymentMethod = removePaymentMethod, saveConsent = saveConsent, canRemoveLastPaymentMethod = canRemoveLastPaymentMethod, - canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, canUpdateCardBrandChoice = true, ) } diff --git a/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/PaymentMethodMetadataFixtures.kt b/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/PaymentMethodMetadataFixtures.kt index b3834cd1312..e9797c70f46 100644 --- a/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/PaymentMethodMetadataFixtures.kt +++ b/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/PaymentMethodMetadataFixtures.kt @@ -16,7 +16,7 @@ internal object PaymentMethodMetadataFixtures { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, - canUpdateCardPaymentMethodDetails = false, + canUpdateCardExpiryAndBillingDetails = false, canUpdateCardBrandChoice = true, ) @@ -39,7 +39,7 @@ internal object PaymentMethodMetadataFixtures { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, - canUpdateCardPaymentMethodDetails = false, + canUpdateCardExpiryAndBillingDetails = false, canUpdateCardBrandChoice = true, ) @@ -49,7 +49,7 @@ internal object PaymentMethodMetadataFixtures { removePaymentMethod: PaymentMethodRemovePermission = PaymentMethodRemovePermission.Full, saveConsent: PaymentMethodSaveConsentBehavior = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod: Boolean = true, - canUpdateCardPaymentMethodDetails: Boolean = false, + canUpdateCardExpiryAndBillingDetails: Boolean = false, ): CustomerMetadata? { return if (hasCustomerConfiguration) { DEFAULT_CUSTOMER_METADATA.copy( @@ -57,7 +57,7 @@ internal object PaymentMethodMetadataFixtures { removePaymentMethod = removePaymentMethod, saveConsent = saveConsent, canRemoveLastPaymentMethod = canRemoveLastPaymentMethod, - canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, ) } else { null @@ -70,7 +70,7 @@ internal object PaymentMethodMetadataFixtures { removePaymentMethod: PaymentMethodRemovePermission = PaymentMethodRemovePermission.Full, saveConsent: PaymentMethodSaveConsentBehavior = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod: Boolean = true, - canUpdateCardPaymentMethodDetails: Boolean = false, + canUpdateCardExpiryAndBillingDetails: Boolean = false, ): StateFlow { return stateFlowOf( getDefaultCustomerMetadata( @@ -79,7 +79,7 @@ internal object PaymentMethodMetadataFixtures { removePaymentMethod = removePaymentMethod, saveConsent = saveConsent, canRemoveLastPaymentMethod = canRemoveLastPaymentMethod, - canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, ) ) } diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/sheet/EmbeddedSheetActivityTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/sheet/EmbeddedSheetActivityTest.kt index d8d9e244dcc..ea21cbfb864 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/sheet/EmbeddedSheetActivityTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/sheet/EmbeddedSheetActivityTest.kt @@ -214,7 +214,7 @@ internal class EmbeddedSheetActivityTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, - canUpdateCardPaymentMethodDetails = false, + canUpdateCardExpiryAndBillingDetails = false, integrationMetadata = IntegrationMetadata.CheckoutSession( id = "cs_test", instancesKey = CheckoutStateFactory.DEFAULT_KEY, @@ -242,7 +242,7 @@ internal class EmbeddedSheetActivityTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, - canUpdateCardPaymentMethodDetails = false, + canUpdateCardExpiryAndBillingDetails = false, ), paymentMethods: List = defaultPaymentMethods(), selection: PaymentSelection? = null, diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/DefaultCustomerStateHolderTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/DefaultCustomerStateHolderTest.kt index d18a2a176d2..345ddc89752 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/DefaultCustomerStateHolderTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/DefaultCustomerStateHolderTest.kt @@ -477,7 +477,7 @@ internal class DefaultCustomerStateHolderTest { removePaymentMethod = paymentMethodRemovePermission, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = canRemoveLastPaymentMethod, - canUpdateCardPaymentMethodDetails = false, + canUpdateCardExpiryAndBillingDetails = false, ) ) diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/SavedPaymentMethodEditabilityTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethodModifiableTest.kt similarity index 93% rename from paymentsheet/src/test/java/com/stripe/android/paymentsheet/SavedPaymentMethodEditabilityTest.kt rename to paymentsheet/src/test/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethodModifiableTest.kt index 3b02dcc3f7c..b603315b756 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/SavedPaymentMethodEditabilityTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethodModifiableTest.kt @@ -34,14 +34,14 @@ class DisplayableSavedPaymentMethodModifiableTest(private val params: IsModifiab "cardExpired=${params.cardExpired}", params.expectedResult, displayableSavedPaymentMethod.isModifiable( - canUpdateCardPaymentMethodDetails = params.canUpdatePaymentMethod, + canUpdateCardExpiryAndBillingDetails = params.canUpdatePaymentMethod, canUpdateCardBrandChoice = params.canUpdateCardBrandChoice, ) ) assertThat( displayableSavedPaymentMethod.isModifiable( - canUpdateCardPaymentMethodDetails = params.canUpdatePaymentMethod, + canUpdateCardExpiryAndBillingDetails = params.canUpdatePaymentMethod, canUpdateCardBrandChoice = params.canUpdateCardBrandChoice, ) ) @@ -49,7 +49,7 @@ class DisplayableSavedPaymentMethodModifiableTest(private val params: IsModifiab assertThat( paymentMethod.isModifiable( - canUpdateCardPaymentMethodDetails = params.canUpdatePaymentMethod, + canUpdateCardExpiryAndBillingDetails = params.canUpdatePaymentMethod, canUpdateCardBrandChoice = params.canUpdateCardBrandChoice, isCbcEligible = params.isCbcEligible, ) @@ -60,7 +60,7 @@ class DisplayableSavedPaymentMethodModifiableTest(private val params: IsModifiab fun `isModifiable returns false for non-card payment methods`() { assertThat( PaymentMethodFixtures.LINK_PAYMENT_METHOD.isModifiable( - canUpdateCardPaymentMethodDetails = true, + canUpdateCardExpiryAndBillingDetails = true, canUpdateCardBrandChoice = true, isCbcEligible = true, ) diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/FakeCustomerStateHolder.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/FakeCustomerStateHolder.kt index 53d2732f3ce..2d2ce12f7e3 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/FakeCustomerStateHolder.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/FakeCustomerStateHolder.kt @@ -20,7 +20,7 @@ internal class FakeCustomerStateHolder : CustomerStateHolder { override val canRemove: StateFlow get() = stateFlowOf(false) - override val canUpdateCardPaymentMethodDetails: StateFlow + override val canUpdateCardExpiryAndBillingDetails: StateFlow get() = stateFlowOf(false) override val canUpdateCardBrandChoice: StateFlow diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/PaymentOptionsStateFactoryTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/PaymentOptionsStateFactoryTest.kt index 251578c0289..d2483021961 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/PaymentOptionsStateFactoryTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/PaymentOptionsStateFactoryTest.kt @@ -137,7 +137,7 @@ class PaymentOptionsStateFactoryTest { .displayableSavedPaymentMethod assertThat( displayableSavedPaymentMethod.isModifiable( - canUpdateCardPaymentMethodDetails = canUpdatePaymentMethod, + canUpdateCardExpiryAndBillingDetails = canUpdatePaymentMethod, canUpdateCardBrandChoice = true, ) ).isEqualTo(expectedResult) diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/SavedPaymentMethodMutatorTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/SavedPaymentMethodMutatorTest.kt index 36e073acf74..9291840a69a 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/SavedPaymentMethodMutatorTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/SavedPaymentMethodMutatorTest.kt @@ -58,7 +58,7 @@ class SavedPaymentMethodMutatorTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, - canUpdateCardPaymentMethodDetails = false, + canUpdateCardExpiryAndBillingDetails = false, ) ) { savedPaymentMethodMutator.canEdit.test { @@ -80,7 +80,7 @@ class SavedPaymentMethodMutatorTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = false, - canUpdateCardPaymentMethodDetails = false, + canUpdateCardExpiryAndBillingDetails = false, ) ) { savedPaymentMethodMutator.canEdit.test { @@ -237,7 +237,7 @@ class SavedPaymentMethodMutatorTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, - canUpdateCardPaymentMethodDetails = false, + canUpdateCardExpiryAndBillingDetails = false, ) ) { val customerPaymentMethods = PaymentMethodFixtures.createCards(1) @@ -267,7 +267,7 @@ class SavedPaymentMethodMutatorTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, - canUpdateCardPaymentMethodDetails = true, + canUpdateCardExpiryAndBillingDetails = true, ) ) { val cards = PaymentMethodFixtures.createCards(3) @@ -293,7 +293,7 @@ class SavedPaymentMethodMutatorTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = false, - canUpdateCardPaymentMethodDetails = true, + canUpdateCardExpiryAndBillingDetails = true, ) ) { val cards = PaymentMethodFixtures.createCards(1) diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/repositories/DefaultSavedPaymentMethodRepositoryTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/repositories/DefaultSavedPaymentMethodRepositoryTest.kt index 3a21f7501d7..da5ae6e5ec8 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/repositories/DefaultSavedPaymentMethodRepositoryTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/repositories/DefaultSavedPaymentMethodRepositoryTest.kt @@ -294,7 +294,7 @@ class DefaultSavedPaymentMethodRepositoryTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, - canUpdateCardPaymentMethodDetails = false, + canUpdateCardExpiryAndBillingDetails = false, canUpdateCardBrandChoice = true, ) @@ -305,7 +305,7 @@ class DefaultSavedPaymentMethodRepositoryTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, - canUpdateCardPaymentMethodDetails = false, + canUpdateCardExpiryAndBillingDetails = false, canUpdateCardBrandChoice = true, ) } diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/CreateCustomerStateTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/CreateCustomerStateTest.kt index 73f141f8980..02ff9507190 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/CreateCustomerStateTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/CreateCustomerStateTest.kt @@ -272,7 +272,7 @@ internal class CreateCustomerStateTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Enabled, canRemoveLastPaymentMethod = true, - canUpdateCardPaymentMethodDetails = true, + canUpdateCardExpiryAndBillingDetails = true, canUpdateCardBrandChoice = true, ) @@ -283,7 +283,7 @@ internal class CreateCustomerStateTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, - canUpdateCardPaymentMethodDetails = false, + canUpdateCardExpiryAndBillingDetails = false, canUpdateCardBrandChoice = true, ) diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultAnalyticsMetadataFactoryTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultAnalyticsMetadataFactoryTest.kt index c4053f90332..fd453ef2bea 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultAnalyticsMetadataFactoryTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultAnalyticsMetadataFactoryTest.kt @@ -839,7 +839,7 @@ class DefaultAnalyticsMetadataFactoryTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, - canUpdateCardPaymentMethodDetails = true, + canUpdateCardExpiryAndBillingDetails = true, canUpdateCardBrandChoice = true, ) 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 a3602a625a7..b5a3e1296df 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 @@ -165,7 +165,7 @@ internal class DefaultPaymentElementLoaderTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, - canUpdateCardPaymentMethodDetails = false, + canUpdateCardExpiryAndBillingDetails = false, clientAttributionMetadata = ClientAttributionMetadata( elementsSessionConfigId = DEFAULT_ELEMENTS_SESSION_CONFIG_ID, paymentIntentCreationFlow = PaymentIntentCreationFlow.Standard, @@ -2850,7 +2850,7 @@ internal class DefaultPaymentElementLoaderTest { .isEqualTo(PaymentMethodSaveConsentBehavior.Disabled(overrideAllowRedisplay = null)) assertThat(state.paymentMethodMetadata.customerMetadata?.canRemoveLastPaymentMethod) .isEqualTo(true) - assertThat(state.paymentMethodMetadata.customerMetadata?.canUpdateCardPaymentMethodDetails) + assertThat(state.paymentMethodMetadata.customerMetadata?.canUpdateCardExpiryAndBillingDetails) .isEqualTo(true) consumeLoadingEvents() @@ -2901,7 +2901,7 @@ internal class DefaultPaymentElementLoaderTest { .isEqualTo(PaymentMethodSaveConsentBehavior.Disabled(overrideAllowRedisplay = null)) assertThat(state.paymentMethodMetadata.customerMetadata?.canRemoveLastPaymentMethod) .isEqualTo(true) - assertThat(state.paymentMethodMetadata.customerMetadata?.canUpdateCardPaymentMethodDetails) + assertThat(state.paymentMethodMetadata.customerMetadata?.canUpdateCardExpiryAndBillingDetails) .isEqualTo(true) consumeLoadingEvents() @@ -2952,7 +2952,7 @@ internal class DefaultPaymentElementLoaderTest { .isEqualTo(PaymentMethodSaveConsentBehavior.Disabled(overrideAllowRedisplay = null)) assertThat(state.paymentMethodMetadata.customerMetadata?.canRemoveLastPaymentMethod) .isEqualTo(true) - assertThat(state.paymentMethodMetadata.customerMetadata?.canUpdateCardPaymentMethodDetails) + assertThat(state.paymentMethodMetadata.customerMetadata?.canUpdateCardExpiryAndBillingDetails) .isEqualTo(true) consumeLoadingEvents() @@ -3003,7 +3003,7 @@ internal class DefaultPaymentElementLoaderTest { .isEqualTo(PaymentMethodSaveConsentBehavior.Disabled(overrideAllowRedisplay = null)) assertThat(state.paymentMethodMetadata.customerMetadata?.canRemoveLastPaymentMethod) .isEqualTo(true) - assertThat(state.paymentMethodMetadata.customerMetadata?.canUpdateCardPaymentMethodDetails) + assertThat(state.paymentMethodMetadata.customerMetadata?.canUpdateCardExpiryAndBillingDetails) .isEqualTo(true) consumeLoadingEvents() @@ -3013,7 +3013,7 @@ internal class DefaultPaymentElementLoaderTest { } @Test - fun `customer session should have canUpdateCardPaymentMethodDetails permission enabled`() = + fun `customer session should have canUpdateCardExpiryAndBillingDetails permission enabled`() = runScenario { val loader = createPaymentElementLoader( customer = createElementsSessionCustomer( @@ -3054,7 +3054,7 @@ internal class DefaultPaymentElementLoaderTest { .isEqualTo(PaymentMethodSaveConsentBehavior.Disabled(overrideAllowRedisplay = null)) assertThat(state.paymentMethodMetadata.customerMetadata?.canRemoveLastPaymentMethod) .isEqualTo(true) - assertThat(state.paymentMethodMetadata.customerMetadata?.canUpdateCardPaymentMethodDetails) + assertThat(state.paymentMethodMetadata.customerMetadata?.canUpdateCardExpiryAndBillingDetails) .isEqualTo(true) consumeLoadingEvents() @@ -3088,7 +3088,7 @@ internal class DefaultPaymentElementLoaderTest { .isEqualTo(PaymentMethodSaveConsentBehavior.Legacy) assertThat(state.paymentMethodMetadata.customerMetadata?.canRemoveLastPaymentMethod) .isEqualTo(true) - assertThat(state.paymentMethodMetadata.customerMetadata?.canUpdateCardPaymentMethodDetails) + assertThat(state.paymentMethodMetadata.customerMetadata?.canUpdateCardExpiryAndBillingDetails) .isEqualTo(false) consumeLoadingEvents() diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultPaymentMethodFilterTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultPaymentMethodFilterTest.kt index 1a2527c2d6d..806bd95c128 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultPaymentMethodFilterTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultPaymentMethodFilterTest.kt @@ -216,7 +216,7 @@ class DefaultPaymentMethodFilterTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = false, - canUpdateCardPaymentMethodDetails = false, + canUpdateCardExpiryAndBillingDetails = false, canUpdateCardBrandChoice = true, ), remoteDefaultPaymentMethodId = remoteDefaultPaymentMethodId, diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultRetrieveCustomerEmailTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultRetrieveCustomerEmailTest.kt index 1c092956ccd..851a09f91ea 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultRetrieveCustomerEmailTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultRetrieveCustomerEmailTest.kt @@ -157,7 +157,7 @@ internal class DefaultRetrieveCustomerEmailTest { removePaymentMethod = PaymentMethodRemovePermission.None, saveConsent = PaymentMethodSaveConsentBehavior.Disabled(overrideAllowRedisplay = null), canRemoveLastPaymentMethod = false, - canUpdateCardPaymentMethodDetails = false, + canUpdateCardExpiryAndBillingDetails = false, canUpdateCardBrandChoice = true, ) @@ -168,7 +168,7 @@ internal class DefaultRetrieveCustomerEmailTest { removePaymentMethod = PaymentMethodRemovePermission.Full, saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, - canUpdateCardPaymentMethodDetails = false, + canUpdateCardExpiryAndBillingDetails = false, canUpdateCardBrandChoice = true, ) diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/DefaultUpdatePaymentMethodInteractorTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/DefaultUpdatePaymentMethodInteractorTest.kt index 7f7e0129eac..7eff5778e12 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/DefaultUpdatePaymentMethodInteractorTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/DefaultUpdatePaymentMethodInteractorTest.kt @@ -551,12 +551,12 @@ class DefaultUpdatePaymentMethodInteractorTest { } @Test - fun shouldCreateEditCardInteractorCorrectly_whenCbcEligible_andCanUpdateCardPaymentMethodDetails() { + fun shouldCreateEditCardInteractorCorrectly_whenCbcEligible_andCanUpdateCardExpiryAndBillingDetails() { val displayableSavedPaymentMethod = PaymentMethodFixtures.CARD_WITH_NETWORKS_PAYMENT_METHOD .toDisplayableSavedPaymentMethod() runScenario( displayableSavedPaymentMethod = displayableSavedPaymentMethod, - canUpdateCardPaymentMethodDetails = true, + canUpdateCardExpiryAndBillingDetails = true, canUpdateCardBrandChoice = true, ) { val state = interactor.editCardDetailsInteractor.state.value @@ -572,7 +572,7 @@ class DefaultUpdatePaymentMethodInteractorTest { .toDisplayableSavedPaymentMethod() runScenario( displayableSavedPaymentMethod = displayableSavedPaymentMethod, - canUpdateCardPaymentMethodDetails = true, + canUpdateCardExpiryAndBillingDetails = true, canUpdateCardBrandChoice = false, ) { val state = interactor.editCardDetailsInteractor.state.value @@ -583,12 +583,12 @@ class DefaultUpdatePaymentMethodInteractorTest { } @Test - fun shouldCreateEditCardInteractorCorrectly_whenCbcEligible_andCanNotUpdateCardPaymentMethodDetails() { + fun shouldCreateEditCardInteractorCorrectly_whenCbcEligible_andCanNotUpdateCardExpiryAndBillingDetails() { val displayableSavedPaymentMethod = PaymentMethodFixtures.CARD_WITH_NETWORKS_PAYMENT_METHOD .toDisplayableSavedPaymentMethod() runScenario( displayableSavedPaymentMethod = displayableSavedPaymentMethod, - canUpdateCardPaymentMethodDetails = false, + canUpdateCardExpiryAndBillingDetails = false, canUpdateCardBrandChoice = true, ) { val state = interactor.editCardDetailsInteractor.state.value @@ -599,9 +599,9 @@ class DefaultUpdatePaymentMethodInteractorTest { } @Test - fun shouldCreateEditCardInteractorCorrectly_whenCbcIneligible_andCanUpdateCardPaymentMethodDetails() { + fun shouldCreateEditCardInteractorCorrectly_whenCbcIneligible_andCanUpdateCardExpiryAndBillingDetails() { runScenario( - canUpdateCardPaymentMethodDetails = true, + canUpdateCardExpiryAndBillingDetails = true, canUpdateCardBrandChoice = true, ) { val state = interactor.editCardDetailsInteractor.state.value @@ -612,9 +612,9 @@ class DefaultUpdatePaymentMethodInteractorTest { } @Test - fun shouldCreateEditCardInteractorCorrectly_whenCbcIneligible_andCanNotUpdateCardPaymentMethodDetails() { + fun shouldCreateEditCardInteractorCorrectly_whenCbcIneligible_andCanNotUpdateCardExpiryAndBillingDetails() { runScenario( - canUpdateCardPaymentMethodDetails = false, + canUpdateCardExpiryAndBillingDetails = false, canUpdateCardBrandChoice = true, ) { val state = interactor.editCardDetailsInteractor.state.value @@ -772,7 +772,7 @@ class DefaultUpdatePaymentMethodInteractorTest { onSetDefaultPaymentMethod: (PaymentMethod) -> Result = { _ -> notImplemented() }, shouldShowSetAsDefaultCheckbox: Boolean = false, isDefaultPaymentMethod: Boolean = false, - canUpdateCardPaymentMethodDetails: Boolean = false, + canUpdateCardExpiryAndBillingDetails: Boolean = false, canUpdateCardBrandChoice: Boolean, addressCollectionMode: AddressCollectionMode = AddressCollectionMode.Automatic, allowedBillingCountries: Set = setOf("US", "CA"), @@ -785,7 +785,7 @@ class DefaultUpdatePaymentMethodInteractorTest { val interactor = DefaultUpdatePaymentMethodInteractor( isLiveMode = isLiveMode, canRemove = canRemove, - canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, canUpdateCardBrandChoice = canUpdateCardBrandChoice, displayableSavedPaymentMethod = displayableSavedPaymentMethod, addressCollectionMode = addressCollectionMode, diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/FakeUpdatePaymentMethodInteractor.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/FakeUpdatePaymentMethodInteractor.kt index b6cd253462a..8eb8d1ebc32 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/FakeUpdatePaymentMethodInteractor.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/FakeUpdatePaymentMethodInteractor.kt @@ -37,7 +37,7 @@ internal class FakeUpdatePaymentMethodInteractor( isSaveButtonEnabled = false, ), override val setAsDefaultCheckboxEnabled: Boolean = true, - override val canUpdateCardPaymentMethodDetails: Boolean = false, + override val canUpdateCardExpiryAndBillingDetails: Boolean = false, override val canUpdateCardBrandChoice: Boolean, private val editCardDetailsInteractorFactory: EditCardDetailsInteractor.Factory = DefaultEditCardDetailsInteractor .Factory(), @@ -48,7 +48,7 @@ internal class FakeUpdatePaymentMethodInteractor( ) override val editCardDetailsInteractor: EditCardDetailsInteractor by lazy { val isModifiable = displayableSavedPaymentMethod.isModifiable( - canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, canUpdateCardBrandChoice = canUpdateCardBrandChoice, ) editCardDetailsInteractorFactory.create( @@ -58,7 +58,7 @@ internal class FakeUpdatePaymentMethodInteractor( isCbcModifiable = isModifiable && canUpdateCardBrandChoice && displayableSavedPaymentMethod.canChangeCbc(), - areExpiryDateAndAddressModificationSupported = isModifiable && canUpdateCardPaymentMethodDetails + areExpiryDateAndAddressModificationSupported = isModifiable && canUpdateCardExpiryAndBillingDetails ), requiresModification = true, payload = EditCardPayload.create( diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentSheetScreenUpdatePaymentMethodScreenshotTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentSheetScreenUpdatePaymentMethodScreenshotTest.kt index c03c090b6d6..3bcf1857d3f 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentSheetScreenUpdatePaymentMethodScreenshotTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentSheetScreenUpdatePaymentMethodScreenshotTest.kt @@ -114,7 +114,7 @@ internal class PaymentSheetScreenUpdatePaymentMethodScreenshotTest { .toDisplayableSavedPaymentMethod(), canRemove = true, shouldShowSetAsDefaultCheckbox = true, - canUpdateCardPaymentMethodDetails = true, + canUpdateCardExpiryAndBillingDetails = true, addressCollectionMode = AddressCollectionMode.Automatic ) } @@ -130,7 +130,7 @@ internal class PaymentSheetScreenUpdatePaymentMethodScreenshotTest { isModifiablePaymentMethod = true, canRemove = true, shouldShowSetAsDefaultCheckbox = true, - canUpdateCardPaymentMethodDetails = true, + canUpdateCardExpiryAndBillingDetails = true, addressCollectionMode = AddressCollectionMode.Full, ) } @@ -146,7 +146,7 @@ internal class PaymentSheetScreenUpdatePaymentMethodScreenshotTest { isModifiablePaymentMethod = true, canRemove = true, shouldShowSetAsDefaultCheckbox = true, - canUpdateCardPaymentMethodDetails = true, + canUpdateCardExpiryAndBillingDetails = true, addressCollectionMode = AddressCollectionMode.Never, ) } @@ -162,7 +162,7 @@ internal class PaymentSheetScreenUpdatePaymentMethodScreenshotTest { isModifiablePaymentMethod = true, canRemove = true, shouldShowSetAsDefaultCheckbox = true, - canUpdateCardPaymentMethodDetails = true, + canUpdateCardExpiryAndBillingDetails = true, addressCollectionMode = AddressCollectionMode.Automatic, ) } @@ -178,7 +178,7 @@ internal class PaymentSheetScreenUpdatePaymentMethodScreenshotTest { isModifiablePaymentMethod = true, canRemove = true, shouldShowSetAsDefaultCheckbox = false, - canUpdateCardPaymentMethodDetails = true, + canUpdateCardExpiryAndBillingDetails = true, addressCollectionMode = AddressCollectionMode.Full, useDefaultBillingDetails = false, validating = true, @@ -204,7 +204,7 @@ internal class PaymentSheetScreenUpdatePaymentMethodScreenshotTest { isExpiredCard: Boolean = false, error: String? = null, shouldShowSetAsDefaultCheckbox: Boolean = false, - canUpdateCardPaymentMethodDetails: Boolean = false, + canUpdateCardExpiryAndBillingDetails: Boolean = false, addressCollectionMode: AddressCollectionMode = AddressCollectionMode.Never, useDefaultBillingDetails: Boolean = true, validating: Boolean = false, @@ -226,7 +226,7 @@ internal class PaymentSheetScreenUpdatePaymentMethodScreenshotTest { useDefaultBillingDetails = useDefaultBillingDetails, shouldShowSaveButton = isModifiablePaymentMethod || shouldShowSetAsDefaultCheckbox, addressCollectionMode = addressCollectionMode, - canUpdateCardPaymentMethodDetails = canUpdateCardPaymentMethodDetails, + canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, canUpdateCardBrandChoice = true, ).apply { if (validating) { 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 3bc4e91d540..a2383a574bb 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 @@ -1812,7 +1812,7 @@ class DefaultPaymentMethodVerticalLayoutInteractorTest { formTypeForCode: (code: String) -> FormHelper.FormType = { FormHelper.FormType.Empty }, initialPaymentMethods: List = emptyList(), initialMostRecentlySelectedSavedPaymentMethod: PaymentMethod? = null, - canUpdateCardPaymentMethodDetails: Boolean = false, + canUpdateCardExpiryAndBillingDetails: Boolean = false, canUpdateCardBrandChoice: Boolean = true, shouldUpdateVerticalModeSelection: (String?) -> Boolean = { paymentMethodCode -> val requiresFormScreen = paymentMethodCode != null && @@ -1865,7 +1865,7 @@ class DefaultPaymentMethodVerticalLayoutInteractorTest { mostRecentlySelectedSavedPaymentMethod = mostRecentlySelectedSavedPaymentMethod, canRemove = canRemove, walletsState = walletsState, - canUpdateCardPaymentMethodDetails = stateFlowOf(canUpdateCardPaymentMethodDetails), + canUpdateCardExpiryAndBillingDetails = stateFlowOf(canUpdateCardExpiryAndBillingDetails), canUpdateCardBrandChoice = stateFlowOf(canUpdateCardBrandChoice), updateSelection = { paymentSelection, isFormScreen -> selection.value = paymentSelection From 90eef4b1c6a926472dab15ac97b0f713a44a4e4a Mon Sep 17 00:00:00 2001 From: Chengtin Tsai Date: Mon, 6 Jul 2026 13:45:58 -0700 Subject: [PATCH 5/7] Combine canUpdateCardBrandChoice and isCbcEligible into canChangeCbc Committed-By-Agent: claude --- .../customersheet/CustomerSheetViewModel.kt | 5 +- .../customersheet/CustomerSheetViewState.kt | 7 +- .../customersheet/ui/CustomerSheetScreen.kt | 1 - .../embedded/EmbeddedCommonModule.kt | 3 +- .../embedded/content/EmbeddedContentHelper.kt | 2 +- .../EmbeddedUpdateScreenInteractorFactory.kt | 2 +- .../manage/InitialManageScreenFactory.kt | 2 - .../paymentsheet/CustomerStateHolder.kt | 2 +- .../DefaultCustomerStateHolder.kt | 15 ++- .../DisplayableSavedPaymentMethod.kt | 18 ---- .../PaymentOptionsStateFactory.kt | 4 - .../SavedPaymentMethodEditability.kt | 16 +--- .../paymentsheet/SavedPaymentMethodMutator.kt | 12 +-- .../ui/UpdatePaymentMethodInteractor.kt | 18 ++-- .../paymentsheet/ui/UpdatePaymentMethodUI.kt | 2 +- .../PaymentMethodVerticalLayoutInteractor.kt | 21 +++-- .../SavedPaymentMethodsExtension.kt | 2 - .../viewmodels/PaymentOptionsItemsMapper.kt | 2 - .../CustomerSheetScreenshotTest.kt | 3 +- .../CustomerSheetViewModelTest.kt | 1 - .../android/model/PaymentMethodFixtures.kt | 1 - .../DefaultEmbeddedContentHelperTest.kt | 1 + .../DefaultEmbeddedSheetLauncherTest.kt | 3 +- .../content/DefaultEmbeddedStateHelperTest.kt | 1 + .../embedded/content/EmbeddedContentUiTest.kt | 1 + .../embedded/manage/EmbeddedNavigatorTest.kt | 16 ++-- .../manage/InitialManageScreenFactoryTest.kt | 3 +- .../DefaultCustomerStateHolderTest.kt | 1 + ...layableSavedPaymentMethodModifiableTest.kt | 55 +++-------- .../DisplayableSavedPaymentMethodTest.kt | 13 --- .../paymentsheet/FakeCustomerStateHolder.kt | 2 +- .../PaymentOptionsStateFactoryTest.kt | 17 ++-- .../SavedPaymentMethodMutatorTest.kt | 2 + ...ManageSavedPaymentMethodsScreenshotTest.kt | 2 - ...SelectSavedPaymentMethodsInteractorTest.kt | 1 - ...efaultUpdatePaymentMethodInteractorTest.kt | 94 +++++++++---------- .../ui/FakeUpdatePaymentMethodInteractor.kt | 12 ++- .../ui/PaymentOptionsScreenshotTest.kt | 2 - ...ScreenUpdatePaymentMethodScreenshotTest.kt | 2 +- .../ui/UpdatePaymentMethodUIScreenshotTest.kt | 2 +- .../ui/UpdatePaymentMethodUITest.kt | 2 +- ...ymentMethodVerticalLayoutInteractorTest.kt | 4 +- .../VerticalModeInitialScreenFactoryTest.kt | 3 +- .../PaymentOptionsItemsMapperTest.kt | 3 - 44 files changed, 153 insertions(+), 228 deletions(-) diff --git a/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewModel.kt b/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewModel.kt index 662aac8254f..a80ce4dfab7 100644 --- a/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewModel.kt +++ b/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewModel.kt @@ -211,7 +211,6 @@ internal class CustomerSheetViewModel( isEditing = userCanEditAndIsEditing, isProcessing = selectionConfirmationState.isConfirming, errorMessage = selectionConfirmationState.error, - isCbcEligible = customerState.cbcEligibility is CardBrandChoiceEligibility.Eligible, canEdit = customerState.canEdit, mandateText = paymentSelection?.mandateText( merchantName = configuration.merchantDisplayName, @@ -571,7 +570,7 @@ internal class CustomerSheetViewModel( isLiveMode = isLiveMode, canRemove = customerState.canRemove, canUpdateCardExpiryAndBillingDetails = customerState.canUpdateCardExpiryAndBillingDetails, - canUpdateCardBrandChoice = true, + canChangeCbc = customerState.cbcEligibility is CardBrandChoiceEligibility.Eligible, displayableSavedPaymentMethod = paymentMethod, addressCollectionMode = configuration.billingDetailsCollectionConfiguration.address, allowedBillingCountries = @@ -1281,8 +1280,8 @@ internal class CustomerSheetViewModel( val canEdit = canRemove || paymentMethods.any { method -> isModifiable( paymentMethod = method, - cbcEligibility = cbcEligibility, canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, + canChangeCbc = cbcEligibility is CardBrandChoiceEligibility.Eligible, ) } diff --git a/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewState.kt b/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewState.kt index fd297b4efd6..5d899418fcf 100644 --- a/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewState.kt +++ b/paymentsheet/src/main/java/com/stripe/android/customersheet/CustomerSheetViewState.kt @@ -16,7 +16,6 @@ import com.stripe.android.paymentsheet.ui.PaymentSheetTopBarState import com.stripe.android.paymentsheet.ui.PaymentSheetTopBarStateFactory import com.stripe.android.paymentsheet.ui.PrimaryButton import com.stripe.android.paymentsheet.ui.UpdatePaymentMethodInteractor -import com.stripe.android.ui.core.cbc.CardBrandChoiceEligibility import com.stripe.android.uicore.elements.FormElement internal sealed class CustomerSheetViewState( @@ -67,7 +66,6 @@ internal sealed class CustomerSheetViewState( val canRemovePaymentMethods: Boolean, val errorMessage: String? = null, val mandateText: ResolvableString? = null, - val isCbcEligible: Boolean, ) : CustomerSheetViewState( isLiveMode = isLiveMode, isProcessing = isProcessing, @@ -143,12 +141,11 @@ internal sealed class CustomerSheetViewState( internal fun isModifiable( paymentMethod: PaymentMethod, - cbcEligibility: CardBrandChoiceEligibility, canUpdateCardExpiryAndBillingDetails: Boolean, + canChangeCbc: Boolean, ): Boolean { return paymentMethod.isModifiable( canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, - canUpdateCardBrandChoice = true, - isCbcEligible = cbcEligibility is CardBrandChoiceEligibility.Eligible, + canChangeCbc = canChangeCbc, ) } 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 25a761444d6..6780e3c66da 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 @@ -156,7 +156,6 @@ internal fun SelectPaymentMethod( linkBrand = LinkBrand.Link, currentSelection = viewState.paymentSelection, nameProvider = paymentMethodNameProvider, - isCbcEligible = viewState.isCbcEligible, defaultPaymentMethodId = null ) diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/EmbeddedCommonModule.kt b/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/EmbeddedCommonModule.kt index c4396ab38d3..2e4e29d7799 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/EmbeddedCommonModule.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/EmbeddedCommonModule.kt @@ -127,7 +127,8 @@ internal interface EmbeddedCommonModule { return DefaultCustomerStateHolder( savedStateHandle = savedStateHandle, selection = selectionHolder.selection, - customerMetadata = customerMetadata + customerMetadata = customerMetadata, + paymentMethodMetadataFlow = paymentMethodMetadataFlow, ) } diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/content/EmbeddedContentHelper.kt b/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/content/EmbeddedContentHelper.kt index cd7e2c4add6..94281699b1f 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/content/EmbeddedContentHelper.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/content/EmbeddedContentHelper.kt @@ -253,7 +253,7 @@ internal class DefaultEmbeddedContentHelper @Inject constructor( mostRecentlySelectedSavedPaymentMethod = customerStateHolder.mostRecentlySelectedSavedPaymentMethod, canRemove = customerStateHolder.canRemove, canUpdateCardExpiryAndBillingDetails = customerStateHolder.canUpdateCardExpiryAndBillingDetails, - canUpdateCardBrandChoice = customerStateHolder.canUpdateCardBrandChoice, + canChangeCbc = customerStateHolder.canChangeCbc, walletsState = walletsState, updateSelection = { updatedSelection, requiresConfirmation -> setSelection(updatedSelection) diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/manage/EmbeddedUpdateScreenInteractorFactory.kt b/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/manage/EmbeddedUpdateScreenInteractorFactory.kt index accf1b1b100..afcdceb58e1 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/manage/EmbeddedUpdateScreenInteractorFactory.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/manage/EmbeddedUpdateScreenInteractorFactory.kt @@ -34,7 +34,7 @@ internal class DefaultEmbeddedUpdateScreenInteractorFactory @Inject constructor( isLiveMode = paymentMethodMetadata.stripeIntent.isLiveMode, canRemove = customerStateHolder.canRemove.value, canUpdateCardExpiryAndBillingDetails = customerStateHolder.canUpdateCardExpiryAndBillingDetails.value, - canUpdateCardBrandChoice = customerStateHolder.canUpdateCardBrandChoice.value, + canChangeCbc = customerStateHolder.canChangeCbc.value, displayableSavedPaymentMethod = displayableSavedPaymentMethod, cardBrandFilter = paymentMethodMetadata.cardBrandFilter, addressCollectionMode = paymentMethodMetadata.billingDetailsCollectionConfiguration.address, diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/manage/InitialManageScreenFactory.kt b/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/manage/InitialManageScreenFactory.kt index 0d694b70a3b..9d486381aeb 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/manage/InitialManageScreenFactory.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentelement/embedded/manage/InitialManageScreenFactory.kt @@ -5,7 +5,6 @@ import com.stripe.android.lpmfoundations.paymentmethod.PaymentMethodMetadata import com.stripe.android.paymentelement.embedded.sheet.EmbeddedNavigator import com.stripe.android.paymentsheet.CustomerStateHolder import com.stripe.android.paymentsheet.DisplayableSavedPaymentMethod -import com.stripe.android.ui.core.cbc.CardBrandChoiceEligibility import javax.inject.Inject internal class InitialManageScreenFactory @Inject constructor( @@ -24,7 +23,6 @@ internal class InitialManageScreenFactory @Inject constructor( val displayableSavedPaymentMethod = DisplayableSavedPaymentMethod.create( displayName = displayName, paymentMethod = paymentMethod, - isCbcEligible = paymentMethodMetadata.cbcEligibility is CardBrandChoiceEligibility.Eligible, ) EmbeddedNavigator.Screen.ManageUpdate( interactor = updateScreenInteractorFactory.createUpdateScreenInteractor( diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/CustomerStateHolder.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/CustomerStateHolder.kt index 49fd29e023a..f5ad8684282 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/CustomerStateHolder.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/CustomerStateHolder.kt @@ -23,7 +23,7 @@ internal interface CustomerStateHolder { val canUpdateCardExpiryAndBillingDetails: StateFlow - val canUpdateCardBrandChoice: StateFlow + val canChangeCbc: StateFlow fun setCustomerState(customerState: CustomerState?) diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DefaultCustomerStateHolder.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DefaultCustomerStateHolder.kt index 3fe582ac020..1478c707017 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DefaultCustomerStateHolder.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DefaultCustomerStateHolder.kt @@ -2,17 +2,20 @@ package com.stripe.android.paymentsheet import androidx.lifecycle.SavedStateHandle import com.stripe.android.lpmfoundations.paymentmethod.CustomerMetadata +import com.stripe.android.lpmfoundations.paymentmethod.PaymentMethodMetadata import com.stripe.android.model.PaymentMethod import com.stripe.android.paymentsheet.CustomerStateHolder.Companion.SAVED_CUSTOMER import com.stripe.android.paymentsheet.model.PaymentSelection import com.stripe.android.paymentsheet.state.CustomerState import com.stripe.android.paymentsheet.viewmodels.BaseSheetViewModel +import com.stripe.android.ui.core.cbc.CardBrandChoiceEligibility import com.stripe.android.uicore.utils.combineAsStateFlow import com.stripe.android.uicore.utils.mapAsStateFlow import kotlinx.coroutines.flow.StateFlow internal class DefaultCustomerStateHolder( private val customerMetadata: StateFlow, + private val paymentMethodMetadataFlow: StateFlow, private val savedStateHandle: SavedStateHandle, private val selection: StateFlow, ) : CustomerStateHolder { @@ -52,8 +55,13 @@ internal class DefaultCustomerStateHolder( it?.canUpdateCardExpiryAndBillingDetails ?: false } - override val canUpdateCardBrandChoice: StateFlow = customerMetadata.mapAsStateFlow { - it?.canUpdateCardBrandChoice ?: false + override val canChangeCbc: StateFlow = combineAsStateFlow( + customerMetadata, + paymentMethodMetadataFlow, + ) { metadata, pmMetadata -> + val canUpdateBrandChoice = metadata?.canUpdateCardBrandChoice ?: false + val isCbcEligible = pmMetadata?.cbcEligibility is CardBrandChoiceEligibility.Eligible + canUpdateBrandChoice && isCbcEligible } override fun setCustomerState(customerState: CustomerState?) { @@ -116,7 +124,8 @@ internal class DefaultCustomerStateHolder( selection = viewModel.selection, customerMetadata = viewModel.paymentMethodMetadata.mapAsStateFlow { it?.customerMetadata - } + }, + paymentMethodMetadataFlow = viewModel.paymentMethodMetadata, ) } } diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethod.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethod.kt index a005d3c92c0..71499d4a96e 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethod.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethod.kt @@ -10,7 +10,6 @@ internal data class DisplayableSavedPaymentMethod private constructor( val displayName: ResolvableString, val paymentMethod: PaymentMethod, val savedPaymentMethod: SavedPaymentMethod, - val isCbcEligible: Boolean = false, val shouldShowDefaultBadge: Boolean = false, ) { val isCard: Boolean @@ -27,21 +26,6 @@ internal data class DisplayableSavedPaymentMethod private constructor( SavedPaymentMethod.Unexpected -> false } - fun canChangeCbc(): Boolean { - return paymentMethod.canChangeCbc(isCbcEligible) - } - - fun isModifiable( - canUpdateCardExpiryAndBillingDetails: Boolean, - canUpdateCardBrandChoice: Boolean, - ): Boolean { - return paymentMethod.isModifiable( - canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, - canUpdateCardBrandChoice = canUpdateCardBrandChoice, - isCbcEligible = isCbcEligible, - ) - } - fun getDescription() = when (savedPaymentMethod) { is SavedPaymentMethod.Card -> { resolvableString( @@ -116,7 +100,6 @@ internal data class DisplayableSavedPaymentMethod private constructor( fun create( displayName: ResolvableString, paymentMethod: PaymentMethod, - isCbcEligible: Boolean = false, shouldShowDefaultBadge: Boolean = false, ): DisplayableSavedPaymentMethod { val savedPaymentMethod = when (paymentMethod.type) { @@ -145,7 +128,6 @@ internal data class DisplayableSavedPaymentMethod private constructor( displayName = displayName, paymentMethod = paymentMethod, savedPaymentMethod = savedPaymentMethod ?: SavedPaymentMethod.Unexpected, - isCbcEligible = isCbcEligible, shouldShowDefaultBadge = shouldShowDefaultBadge, ) } diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/PaymentOptionsStateFactory.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/PaymentOptionsStateFactory.kt index 3c912edcc00..6598dad98a6 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/PaymentOptionsStateFactory.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/PaymentOptionsStateFactory.kt @@ -19,7 +19,6 @@ internal object PaymentOptionsStateFactory { showLink: Boolean, linkBrand: LinkBrand, nameProvider: (PaymentMethodCode?) -> ResolvableString, - isCbcEligible: Boolean, defaultPaymentMethodId: String?, ): List { return listOfNotNull( @@ -31,7 +30,6 @@ internal object PaymentOptionsStateFactory { DisplayableSavedPaymentMethod.create( displayName = nameProvider(it.type?.code), paymentMethod = it, - isCbcEligible = isCbcEligible, shouldShowDefaultBadge = it.id == defaultPaymentMethodId, ), ) @@ -54,7 +52,6 @@ internal object PaymentOptionsStateFactory { linkBrand: LinkBrand, currentSelection: PaymentSelection?, nameProvider: (PaymentMethodCode?) -> ResolvableString, - isCbcEligible: Boolean, defaultPaymentMethodId: String? ): PaymentOptionsState { val items = createPaymentOptionsList( @@ -63,7 +60,6 @@ internal object PaymentOptionsStateFactory { showLink = showLink, linkBrand = linkBrand, nameProvider = nameProvider, - isCbcEligible = isCbcEligible, defaultPaymentMethodId = defaultPaymentMethodId ) diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodEditability.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodEditability.kt index 35e974ffa82..0f44e1fda7d 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodEditability.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodEditability.kt @@ -5,29 +5,21 @@ import com.stripe.android.model.PaymentMethod internal fun PaymentMethod.isModifiable( canUpdateCardExpiryAndBillingDetails: Boolean, - canUpdateCardBrandChoice: Boolean, - isCbcEligible: Boolean, + canChangeCbc: Boolean, ): Boolean { val card = editableSavedCard() ?: return false - return canUpdateCardExpiryAndBillingDetails || - (canUpdateCardBrandChoice && card.isExpired().not() && canChangeCbc(isCbcEligible)) + (canChangeCbc && card.isExpired().not() && hasMultipleNetworks()) } -internal fun PaymentMethod.canChangeCbc(isCbcEligible: Boolean): Boolean { +internal fun PaymentMethod.hasMultipleNetworks(): Boolean { val card = editableSavedCard() ?: return false - val hasMultipleNetworks = card.networks?.available?.let { available -> - available.size > 1 - } ?: false - - return isCbcEligible && hasMultipleNetworks + return card.networks?.available?.let { it.size > 1 } ?: false } internal fun PaymentMethod.Card.isExpired(): Boolean { val cardExpiryMonth = expiryMonth val cardExpiryYear = expiryYear - // If the card's expiration dates are missing, we can't conclude that it is expired, so we don't want to - // show the user an expired card error. return cardExpiryMonth != null && cardExpiryYear != null && !DateUtils.isExpiryDataValid( expiryMonth = cardExpiryMonth, diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodMutator.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodMutator.kt index 547aabdb831..e742f618ffa 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodMutator.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodMutator.kt @@ -16,7 +16,6 @@ import com.stripe.android.paymentsheet.ui.DefaultUpdatePaymentMethodInteractor import com.stripe.android.paymentsheet.ui.PaymentMethodRemovalDelayMillis import com.stripe.android.paymentsheet.viewmodels.BaseSheetViewModel import com.stripe.android.paymentsheet.viewmodels.PaymentOptionsItemsMapper -import com.stripe.android.ui.core.cbc.CardBrandChoiceEligibility import com.stripe.android.uicore.utils.combineAsStateFlow import com.stripe.android.uicore.utils.mapAsStateFlow import kotlinx.coroutines.CoroutineScope @@ -84,7 +83,6 @@ internal class SavedPaymentMethodMutator( linkBrand = effectiveLinkBrand, isNotPaymentFlow = isNotPaymentFlow, nameProvider = { paymentMethodMetadataFlow.value?.displayNameForCode(it).orEmpty() }, - isCbcEligible = { paymentMethodMetadataFlow.value?.cbcEligibility is CardBrandChoiceEligibility.Eligible }, ) } @@ -94,12 +92,12 @@ internal class SavedPaymentMethodMutator( customerStateHolder.canRemove, paymentOptionsItems, customerStateHolder.canUpdateCardExpiryAndBillingDetails, - customerStateHolder.canUpdateCardBrandChoice, - ) { canRemove, items, canUpdateCardExpiryAndBillingDetails, canUpdateCardBrandChoice -> + customerStateHolder.canChangeCbc, + ) { canRemove, items, canUpdateCardExpiryAndBillingDetails, canChangeCbc -> canRemove || items.filterIsInstance().any { item -> - item.displayableSavedPaymentMethod.isModifiable( + item.displayableSavedPaymentMethod.paymentMethod.isModifiable( canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, - canUpdateCardBrandChoice = canUpdateCardBrandChoice, + canChangeCbc = canChangeCbc, ) } } @@ -382,7 +380,7 @@ internal class SavedPaymentMethodMutator( canRemove = canRemove, canUpdateCardExpiryAndBillingDetails = viewModel.customerStateHolder .canUpdateCardExpiryAndBillingDetails.value, - canUpdateCardBrandChoice = viewModel.customerStateHolder.canUpdateCardBrandChoice.value, + canChangeCbc = viewModel.customerStateHolder.canChangeCbc.value, displayableSavedPaymentMethod = displayableSavedPaymentMethod, cardBrandFilter = PaymentSheetCardBrandFilter(viewModel.config.cardBrandAcceptance), addressCollectionMode = viewModel.config.billingDetailsCollectionConfiguration.address, diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodInteractor.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodInteractor.kt index d6c89500c77..6426d93ad1f 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodInteractor.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodInteractor.kt @@ -10,6 +10,8 @@ import com.stripe.android.model.LinkPaymentDetails import com.stripe.android.model.PaymentMethod import com.stripe.android.paymentsheet.CardUpdateParams import com.stripe.android.paymentsheet.DisplayableSavedPaymentMethod +import com.stripe.android.paymentsheet.hasMultipleNetworks +import com.stripe.android.paymentsheet.isModifiable import com.stripe.android.paymentsheet.PaymentSheet.BillingDetailsCollectionConfiguration import com.stripe.android.paymentsheet.PaymentSheet.BillingDetailsCollectionConfiguration.AddressCollectionMode import com.stripe.android.paymentsheet.PaymentSheet.BillingDetailsCollectionConfiguration.CollectionMode @@ -41,7 +43,7 @@ internal interface UpdatePaymentMethodInteractor { val setAsDefaultCheckboxEnabled: Boolean val shouldShowSaveButton: Boolean val canUpdateCardExpiryAndBillingDetails: Boolean - val canUpdateCardBrandChoice: Boolean + val canChangeCbc: Boolean val addressCollectionMode: AddressCollectionMode val allowedBillingCountries: Set val editCardDetailsInteractor: EditCardDetailsInteractor @@ -117,7 +119,7 @@ internal class DefaultUpdatePaymentMethodInteractor( override val addressCollectionMode: AddressCollectionMode, override val allowedBillingCountries: Set, override val canUpdateCardExpiryAndBillingDetails: Boolean, - override val canUpdateCardBrandChoice: Boolean, + override val canChangeCbc: Boolean, override val removeMessage: ResolvableString?, val isDefaultPaymentMethod: Boolean, override val shouldShowSetAsDefaultCheckbox: Boolean, @@ -143,12 +145,12 @@ internal class DefaultUpdatePaymentMethodInteractor( displayableSavedPaymentMethod ) override val isModifiablePaymentMethod: Boolean - get() = displayableSavedPaymentMethod.isModifiable( + get() = displayableSavedPaymentMethod.paymentMethod.isModifiable( canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, - canUpdateCardBrandChoice = canUpdateCardBrandChoice, + canChangeCbc = canChangeCbc, ) override val shouldShowCardBrandDropdown: Boolean - get() = isModifiablePaymentMethod && canUpdateCardBrandChoice && displayableSavedPaymentMethod.canChangeCbc() + get() = isModifiablePaymentMethod && canChangeCbc && displayableSavedPaymentMethod.paymentMethod.hasMultipleNetworks() override val topBarState: PaymentSheetTopBarState = PaymentSheetTopBarStateFactory.create( isLiveMode = isLiveMode, @@ -183,14 +185,14 @@ internal class DefaultUpdatePaymentMethodInteractor( private fun createEditCardDetailsInteractorForCard( savedPaymentMethodCard: SavedPaymentMethod.Card, ): EditCardDetailsInteractor { - val isModifiable = displayableSavedPaymentMethod.isModifiable( + val isModifiable = displayableSavedPaymentMethod.paymentMethod.isModifiable( canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, - canUpdateCardBrandChoice = canUpdateCardBrandChoice, + canChangeCbc = canChangeCbc, ) val payload = EditCardPayload.create(savedPaymentMethodCard.card, savedPaymentMethodCard.billingDetails) val cardEditConfiguration = CardEditConfiguration( cardBrandFilter = cardBrandFilter, - isCbcModifiable = isModifiable && canUpdateCardBrandChoice && displayableSavedPaymentMethod.canChangeCbc(), + isCbcModifiable = isModifiable && canChangeCbc && displayableSavedPaymentMethod.paymentMethod.hasMultipleNetworks(), areExpiryDateAndAddressModificationSupported = isModifiable && canUpdateCardExpiryAndBillingDetails, ) return editCardDetailsInteractorFactory.create( diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUI.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUI.kt index af2f1bfe377..c7f508a6ba6 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUI.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUI.kt @@ -356,7 +356,7 @@ private fun PreviewUpdatePaymentMethodUI() { isLiveMode = false, canRemove = true, canUpdateCardExpiryAndBillingDetails = true, - canUpdateCardBrandChoice = true, + canChangeCbc = true, displayableSavedPaymentMethod = exampleCard, addressCollectionMode = AddressCollectionMode.Automatic, allowedBillingCountries = emptySet(), 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 f86d92174e7..6388fc064c8 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.CustomerStateHolder import com.stripe.android.paymentsheet.DefaultFormHelper import com.stripe.android.paymentsheet.DisplayableSavedPaymentMethod import com.stripe.android.paymentsheet.FormHelper.FormType +import com.stripe.android.paymentsheet.isModifiable import com.stripe.android.paymentsheet.R import com.stripe.android.paymentsheet.analytics.code import com.stripe.android.paymentsheet.forms.FormArgumentsFactory @@ -104,7 +105,7 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( private val canRemove: StateFlow, private val walletsState: StateFlow, private val canUpdateCardExpiryAndBillingDetails: StateFlow, - private val canUpdateCardBrandChoice: StateFlow, + private val canChangeCbc: StateFlow, private val updateSelection: (PaymentSelection?, Boolean) -> Unit, private val isCurrentScreen: StateFlow, private val reportPaymentMethodTypeSelected: (PaymentMethodCode) -> Unit, @@ -181,7 +182,7 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( walletsState = viewModel.walletsState, canUpdateCardExpiryAndBillingDetails = viewModel.customerStateHolder .canUpdateCardExpiryAndBillingDetails, - canUpdateCardBrandChoice = viewModel.customerStateHolder.canUpdateCardBrandChoice, + canChangeCbc = viewModel.customerStateHolder.canChangeCbc, isCurrentScreen = isCurrentScreen, reportPaymentMethodTypeSelected = viewModel.eventReporter::onSelectPaymentMethod, reportFormShown = viewModel.eventReporter::onPaymentMethodFormShown, @@ -245,18 +246,18 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( displayedSavedPaymentMethod, canRemove, canUpdateCardExpiryAndBillingDetails, - canUpdateCardBrandChoice, + canChangeCbc, ) { paymentMethods, displayedSavedPaymentMethod, canRemove, canUpdateCardExpiryAndBillingDetails, - canUpdateCardBrandChoice -> + canChangeCbc -> getAvailableSavedPaymentMethodAction( paymentMethods = paymentMethods, savedPaymentMethod = displayedSavedPaymentMethod, canRemove = canRemove, canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, - canUpdateCardBrandChoice = canUpdateCardBrandChoice, + canChangeCbc = canChangeCbc, ) } @@ -513,7 +514,7 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( savedPaymentMethod: DisplayableSavedPaymentMethod?, canRemove: Boolean, canUpdateCardExpiryAndBillingDetails: Boolean, - canUpdateCardBrandChoice: Boolean, + canChangeCbc: Boolean, ): PaymentMethodVerticalLayoutInteractor.SavedPaymentMethodAction { if (paymentMethods == null || savedPaymentMethod == null) { return PaymentMethodVerticalLayoutInteractor.SavedPaymentMethodAction.NONE @@ -526,7 +527,7 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( canRemove = canRemove, savedPaymentMethod = savedPaymentMethod, canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, - canUpdateCardBrandChoice = canUpdateCardBrandChoice, + canChangeCbc = canChangeCbc, ) } else -> @@ -538,11 +539,11 @@ internal class DefaultPaymentMethodVerticalLayoutInteractor( canRemove: Boolean, savedPaymentMethod: DisplayableSavedPaymentMethod?, canUpdateCardExpiryAndBillingDetails: Boolean, - canUpdateCardBrandChoice: Boolean, + canChangeCbc: Boolean, ): PaymentMethodVerticalLayoutInteractor.SavedPaymentMethodAction { - return if (savedPaymentMethod?.isModifiable( + return if (savedPaymentMethod?.paymentMethod?.isModifiable( canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, - canUpdateCardBrandChoice = canUpdateCardBrandChoice, + canChangeCbc = canChangeCbc, ) == true || canRemove ) { PaymentMethodVerticalLayoutInteractor.SavedPaymentMethodAction.MANAGE_ONE diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/verticalmode/SavedPaymentMethodsExtension.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/verticalmode/SavedPaymentMethodsExtension.kt index 52fd420570a..7f6911f94f9 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/verticalmode/SavedPaymentMethodsExtension.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/verticalmode/SavedPaymentMethodsExtension.kt @@ -4,7 +4,6 @@ import com.stripe.android.core.strings.orEmpty import com.stripe.android.lpmfoundations.paymentmethod.PaymentMethodMetadata import com.stripe.android.model.PaymentMethod import com.stripe.android.paymentsheet.DisplayableSavedPaymentMethod -import com.stripe.android.ui.core.cbc.CardBrandChoiceEligibility internal fun PaymentMethod.toDisplayableSavedPaymentMethod( paymentMethodMetadata: PaymentMethodMetadata?, @@ -13,7 +12,6 @@ internal fun PaymentMethod.toDisplayableSavedPaymentMethod( return DisplayableSavedPaymentMethod.create( displayName = paymentMethodMetadata?.displayNameForCode(type?.code).orEmpty(), paymentMethod = this, - isCbcEligible = paymentMethodMetadata?.cbcEligibility is CardBrandChoiceEligibility.Eligible, shouldShowDefaultBadge = id == defaultPaymentMethodId, ) } diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/viewmodels/PaymentOptionsItemsMapper.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/viewmodels/PaymentOptionsItemsMapper.kt index 5166702c7b9..dfebae2a858 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/viewmodels/PaymentOptionsItemsMapper.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/viewmodels/PaymentOptionsItemsMapper.kt @@ -19,7 +19,6 @@ internal class PaymentOptionsItemsMapper( private val linkBrand: StateFlow, private val nameProvider: (PaymentMethodCode?) -> ResolvableString, private val isNotPaymentFlow: Boolean, - private val isCbcEligible: () -> Boolean ) { operator fun invoke(): StateFlow> { @@ -61,7 +60,6 @@ internal class PaymentOptionsItemsMapper( // linkBrand is non-null whenever showLink=true (Link is enabled only when LinkState is available) linkBrand = linkBrand ?: LinkBrand.Link, nameProvider = nameProvider, - isCbcEligible = isCbcEligible(), defaultPaymentMethodId = defaultPaymentMethodId, ) } diff --git a/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetScreenshotTest.kt b/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetScreenshotTest.kt index 67af6c055c4..b559878f009 100644 --- a/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetScreenshotTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetScreenshotTest.kt @@ -103,7 +103,6 @@ internal class CustomerSheetScreenshotTest { primaryButtonVisible = false, canEdit = true, canRemovePaymentMethods = true, - isCbcEligible = false, ) private val addPaymentMethodViewState = CustomerSheetViewState.AddPaymentMethod( @@ -377,7 +376,7 @@ internal class CustomerSheetScreenshotTest { return CustomerSheetViewState.UpdatePaymentMethod( updatePaymentMethodInteractor = DefaultUpdatePaymentMethodInteractor( canUpdateCardExpiryAndBillingDetails = false, - canUpdateCardBrandChoice = true, + canChangeCbc = true, displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), removeExecutor = { null }, updatePaymentMethodExecutor = { paymentMethod, _ -> Result.success(paymentMethod) }, diff --git a/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetViewModelTest.kt b/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetViewModelTest.kt index f8ca244529b..21f30e26aa8 100644 --- a/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetViewModelTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetViewModelTest.kt @@ -2683,7 +2683,6 @@ class CustomerSheetViewModelTest { val selectPaymentMethodState = awaitViewState() - assertThat(selectPaymentMethodState.isCbcEligible).isTrue() } } diff --git a/paymentsheet/src/test/java/com/stripe/android/model/PaymentMethodFixtures.kt b/paymentsheet/src/test/java/com/stripe/android/model/PaymentMethodFixtures.kt index 405fd570e0e..6ff3b4b70e7 100644 --- a/paymentsheet/src/test/java/com/stripe/android/model/PaymentMethodFixtures.kt +++ b/paymentsheet/src/test/java/com/stripe/android/model/PaymentMethodFixtures.kt @@ -710,7 +710,6 @@ internal object PaymentMethodFixtures { return DisplayableSavedPaymentMethod.create( displayName = displayName, paymentMethod = this, - isCbcEligible = true, shouldShowDefaultBadge = shouldShowDefaultBadge, ) } diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/content/DefaultEmbeddedContentHelperTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/content/DefaultEmbeddedContentHelperTest.kt index 6b0e6792b7c..de66d3c6dad 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/content/DefaultEmbeddedContentHelperTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/content/DefaultEmbeddedContentHelperTest.kt @@ -174,6 +174,7 @@ internal class DefaultEmbeddedContentHelperTest { customerMetadata = stateFlowOf( PaymentMethodMetadataFixtures.DEFAULT_CUSTOMER_METADATA ), + paymentMethodMetadataFlow = stateFlowOf(null), ), embeddedFormHelperFactory = embeddedFormHelperFactory, confirmationHandler = confirmationHandler, diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/content/DefaultEmbeddedSheetLauncherTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/content/DefaultEmbeddedSheetLauncherTest.kt index ceeb1632bf7..2948aa9b258 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/content/DefaultEmbeddedSheetLauncherTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/content/DefaultEmbeddedSheetLauncherTest.kt @@ -643,7 +643,8 @@ internal class DefaultEmbeddedSheetLauncherTest { val customerStateHolder = DefaultCustomerStateHolder( savedStateHandle = savedStateHandle, selection = selectionHolder.selection, - customerMetadata = stateFlowOf(paymentMethodMetadata.customerMetadata) + customerMetadata = stateFlowOf(paymentMethodMetadata.customerMetadata), + paymentMethodMetadataFlow = stateFlowOf(null), ) val sheetStateHolder = SheetStateHolder(savedStateHandle) val errorReporter = FakeErrorReporter() diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/content/DefaultEmbeddedStateHelperTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/content/DefaultEmbeddedStateHelperTest.kt index 54a19893ab1..60c52567254 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/content/DefaultEmbeddedStateHelperTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/content/DefaultEmbeddedStateHelperTest.kt @@ -216,6 +216,7 @@ internal class DefaultEmbeddedStateHelperTest { customerMetadata = stateFlowOf( PaymentMethodMetadataFixtures.DEFAULT_CUSTOMER_METADATA ), + paymentMethodMetadataFlow = stateFlowOf(null), ) val confirmationStateHolder = EmbeddedConfirmationStateHolder( savedStateHandle = savedStateHandle, diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/content/EmbeddedContentUiTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/content/EmbeddedContentUiTest.kt index 617e583694a..9196ca9dd60 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/content/EmbeddedContentUiTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/content/EmbeddedContentUiTest.kt @@ -170,6 +170,7 @@ internal class EmbeddedContentUiTest { customerMetadata = stateFlowOf( PaymentMethodMetadataFixtures.DEFAULT_CUSTOMER_METADATA ), + paymentMethodMetadataFlow = stateFlowOf(null), ), embeddedFormHelperFactory = embeddedFormHelperFactory, confirmationHandler = confirmationHandler, diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/manage/EmbeddedNavigatorTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/manage/EmbeddedNavigatorTest.kt index b5bce360a16..6f260ff67b2 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/manage/EmbeddedNavigatorTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/manage/EmbeddedNavigatorTest.kt @@ -40,7 +40,7 @@ internal class EmbeddedNavigatorTest { assertThat(navigator.canGoBack).isFalse() val newScreen = EmbeddedNavigator.Screen.ManageUpdate( - FakeUpdatePaymentMethodInteractor(canUpdateCardBrandChoice = true) + FakeUpdatePaymentMethodInteractor(canChangeCbc = true) ) navigator.performAction(EmbeddedNavigator.Action.GoToScreen(newScreen)) assertThat(awaitItem()).isEqualTo(newScreen) @@ -66,7 +66,7 @@ internal class EmbeddedNavigatorTest { assertThat(awaitItem()).isEqualTo(initialScreen) val newScreen = EmbeddedNavigator.Screen.ManageUpdate( - FakeUpdatePaymentMethodInteractor(canUpdateCardBrandChoice = true) + FakeUpdatePaymentMethodInteractor(canChangeCbc = true) ) navigator.performAction(EmbeddedNavigator.Action.GoToScreen(newScreen)) assertThat(awaitItem()).isEqualTo(newScreen) @@ -141,7 +141,7 @@ internal class EmbeddedNavigatorTest { @Test fun `Close while on ManageUpdate calls onHideEditablePaymentOption`() = testScenario { val manageUpdateScreen = EmbeddedNavigator.Screen.ManageUpdate( - FakeUpdatePaymentMethodInteractor(canUpdateCardBrandChoice = true) + FakeUpdatePaymentMethodInteractor(canChangeCbc = true) ) navigator.screen.test { assertThat(awaitItem()).isEqualTo(initialScreen) @@ -161,7 +161,7 @@ internal class EmbeddedNavigatorTest { coroutineScope = this, eventReporter = eventReporter, initialScreen = EmbeddedNavigator.Screen.ManageUpdate( - FakeUpdatePaymentMethodInteractor(canUpdateCardBrandChoice = true) + FakeUpdatePaymentMethodInteractor(canChangeCbc = true) ), ) assertThat(eventReporter.showEditablePaymentOptionCalls.awaitItem()).isEqualTo(Unit) @@ -222,7 +222,7 @@ internal class EmbeddedNavigatorTest { @Test fun `ManageUpdate topBarState returns interactor topBarState`() { - val interactor = FakeUpdatePaymentMethodInteractor(canUpdateCardBrandChoice = true) + val interactor = FakeUpdatePaymentMethodInteractor(canChangeCbc = true) val screen = EmbeddedNavigator.Screen.ManageUpdate(interactor) val topBarState = screen.topBarState().value @@ -231,7 +231,7 @@ internal class EmbeddedNavigatorTest { @Test fun `ManageUpdate title returns interactor screenTitle`() { - val interactor = FakeUpdatePaymentMethodInteractor(canUpdateCardBrandChoice = true) + val interactor = FakeUpdatePaymentMethodInteractor(canChangeCbc = true) val screen = EmbeddedNavigator.Screen.ManageUpdate(interactor) val title = screen.title().value @@ -241,7 +241,7 @@ internal class EmbeddedNavigatorTest { @Test fun `ManageUpdate isPerformingNetworkOperation when idle returns false`() { val interactor = FakeUpdatePaymentMethodInteractor( - canUpdateCardBrandChoice = true, + canChangeCbc = true, initialState = UpdatePaymentMethodInteractor.State( error = null, status = UpdatePaymentMethodInteractor.Status.Idle, @@ -256,7 +256,7 @@ internal class EmbeddedNavigatorTest { @Test fun `ManageUpdate isPerformingNetworkOperation when updating returns true`() { val interactor = FakeUpdatePaymentMethodInteractor( - canUpdateCardBrandChoice = true, + canChangeCbc = true, initialState = UpdatePaymentMethodInteractor.State( error = null, status = UpdatePaymentMethodInteractor.Status.Updating, diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/manage/InitialManageScreenFactoryTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/manage/InitialManageScreenFactoryTest.kt index 5ed01c04c0e..a4aea861652 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/manage/InitialManageScreenFactoryTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/manage/InitialManageScreenFactoryTest.kt @@ -49,6 +49,7 @@ internal class InitialManageScreenFactoryTest { customerMetadata = stateFlowOf( PaymentMethodMetadataFixtures.DEFAULT_CUSTOMER_METADATA ), + paymentMethodMetadataFlow = stateFlowOf(null), ) val factory = InitialManageScreenFactory( customerStateHolder = customerStateHolder, @@ -57,7 +58,7 @@ internal class InitialManageScreenFactoryTest { FakeUpdatePaymentMethodInteractor( displayableSavedPaymentMethod = displayableSavedPaymentMethod, canRemove = customerStateHolder.canRemove.value, - canUpdateCardBrandChoice = true, + canChangeCbc = true, isExpiredCard = false, isModifiablePaymentMethod = true, viewActionRecorder = ViewActionRecorder(), diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/DefaultCustomerStateHolderTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/DefaultCustomerStateHolderTest.kt index 345ddc89752..42727abf947 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/DefaultCustomerStateHolderTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/DefaultCustomerStateHolderTest.kt @@ -483,6 +483,7 @@ internal class DefaultCustomerStateHolderTest { val customerStateHolder = DefaultCustomerStateHolder( customerMetadata = customerMetadata, + paymentMethodMetadataFlow = stateFlowOf(null), savedStateHandle = savedStateHandle, selection = selection, ) diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethodModifiableTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethodModifiableTest.kt index b603315b756..2a74eea26ac 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethodModifiableTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethodModifiableTest.kt @@ -1,7 +1,6 @@ package com.stripe.android.paymentsheet import com.google.common.truth.Truth.assertThat -import com.stripe.android.core.strings.resolvableString import com.stripe.android.model.PaymentMethod import com.stripe.android.model.PaymentMethodFixtures import junit.framework.TestCase.assertEquals @@ -20,38 +19,24 @@ class DisplayableSavedPaymentMethodModifiableTest(private val params: IsModifiab expiryYear = if (params.cardExpired) 2005 else 2099 ) ) - val displayableSavedPaymentMethod = DisplayableSavedPaymentMethod.create( - displayName = "unused".resolvableString, - paymentMethod = paymentMethod, - isCbcEligible = params.isCbcEligible, - ) assertEquals( "Expected isModifiable to be ${params.expectedResult} for parameters: " + "canUpdatePaymentMethod=${params.canUpdatePaymentMethod}, " + - "isCbcEligible=${params.isCbcEligible}, " + + "canChangeCbc=${params.canChangeCbc}, " + "availableNetworks=${params.availableNetworks}, " + "cardExpired=${params.cardExpired}", params.expectedResult, - displayableSavedPaymentMethod.isModifiable( - canUpdateCardExpiryAndBillingDetails = params.canUpdatePaymentMethod, - canUpdateCardBrandChoice = params.canUpdateCardBrandChoice, - ) - ) - - assertThat( - displayableSavedPaymentMethod.isModifiable( + paymentMethod.isModifiable( canUpdateCardExpiryAndBillingDetails = params.canUpdatePaymentMethod, - canUpdateCardBrandChoice = params.canUpdateCardBrandChoice, + canChangeCbc = params.canChangeCbc, ) ) - .isEqualTo(params.expectedResult) assertThat( paymentMethod.isModifiable( canUpdateCardExpiryAndBillingDetails = params.canUpdatePaymentMethod, - canUpdateCardBrandChoice = params.canUpdateCardBrandChoice, - isCbcEligible = params.isCbcEligible, + canChangeCbc = params.canChangeCbc, ) ).isEqualTo(params.expectedResult) } @@ -61,16 +46,14 @@ class DisplayableSavedPaymentMethodModifiableTest(private val params: IsModifiab assertThat( PaymentMethodFixtures.LINK_PAYMENT_METHOD.isModifiable( canUpdateCardExpiryAndBillingDetails = true, - canUpdateCardBrandChoice = true, - isCbcEligible = true, + canChangeCbc = true, ) ).isFalse() } data class IsModifiableParams( val canUpdatePaymentMethod: Boolean = false, - val canUpdateCardBrandChoice: Boolean, - val isCbcEligible: Boolean = false, + val canChangeCbc: Boolean, val availableNetworks: Set = setOf("visa"), val cardExpired: Boolean = false, val expectedResult: Boolean, @@ -82,54 +65,44 @@ class DisplayableSavedPaymentMethodModifiableTest(private val params: IsModifiab fun testCases() = listOf( IsModifiableParams( canUpdatePaymentMethod = true, - canUpdateCardBrandChoice = true, + canChangeCbc = true, expectedResult = true ), IsModifiableParams( canUpdatePaymentMethod = true, - canUpdateCardBrandChoice = true, + canChangeCbc = true, cardExpired = true, expectedResult = true ), IsModifiableParams( canUpdatePaymentMethod = true, - canUpdateCardBrandChoice = true, - isCbcEligible = true, + canChangeCbc = true, availableNetworks = setOf("visa", "mastercard"), cardExpired = false, expectedResult = true ), IsModifiableParams( - canUpdateCardBrandChoice = true, - isCbcEligible = true, + canChangeCbc = true, availableNetworks = setOf("visa", "cartes_bancaires"), expectedResult = true ), IsModifiableParams( - canUpdateCardBrandChoice = false, - isCbcEligible = true, - availableNetworks = setOf("visa", "cartes_bancaires"), - expectedResult = false - ), - IsModifiableParams( - canUpdateCardBrandChoice = true, + canChangeCbc = false, availableNetworks = setOf("visa", "cartes_bancaires"), expectedResult = false ), IsModifiableParams( - canUpdateCardBrandChoice = true, - isCbcEligible = true, + canChangeCbc = true, expectedResult = false ), IsModifiableParams( - canUpdateCardBrandChoice = true, - isCbcEligible = true, + canChangeCbc = true, availableNetworks = setOf("visa", "cartes_bancaires"), cardExpired = true, expectedResult = false ), IsModifiableParams( - canUpdateCardBrandChoice = true, + canChangeCbc = true, cardExpired = true, expectedResult = false ) diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethodTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethodTest.kt index 1aae8ed4f29..95566ef9067 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethodTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethodTest.kt @@ -53,7 +53,6 @@ class DisplayableSavedPaymentMethodTest { val displayableSavedPaymentMethod = DisplayableSavedPaymentMethod.create( displayName = "unused".resolvableString, paymentMethod = paymentMethod, - isCbcEligible = false, ) assertThat(displayableSavedPaymentMethod.savedPaymentMethod).isInstanceOf() @@ -66,7 +65,6 @@ class DisplayableSavedPaymentMethodTest { val displayableSavedPaymentMethod = DisplayableSavedPaymentMethod.create( displayName = "unused".resolvableString, paymentMethod = paymentMethod, - isCbcEligible = false, ) assertThat(displayableSavedPaymentMethod.savedPaymentMethod).isInstanceOf() @@ -79,7 +77,6 @@ class DisplayableSavedPaymentMethodTest { val displayableSavedPaymentMethod = DisplayableSavedPaymentMethod.create( displayName = "unused".resolvableString, paymentMethod = paymentMethod, - isCbcEligible = false, ) assertThat(displayableSavedPaymentMethod.savedPaymentMethod).isInstanceOf() @@ -94,7 +91,6 @@ class DisplayableSavedPaymentMethodTest { val displayableSavedPaymentMethod = DisplayableSavedPaymentMethod.create( displayName = "unused".resolvableString, paymentMethod = paymentMethod, - isCbcEligible = false, ) assertThat(displayableSavedPaymentMethod.savedPaymentMethod).isInstanceOf() @@ -107,17 +103,8 @@ class DisplayableSavedPaymentMethodTest { val displayableSavedPaymentMethod = DisplayableSavedPaymentMethod.create( displayName = "unused".resolvableString, paymentMethod = paymentMethod, - isCbcEligible = false, ) assertThat(displayableSavedPaymentMethod.savedPaymentMethod).isInstanceOf() } - - data class IsModifiableParams( - val canUpdatePaymentMethod: Boolean = false, - val isCbcEligible: Boolean = false, - val availableNetworks: Set = setOf("visa"), - val cardExpired: Boolean = false, - val expectedResult: Boolean, - ) } diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/FakeCustomerStateHolder.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/FakeCustomerStateHolder.kt index 2d2ce12f7e3..78e5674b4fb 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/FakeCustomerStateHolder.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/FakeCustomerStateHolder.kt @@ -23,7 +23,7 @@ internal class FakeCustomerStateHolder : CustomerStateHolder { override val canUpdateCardExpiryAndBillingDetails: StateFlow get() = stateFlowOf(false) - override val canUpdateCardBrandChoice: StateFlow + override val canChangeCbc: StateFlow get() = stateFlowOf(false) val setCustomerStateCalls = Turbine() diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/PaymentOptionsStateFactoryTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/PaymentOptionsStateFactoryTest.kt index d2483021961..7cc3ae159cf 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/PaymentOptionsStateFactoryTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/PaymentOptionsStateFactoryTest.kt @@ -46,7 +46,6 @@ class PaymentOptionsStateFactoryTest { linkBrand = LinkBrand.Link, currentSelection = PaymentSelection.Saved(paymentMethod), nameProvider = { it!!.resolvableString }, - isCbcEligible = false, defaultPaymentMethodId = null, ) @@ -65,7 +64,6 @@ class PaymentOptionsStateFactoryTest { linkBrand = LinkBrand.Link, currentSelection = PaymentSelection.Link(brand = LinkBrand.Link), nameProvider = { it!!.resolvableString }, - isCbcEligible = false, defaultPaymentMethodId = null, ) @@ -76,7 +74,7 @@ class PaymentOptionsStateFactoryTest { fun `'isModifiable' is true when canUpdatePaymentMethod is false and cbc can change`() { helperIsModifiable( canUpdatePaymentMethod = false, - isCbcEligible = true, + canChangeCbc = true, availableNetworks = setOf("visa", "cartes_bancaires"), expectedResult = true ) @@ -86,7 +84,7 @@ class PaymentOptionsStateFactoryTest { fun `'isModifiable' is true when canUpdatePaymentMethod is true and cbc cannot change`() { helperIsModifiable( canUpdatePaymentMethod = true, - isCbcEligible = false, + canChangeCbc = false, availableNetworks = setOf("visa"), expectedResult = true ) @@ -96,7 +94,7 @@ class PaymentOptionsStateFactoryTest { fun `'isModifiable' is false when canUpdatePaymentMethod is false and cbc cannot change`() { helperIsModifiable( canUpdatePaymentMethod = false, - isCbcEligible = false, + canChangeCbc = false, availableNetworks = setOf("visa"), expectedResult = false ) @@ -104,7 +102,7 @@ class PaymentOptionsStateFactoryTest { private fun helperIsModifiable( canUpdatePaymentMethod: Boolean = false, - isCbcEligible: Boolean = false, + canChangeCbc: Boolean = false, availableNetworks: Set = emptySet(), expectedResult: Boolean ) { @@ -129,16 +127,15 @@ class PaymentOptionsStateFactoryTest { linkBrand = LinkBrand.Link, currentSelection = PaymentSelection.Link(brand = LinkBrand.Link), nameProvider = { it!!.resolvableString }, - isCbcEligible = isCbcEligible, defaultPaymentMethodId = null, ) val displayableSavedPaymentMethod = (state.items.last() as PaymentOptionsItem.SavedPaymentMethod) .displayableSavedPaymentMethod assertThat( - displayableSavedPaymentMethod.isModifiable( + displayableSavedPaymentMethod.paymentMethod.isModifiable( canUpdateCardExpiryAndBillingDetails = canUpdatePaymentMethod, - canUpdateCardBrandChoice = true, + canChangeCbc = canChangeCbc, ) ).isEqualTo(expectedResult) } @@ -185,7 +182,6 @@ class PaymentOptionsStateFactoryTest { linkBrand = LinkBrand.Link, currentSelection = PaymentSelection.Saved(defaultPaymentMethod), nameProvider = { it!!.resolvableString }, - isCbcEligible = false, defaultPaymentMethodId = defaultPaymentMethodId ) @@ -207,7 +203,6 @@ class PaymentOptionsStateFactoryTest { linkBrand = LinkBrand.Link, currentSelection = PaymentSelection.Link(brand = LinkBrand.Link), nameProvider = { it!!.resolvableString }, - isCbcEligible = true, defaultPaymentMethodId = null, ) } diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/SavedPaymentMethodMutatorTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/SavedPaymentMethodMutatorTest.kt index 9291840a69a..4861e520f60 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/SavedPaymentMethodMutatorTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/SavedPaymentMethodMutatorTest.kt @@ -912,6 +912,7 @@ class SavedPaymentMethodMutatorTest { selection = MutableStateFlow(null), customerMetadata = stateFlowOf(PaymentMethodMetadataFixtures.DEFAULT_CUSTOMER_METADATA), + paymentMethodMetadataFlow = stateFlowOf(null), ) runScenario( customerStateHolder = customerStateHolder, @@ -956,6 +957,7 @@ class SavedPaymentMethodMutatorTest { paymentMethodMetadata?.customerMetadata ?: PaymentMethodMetadataFixtures.DEFAULT_CUSTOMER_METADATA ), + paymentMethodMetadataFlow = stateFlowOf(null), ), block: suspend Scenario.() -> Unit ) { diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/navigation/PaymentSheetScreenManageSavedPaymentMethodsScreenshotTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/navigation/PaymentSheetScreenManageSavedPaymentMethodsScreenshotTest.kt index 61be77cd054..2e70eb392e1 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/navigation/PaymentSheetScreenManageSavedPaymentMethodsScreenshotTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/navigation/PaymentSheetScreenManageSavedPaymentMethodsScreenshotTest.kt @@ -37,7 +37,6 @@ internal class PaymentSheetScreenManageSavedPaymentMethodsScreenshotTest { DisplayableSavedPaymentMethod.create( displayName = it.second.resolvableString, paymentMethod = it.first, - isCbcEligible = true, ) } @@ -49,7 +48,6 @@ internal class PaymentSheetScreenManageSavedPaymentMethodsScreenshotTest { DisplayableSavedPaymentMethod.create( displayName = it.second.resolvableString, paymentMethod = it.first, - isCbcEligible = true, ) } diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/DefaultSelectSavedPaymentMethodsInteractorTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/DefaultSelectSavedPaymentMethodsInteractorTest.kt index cba6ec7c6af..26929511748 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/DefaultSelectSavedPaymentMethodsInteractorTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/DefaultSelectSavedPaymentMethodsInteractorTest.kt @@ -472,7 +472,6 @@ class DefaultSelectSavedPaymentMethodsInteractorTest { linkBrand = LinkBrand.Link, currentSelection = PaymentSelection.Saved(paymentMethods[0]), nameProvider = { it!!.resolvableString }, - isCbcEligible = true, defaultPaymentMethodId = null, ).items } diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/DefaultUpdatePaymentMethodInteractorTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/DefaultUpdatePaymentMethodInteractorTest.kt index 7eff5778e12..72476b3dd70 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/DefaultUpdatePaymentMethodInteractorTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/DefaultUpdatePaymentMethodInteractorTest.kt @@ -47,7 +47,7 @@ class DefaultUpdatePaymentMethodInteractorTest { canRemove = true, displayableSavedPaymentMethod = paymentMethod, onRemovePaymentMethod = ::onRemovePaymentMethod, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { interactor.handleViewAction(UpdatePaymentMethodInteractor.ViewAction.RemovePaymentMethod) @@ -58,7 +58,7 @@ class DefaultUpdatePaymentMethodInteractorTest { @Test fun creatingInteractorInLiveMode_setsTopBarStateCorrectly() = runScenario( isLiveMode = true, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { assertThat(interactor.topBarState.showTestModeLabel).isFalse() } @@ -66,7 +66,7 @@ class DefaultUpdatePaymentMethodInteractorTest { @Test fun creatingInteractorInTestMode_setsTopBarStateCorrectly() = runScenario( isLiveMode = false, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { assertThat(interactor.topBarState.showTestModeLabel).isTrue() } @@ -84,7 +84,7 @@ class DefaultUpdatePaymentMethodInteractorTest { canRemove = true, displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), onRemovePaymentMethod = ::onRemovePaymentMethod, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { interactor.handleViewAction(UpdatePaymentMethodInteractor.ViewAction.RemovePaymentMethod) @@ -100,7 +100,7 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures .EXPIRED_CARD_PAYMENT_METHOD .toDisplayableSavedPaymentMethod(), - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { interactor.state.test { assertThat(awaitItem().error).isEqualTo( @@ -116,7 +116,7 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures .EXPIRED_CARD_PAYMENT_METHOD .toDisplayableSavedPaymentMethod(), - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { assertThat(interactor.isModifiablePaymentMethod).isFalse() } @@ -126,7 +126,7 @@ class DefaultUpdatePaymentMethodInteractorTest { fun nonExpiredCard_hasNoInitialError() { runScenario( displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { interactor.state.test { assertThat(awaitItem().error).isNull() @@ -140,7 +140,7 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures .CARD_WITH_NETWORKS_PAYMENT_METHOD .toDisplayableSavedPaymentMethod(), - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { assertThat(interactor.isModifiablePaymentMethod).isTrue() } @@ -152,7 +152,7 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures.CARD_WITH_NETWORKS_PAYMENT_METHOD.toDisplayableSavedPaymentMethod(), updatePaymentMethodExecutor = { paymentMethod, _ -> Result.success(paymentMethod) }, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { interactor.cardParamsUpdateAction(CardBrand.Visa) @@ -176,7 +176,7 @@ class DefaultUpdatePaymentMethodInteractorTest { updatedPaymentMethod = paymentMethod Result.success(paymentMethod) }, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { interactor.cardParamsUpdateAction(CardBrand.CartesBancaires) @@ -220,7 +220,7 @@ class DefaultUpdatePaymentMethodInteractorTest { runScenario( displayableSavedPaymentMethod = initialPaymentMethod.toDisplayableSavedPaymentMethod(), updatePaymentMethodExecutor = ::updatePaymentMethodExecutor, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { interactor.handleViewAction(UpdatePaymentMethodInteractor.ViewAction.SaveButtonPressed) @@ -243,7 +243,7 @@ class DefaultUpdatePaymentMethodInteractorTest { .CARD_WITH_NETWORKS_PAYMENT_METHOD .toDisplayableSavedPaymentMethod(), updatePaymentMethodExecutor = ::updatePaymentMethodExecutor, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { interactor.cardParamsUpdateAction(CardBrand.CartesBancaires) interactor.handleViewAction(UpdatePaymentMethodInteractor.ViewAction.SaveButtonPressed) @@ -262,7 +262,7 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures.SEPA_DEBIT_PAYMENT_METHOD.toDisplayableSavedPaymentMethod(), shouldShowSetAsDefaultCheckbox = true, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { assertThat(interactor.shouldShowSetAsDefaultCheckbox).isTrue() } @@ -271,7 +271,7 @@ class DefaultUpdatePaymentMethodInteractorTest { fun setAsDefaultCheckbox_shownForCards() = runScenario( displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), shouldShowSetAsDefaultCheckbox = true, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { assertThat(interactor.shouldShowSetAsDefaultCheckbox).isTrue() } @@ -280,7 +280,7 @@ class DefaultUpdatePaymentMethodInteractorTest { fun setAsDefaultCheckbox_shownForUsBankAccount() = runScenario( displayableSavedPaymentMethod = PaymentMethodFixtures.US_BANK_ACCOUNT.toDisplayableSavedPaymentMethod(), shouldShowSetAsDefaultCheckbox = true, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { assertThat(interactor.shouldShowSetAsDefaultCheckbox).isTrue() } @@ -290,7 +290,7 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), shouldShowSetAsDefaultCheckbox = true, isDefaultPaymentMethod = true, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { assertThat(interactor.shouldShowSaveButton).isFalse() } @@ -302,7 +302,7 @@ class DefaultUpdatePaymentMethodInteractorTest { .toDisplayableSavedPaymentMethod(), shouldShowSetAsDefaultCheckbox = true, isDefaultPaymentMethod = true, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { assertThat(interactor.shouldShowSaveButton).isTrue() } @@ -314,7 +314,7 @@ class DefaultUpdatePaymentMethodInteractorTest { .toDisplayableSavedPaymentMethod(), shouldShowSetAsDefaultCheckbox = true, isDefaultPaymentMethod = true, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { interactor.state.test { assertThat(awaitItem().isSaveButtonEnabled).isFalse() @@ -332,7 +332,7 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), shouldShowSetAsDefaultCheckbox = true, isDefaultPaymentMethod = true, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { interactor.state.test { assertThat(awaitItem().setAsDefaultCheckboxChecked).isTrue() @@ -344,7 +344,7 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), shouldShowSetAsDefaultCheckbox = true, isDefaultPaymentMethod = true, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { assertThat(interactor.setAsDefaultCheckboxEnabled).isFalse() } @@ -354,7 +354,7 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), shouldShowSetAsDefaultCheckbox = true, isDefaultPaymentMethod = false, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { assertThat(interactor.setAsDefaultCheckboxEnabled).isTrue() } @@ -362,7 +362,7 @@ class DefaultUpdatePaymentMethodInteractorTest { @Test fun setAsDefaultCheckboxChangedViewAction_updatesState() = runScenario( shouldShowSetAsDefaultCheckbox = true, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { val expectedInitialCheckedValue = false val expectedUpdatedCheckedValue = true @@ -389,7 +389,7 @@ class DefaultUpdatePaymentMethodInteractorTest { runScenario( shouldShowSetAsDefaultCheckbox = true, onSetDefaultPaymentMethod = { Result.success(Unit) }, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { interactor.handleViewAction(UpdatePaymentMethodInteractor.ViewAction.SaveButtonPressed) } @@ -400,7 +400,7 @@ class DefaultUpdatePaymentMethodInteractorTest { runScenario( shouldShowSetAsDefaultCheckbox = true, onSetDefaultPaymentMethod = { Result.success(Unit) }, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { interactor.handleViewAction( UpdatePaymentMethodInteractor.ViewAction.SetAsDefaultCheckboxChanged( @@ -418,7 +418,7 @@ class DefaultUpdatePaymentMethodInteractorTest { fun setAsDefault_failure_displaysErrorMessage() = runScenario( shouldShowSetAsDefaultCheckbox = true, onSetDefaultPaymentMethod = { Result.failure(IllegalStateException("Fake error")) }, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { interactor.handleViewAction( UpdatePaymentMethodInteractor.ViewAction.SetAsDefaultCheckboxChanged( @@ -444,7 +444,7 @@ class DefaultUpdatePaymentMethodInteractorTest { shouldShowSetAsDefaultCheckbox = true, onSetDefaultPaymentMethod = { Result.success(Unit) }, updatePaymentMethodExecutor = { _, _ -> Result.failure(expectedError) }, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { updateCardAndDefaultPaymentMethod(interactor) @@ -463,7 +463,7 @@ class DefaultUpdatePaymentMethodInteractorTest { shouldShowSetAsDefaultCheckbox = true, onSetDefaultPaymentMethod = { Result.failure(IllegalStateException("Fake error")) }, updatePaymentMethodExecutor = { paymentMethod, _ -> Result.success(paymentMethod) }, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { updateCardAndDefaultPaymentMethod(interactor) @@ -482,7 +482,7 @@ class DefaultUpdatePaymentMethodInteractorTest { shouldShowSetAsDefaultCheckbox = true, onSetDefaultPaymentMethod = { Result.failure(IllegalStateException("Fake error")) }, updatePaymentMethodExecutor = { _, _ -> Result.failure(IllegalStateException("Fake error")) }, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { updateCardAndDefaultPaymentMethod(interactor) @@ -497,7 +497,7 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures .CARD_WITH_NETWORKS_PAYMENT_METHOD .toDisplayableSavedPaymentMethod(), - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { assertThat(interactor.shouldShowSaveButton).isTrue() } @@ -506,7 +506,7 @@ class DefaultUpdatePaymentMethodInteractorTest { fun shouldShowSaveButton_whenSetAsDefaultCheckboxShown() = runScenario( displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), shouldShowSetAsDefaultCheckbox = true, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { assertThat(interactor.shouldShowSaveButton).isTrue() } @@ -517,7 +517,7 @@ class DefaultUpdatePaymentMethodInteractorTest { .CARD_WITH_NETWORKS_PAYMENT_METHOD .toDisplayableSavedPaymentMethod(), shouldShowSetAsDefaultCheckbox = true, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { assertThat(interactor.shouldShowSaveButton).isTrue() } @@ -526,7 +526,7 @@ class DefaultUpdatePaymentMethodInteractorTest { fun shouldNotShowSaveButton_whenNothingIsChangeable() = runScenario( displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), shouldShowSetAsDefaultCheckbox = false, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { assertThat(interactor.shouldShowSaveButton).isFalse() } @@ -536,7 +536,7 @@ class DefaultUpdatePaymentMethodInteractorTest { isDefaultPaymentMethod = true, onSetDefaultPaymentMethod = { _ -> notImplemented() }, updatePaymentMethodExecutor = { _, _ -> notImplemented() }, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { interactor.handleViewAction(UpdatePaymentMethodInteractor.ViewAction.SaveButtonPressed) @@ -545,7 +545,7 @@ class DefaultUpdatePaymentMethodInteractorTest { @Test fun shouldCreateEditCardInteractor_whenPaymentMethodIsCard() = runScenario( - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { assertThat(interactor.editCardDetailsInteractor).isNotNull() } @@ -557,7 +557,7 @@ class DefaultUpdatePaymentMethodInteractorTest { runScenario( displayableSavedPaymentMethod = displayableSavedPaymentMethod, canUpdateCardExpiryAndBillingDetails = true, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { val state = interactor.editCardDetailsInteractor.state.value assertThat(state.cardDetailsState?.shouldShowCardBrandDropdown).isTrue() @@ -573,7 +573,7 @@ class DefaultUpdatePaymentMethodInteractorTest { runScenario( displayableSavedPaymentMethod = displayableSavedPaymentMethod, canUpdateCardExpiryAndBillingDetails = true, - canUpdateCardBrandChoice = false, + canChangeCbc = false, ) { val state = interactor.editCardDetailsInteractor.state.value assertThat(state.cardDetailsState?.shouldShowCardBrandDropdown).isFalse() @@ -589,7 +589,7 @@ class DefaultUpdatePaymentMethodInteractorTest { runScenario( displayableSavedPaymentMethod = displayableSavedPaymentMethod, canUpdateCardExpiryAndBillingDetails = false, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { val state = interactor.editCardDetailsInteractor.state.value assertThat(state.cardDetailsState?.shouldShowCardBrandDropdown).isTrue() @@ -602,7 +602,7 @@ class DefaultUpdatePaymentMethodInteractorTest { fun shouldCreateEditCardInteractorCorrectly_whenCbcIneligible_andCanUpdateCardExpiryAndBillingDetails() { runScenario( canUpdateCardExpiryAndBillingDetails = true, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { val state = interactor.editCardDetailsInteractor.state.value assertThat(state.cardDetailsState?.shouldShowCardBrandDropdown).isFalse() @@ -615,7 +615,7 @@ class DefaultUpdatePaymentMethodInteractorTest { fun shouldCreateEditCardInteractorCorrectly_whenCbcIneligible_andCanNotUpdateCardExpiryAndBillingDetails() { runScenario( canUpdateCardExpiryAndBillingDetails = false, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { val state = interactor.editCardDetailsInteractor.state.value assertThat(state.cardDetailsState?.shouldShowCardBrandDropdown).isFalse() @@ -627,7 +627,7 @@ class DefaultUpdatePaymentMethodInteractorTest { @Test fun shouldNotCreateEditCardInteractor_whenPaymentMethodIsNotCard() = runScenario( displayableSavedPaymentMethod = PaymentMethodFixtures.US_BANK_ACCOUNT.toDisplayableSavedPaymentMethod(), - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { val exception = assertThrows(IllegalArgumentException::class.java) { interactor.editCardDetailsInteractor @@ -642,7 +642,7 @@ class DefaultUpdatePaymentMethodInteractorTest { val editCardDetailsInteractorFactory = FakeEditCardDetailsInteractorFactory() runScenario( editCardDetailsInteractorFactory = editCardDetailsInteractorFactory, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { interactor.editCardDetailsInteractor editCardDetailsInteractorFactory.onCardUpdateParamsChanged?.invoke( @@ -658,7 +658,7 @@ class DefaultUpdatePaymentMethodInteractorTest { val editCardDetailsInteractorFactory = FakeEditCardDetailsInteractorFactory() runScenario( editCardDetailsInteractorFactory = editCardDetailsInteractorFactory, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { editCardDetailsInteractorFactory.onCardUpdateParamsChanged?.invoke( CardUpdateParams(cardBrand = CardBrand.Visa) @@ -677,7 +677,7 @@ class DefaultUpdatePaymentMethodInteractorTest { addressCollectionMode = AddressCollectionMode.Full, allowedBillingCountries = setOf("us", "CA"), editCardDetailsInteractorFactory = editCardDetailsInteractorFactory, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { assertThat(interactor.editCardDetailsInteractor.state.value).isNotNull() @@ -704,7 +704,7 @@ class DefaultUpdatePaymentMethodInteractorTest { addressCollectionMode = AddressCollectionMode.Full, allowedBillingCountries = setOf("us", "CA"), editCardDetailsInteractorFactory = editCardDetailsInteractorFactory, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { assertThat(interactor.editCardDetailsInteractor.state.value).isNotNull() @@ -730,7 +730,7 @@ class DefaultUpdatePaymentMethodInteractorTest { addressCollectionMode = AddressCollectionMode.Full, allowedBillingCountries = setOf("us", "CA"), editCardDetailsInteractorFactory = FakeEditCardDetailsInteractorFactory(), - canUpdateCardBrandChoice = true, + canChangeCbc = true, ) { assertThat(interactor.editCardDetailsInteractor).isInstanceOf() @@ -773,7 +773,7 @@ class DefaultUpdatePaymentMethodInteractorTest { shouldShowSetAsDefaultCheckbox: Boolean = false, isDefaultPaymentMethod: Boolean = false, canUpdateCardExpiryAndBillingDetails: Boolean = false, - canUpdateCardBrandChoice: Boolean, + canChangeCbc: Boolean, addressCollectionMode: AddressCollectionMode = AddressCollectionMode.Automatic, allowedBillingCountries: Set = setOf("US", "CA"), editCardDetailsInteractorFactory: EditCardDetailsInteractor.Factory = DefaultEditCardDetailsInteractor @@ -786,7 +786,7 @@ class DefaultUpdatePaymentMethodInteractorTest { isLiveMode = isLiveMode, canRemove = canRemove, canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, - canUpdateCardBrandChoice = canUpdateCardBrandChoice, + canChangeCbc = canChangeCbc, displayableSavedPaymentMethod = displayableSavedPaymentMethod, addressCollectionMode = addressCollectionMode, removeExecutor = onRemovePaymentMethod, diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/FakeUpdatePaymentMethodInteractor.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/FakeUpdatePaymentMethodInteractor.kt index 8eb8d1ebc32..7458654fb7b 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/FakeUpdatePaymentMethodInteractor.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/FakeUpdatePaymentMethodInteractor.kt @@ -7,6 +7,8 @@ import com.stripe.android.model.PaymentMethodFixtures import com.stripe.android.model.PaymentMethodFixtures.toDisplayableSavedPaymentMethod import com.stripe.android.paymentsheet.DisplayableSavedPaymentMethod import com.stripe.android.paymentsheet.PaymentSheet +import com.stripe.android.paymentsheet.hasMultipleNetworks +import com.stripe.android.paymentsheet.isModifiable import com.stripe.android.paymentsheet.PaymentSheet.BillingDetailsCollectionConfiguration.AddressCollectionMode import com.stripe.android.paymentsheet.ViewActionRecorder import com.stripe.android.testing.PaymentMethodFactory @@ -38,7 +40,7 @@ internal class FakeUpdatePaymentMethodInteractor( ), override val setAsDefaultCheckboxEnabled: Boolean = true, override val canUpdateCardExpiryAndBillingDetails: Boolean = false, - override val canUpdateCardBrandChoice: Boolean, + override val canChangeCbc: Boolean, private val editCardDetailsInteractorFactory: EditCardDetailsInteractor.Factory = DefaultEditCardDetailsInteractor .Factory(), ) : UpdatePaymentMethodInteractor { @@ -47,17 +49,17 @@ internal class FakeUpdatePaymentMethodInteractor( displayableSavedPaymentMethod ) override val editCardDetailsInteractor: EditCardDetailsInteractor by lazy { - val isModifiable = displayableSavedPaymentMethod.isModifiable( + val isModifiable = displayableSavedPaymentMethod.paymentMethod.isModifiable( canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, - canUpdateCardBrandChoice = canUpdateCardBrandChoice, + canChangeCbc = canChangeCbc, ) editCardDetailsInteractorFactory.create( coroutineScope = TestScope(), cardEditConfiguration = CardEditConfiguration( cardBrandFilter = cardBrandFilter, isCbcModifiable = isModifiable && - canUpdateCardBrandChoice && - displayableSavedPaymentMethod.canChangeCbc(), + canChangeCbc && + displayableSavedPaymentMethod.paymentMethod.hasMultipleNetworks(), areExpiryDateAndAddressModificationSupported = isModifiable && canUpdateCardExpiryAndBillingDetails ), requiresModification = true, diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentOptionsScreenshotTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentOptionsScreenshotTest.kt index aed690e078d..adc836f2b0f 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentOptionsScreenshotTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentOptionsScreenshotTest.kt @@ -115,7 +115,6 @@ class PaymentOptionsScreenshotTest { DisplayableSavedPaymentMethod.create( displayName = "Card".resolvableString, paymentMethod = createCard("1234", addNetworks = true), - isCbcEligible = true, ), ), ) @@ -189,7 +188,6 @@ class PaymentOptionsScreenshotTest { DisplayableSavedPaymentMethod.create( displayName = "Card".resolvableString, paymentMethod = createCard("1234", addNetworks = true), - isCbcEligible = true, ), ), ) diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentSheetScreenUpdatePaymentMethodScreenshotTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentSheetScreenUpdatePaymentMethodScreenshotTest.kt index 3bcf1857d3f..ade1cc9b0a1 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentSheetScreenUpdatePaymentMethodScreenshotTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentSheetScreenUpdatePaymentMethodScreenshotTest.kt @@ -227,7 +227,7 @@ internal class PaymentSheetScreenUpdatePaymentMethodScreenshotTest { shouldShowSaveButton = isModifiablePaymentMethod || shouldShowSetAsDefaultCheckbox, addressCollectionMode = addressCollectionMode, canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, - canUpdateCardBrandChoice = true, + canChangeCbc = true, ).apply { if (validating) { editCardDetailsInteractor.handleViewAction(EditCardDetailsInteractor.ViewAction.Validate) diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUIScreenshotTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUIScreenshotTest.kt index 7bc93a3f5d9..8378a674e57 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUIScreenshotTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUIScreenshotTest.kt @@ -54,7 +54,7 @@ class UpdatePaymentMethodUIScreenshotTest { shouldShowSetAsDefaultCheckbox = false, shouldShowSaveButton = true, setAsDefaultCheckboxEnabled = false, - canUpdateCardBrandChoice = true, + canChangeCbc = true, initialState = UpdatePaymentMethodInteractor.State( error = null, status = status, diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUITest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUITest.kt index 1a60571052a..33a92f13138 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUITest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUITest.kt @@ -339,7 +339,7 @@ class UpdatePaymentMethodUITest { shouldShowSetAsDefaultCheckbox = shouldShowSetAsDefaultCheckbox, shouldShowSaveButton = shouldShowSaveButton, setAsDefaultCheckboxEnabled = setAsDefaultCheckboxEnabled, - canUpdateCardBrandChoice = true, + canChangeCbc = true, initialState = UpdatePaymentMethodInteractor.State( error = errorMessage, status = UpdatePaymentMethodInteractor.Status.Idle, 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 a2383a574bb..a3f552c4161 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 @@ -1813,7 +1813,7 @@ class DefaultPaymentMethodVerticalLayoutInteractorTest { initialPaymentMethods: List = emptyList(), initialMostRecentlySelectedSavedPaymentMethod: PaymentMethod? = null, canUpdateCardExpiryAndBillingDetails: Boolean = false, - canUpdateCardBrandChoice: Boolean = true, + canChangeCbc: Boolean = true, shouldUpdateVerticalModeSelection: (String?) -> Boolean = { paymentMethodCode -> val requiresFormScreen = paymentMethodCode != null && formTypeForCode(paymentMethodCode) == FormHelper.FormType.UserInteractionRequired @@ -1866,7 +1866,7 @@ class DefaultPaymentMethodVerticalLayoutInteractorTest { canRemove = canRemove, walletsState = walletsState, canUpdateCardExpiryAndBillingDetails = stateFlowOf(canUpdateCardExpiryAndBillingDetails), - canUpdateCardBrandChoice = stateFlowOf(canUpdateCardBrandChoice), + canChangeCbc = stateFlowOf(canChangeCbc), updateSelection = { paymentSelection, isFormScreen -> selection.value = paymentSelection updateSelectionTurbine.add(isFormScreen) diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/verticalmode/VerticalModeInitialScreenFactoryTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/verticalmode/VerticalModeInitialScreenFactoryTest.kt index 6e4ea403506..708f70f119c 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/verticalmode/VerticalModeInitialScreenFactoryTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/verticalmode/VerticalModeInitialScreenFactoryTest.kt @@ -155,7 +155,8 @@ class VerticalModeInitialScreenFactoryTest { selection = fakeViewModel.selection, customerMetadata = stateFlowOf( paymentMethodMetadata.customerMetadata - ) + ), + paymentMethodMetadataFlow = stateFlowOf(null), ) if (hasSavedPaymentMethods) { customerStateHolder.setCustomerState( diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/viewmodels/PaymentOptionsItemsMapperTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/viewmodels/PaymentOptionsItemsMapperTest.kt index eeff412ead6..982a525caf7 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/viewmodels/PaymentOptionsItemsMapperTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/viewmodels/PaymentOptionsItemsMapperTest.kt @@ -34,7 +34,6 @@ class PaymentOptionsItemsMapperTest { linkBrand = linkBrandFlow, isNotPaymentFlow = true, nameProvider = { it!!.resolvableString }, - isCbcEligible = { false }, customerMetadata = getDefaultCustomerMetadataFlow(), ) @@ -67,7 +66,6 @@ class PaymentOptionsItemsMapperTest { linkBrand = linkBrandFlow, isNotPaymentFlow = false, nameProvider = { it!!.resolvableString }, - isCbcEligible = { false }, customerMetadata = getDefaultCustomerMetadataFlow(), ) @@ -118,7 +116,6 @@ class PaymentOptionsItemsMapperTest { linkBrand = linkBrandFlow, isNotPaymentFlow = false, nameProvider = { it!!.resolvableString }, - isCbcEligible = { false }, customerMetadata = getDefaultCustomerMetadataFlow( isPaymentMethodSetAsDefaultEnabled = isSetAsDefaultEnabled ), From af3b6b4ea62cdec5bf4bc39082bdda23362f496e Mon Sep 17 00:00:00 2001 From: Chengtin Tsai Date: Mon, 6 Jul 2026 14:01:06 -0700 Subject: [PATCH 6/7] Restore saved card expiry coverage Committed-By-Agent: codex Co-authored-by: codex Committed-By-Agent: codex Co-authored-by: codex Committed-By-Agent: codex Co-authored-by: codex Committed-By-Agent: codex Co-authored-by: codex --- .../paymentmethod/CustomerMetadata.kt | 14 ++-- .../SavedPaymentMethodEditability.kt | 2 + .../ui/UpdatePaymentMethodInteractor.kt | 12 ++- .../PaymentMethodVerticalLayoutInteractor.kt | 2 +- .../CustomerSheetViewModelTest.kt | 3 +- .../paymentmethod/CustomerMetadataTest.kt | 26 +++++++ .../PaymentMethodMetadataFactory.kt | 2 - .../PaymentMethodMetadataFixtures.kt | 2 - .../embedded/manage/EmbeddedNavigatorTest.kt | 14 ++-- .../manage/InitialManageScreenFactoryTest.kt | 1 - ...layableSavedPaymentMethodModifiableTest.kt | 74 ++++++++++++++----- ...DefaultSavedPaymentMethodRepositoryTest.kt | 2 - .../state/CreateCustomerStateTest.kt | 2 - .../DefaultAnalyticsMetadataFactoryTest.kt | 1 - .../state/DefaultPaymentMethodFilterTest.kt | 1 - .../state/DefaultRetrieveCustomerEmailTest.kt | 2 - ...efaultUpdatePaymentMethodInteractorTest.kt | 49 +----------- .../ui/FakeUpdatePaymentMethodInteractor.kt | 6 +- ...ScreenUpdatePaymentMethodScreenshotTest.kt | 1 - .../ui/UpdatePaymentMethodUIScreenshotTest.kt | 1 - .../ui/UpdatePaymentMethodUITest.kt | 1 - 21 files changed, 110 insertions(+), 108 deletions(-) diff --git a/paymentsheet/src/main/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadata.kt b/paymentsheet/src/main/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadata.kt index 64b9f111eef..fccbb3db52b 100644 --- a/paymentsheet/src/main/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadata.kt +++ b/paymentsheet/src/main/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadata.kt @@ -29,8 +29,9 @@ internal sealed class CustomerMetadata : Parcelable { override val saveConsent: PaymentMethodSaveConsentBehavior, override val canRemoveLastPaymentMethod: Boolean, override val canUpdateCardExpiryAndBillingDetails: Boolean, - override val canUpdateCardBrandChoice: Boolean, - ) : CustomerMetadata() + ) : CustomerMetadata() { + override val canUpdateCardBrandChoice: Boolean get() = true + } @Parcelize data class CustomerSession( @@ -42,8 +43,9 @@ internal sealed class CustomerMetadata : Parcelable { override val saveConsent: PaymentMethodSaveConsentBehavior, override val canRemoveLastPaymentMethod: Boolean, override val canUpdateCardExpiryAndBillingDetails: Boolean, - override val canUpdateCardBrandChoice: Boolean, - ) : CustomerMetadata() + ) : CustomerMetadata() { + override val canUpdateCardBrandChoice: Boolean get() = true + } @Parcelize data class CheckoutSession( @@ -119,7 +121,6 @@ internal sealed class CustomerMetadata : Parcelable { canRemoveLastPaymentMethod = canRemoveLastPaymentMethod, // Should always be enabled when using `customer_session` canUpdateCardExpiryAndBillingDetails = true, - canUpdateCardBrandChoice = true, ) } @@ -151,7 +152,6 @@ internal sealed class CustomerMetadata : Parcelable { */ canRemoveLastPaymentMethod = configuration.allowsRemovalOfLastSavedPaymentMethod, canUpdateCardExpiryAndBillingDetails = false, - canUpdateCardBrandChoice = true, ) } @@ -179,7 +179,6 @@ internal sealed class CustomerMetadata : Parcelable { saveConsent = saveConsent, canRemoveLastPaymentMethod = canRemoveLastPaymentMethod, canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, - canUpdateCardBrandChoice = true, ) } else { LegacyEphemeralKey( @@ -190,7 +189,6 @@ internal sealed class CustomerMetadata : Parcelable { saveConsent = saveConsent, canRemoveLastPaymentMethod = canRemoveLastPaymentMethod, canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, - canUpdateCardBrandChoice = true, ) } } diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodEditability.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodEditability.kt index 0f44e1fda7d..f5b11cd3270 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodEditability.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/SavedPaymentMethodEditability.kt @@ -20,6 +20,8 @@ internal fun PaymentMethod.hasMultipleNetworks(): Boolean { internal fun PaymentMethod.Card.isExpired(): Boolean { val cardExpiryMonth = expiryMonth val cardExpiryYear = expiryYear + // If the card's expiration dates are missing, we can't conclude that it is expired, so we don't want to + // show the user an expired card error. return cardExpiryMonth != null && cardExpiryYear != null && !DateUtils.isExpiryDataValid( expiryMonth = cardExpiryMonth, diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodInteractor.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodInteractor.kt index 6426d93ad1f..38a8b2b76a8 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodInteractor.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodInteractor.kt @@ -10,13 +10,13 @@ import com.stripe.android.model.LinkPaymentDetails import com.stripe.android.model.PaymentMethod import com.stripe.android.paymentsheet.CardUpdateParams import com.stripe.android.paymentsheet.DisplayableSavedPaymentMethod -import com.stripe.android.paymentsheet.hasMultipleNetworks -import com.stripe.android.paymentsheet.isModifiable import com.stripe.android.paymentsheet.PaymentSheet.BillingDetailsCollectionConfiguration import com.stripe.android.paymentsheet.PaymentSheet.BillingDetailsCollectionConfiguration.AddressCollectionMode import com.stripe.android.paymentsheet.PaymentSheet.BillingDetailsCollectionConfiguration.CollectionMode import com.stripe.android.paymentsheet.R import com.stripe.android.paymentsheet.SavedPaymentMethod +import com.stripe.android.paymentsheet.hasMultipleNetworks +import com.stripe.android.paymentsheet.isModifiable import com.stripe.android.uicore.elements.AutocompleteAddressInteractor import com.stripe.android.uicore.utils.combineAsStateFlow import com.stripe.android.uicore.utils.mapAsStateFlow @@ -150,7 +150,9 @@ internal class DefaultUpdatePaymentMethodInteractor( canChangeCbc = canChangeCbc, ) override val shouldShowCardBrandDropdown: Boolean - get() = isModifiablePaymentMethod && canChangeCbc && displayableSavedPaymentMethod.paymentMethod.hasMultipleNetworks() + get() = isModifiablePaymentMethod && + canChangeCbc && + displayableSavedPaymentMethod.paymentMethod.hasMultipleNetworks() override val topBarState: PaymentSheetTopBarState = PaymentSheetTopBarStateFactory.create( isLiveMode = isLiveMode, @@ -192,7 +194,9 @@ internal class DefaultUpdatePaymentMethodInteractor( val payload = EditCardPayload.create(savedPaymentMethodCard.card, savedPaymentMethodCard.billingDetails) val cardEditConfiguration = CardEditConfiguration( cardBrandFilter = cardBrandFilter, - isCbcModifiable = isModifiable && canChangeCbc && displayableSavedPaymentMethod.paymentMethod.hasMultipleNetworks(), + isCbcModifiable = isModifiable && + canChangeCbc && + displayableSavedPaymentMethod.paymentMethod.hasMultipleNetworks(), areExpiryDateAndAddressModificationSupported = isModifiable && canUpdateCardExpiryAndBillingDetails, ) return editCardDetailsInteractorFactory.create( 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 6388fc064c8..3a3b5b7c785 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,11 +14,11 @@ import com.stripe.android.paymentsheet.CustomerStateHolder import com.stripe.android.paymentsheet.DefaultFormHelper import com.stripe.android.paymentsheet.DisplayableSavedPaymentMethod import com.stripe.android.paymentsheet.FormHelper.FormType -import com.stripe.android.paymentsheet.isModifiable import com.stripe.android.paymentsheet.R import com.stripe.android.paymentsheet.analytics.code import com.stripe.android.paymentsheet.forms.FormArgumentsFactory import com.stripe.android.paymentsheet.forms.FormFieldValues +import com.stripe.android.paymentsheet.isModifiable import com.stripe.android.paymentsheet.model.PaymentMethodIncentive import com.stripe.android.paymentsheet.model.PaymentSelection import com.stripe.android.paymentsheet.model.mandateTextFromPaymentMethodMetadata diff --git a/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetViewModelTest.kt b/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetViewModelTest.kt index 21f30e26aa8..680edfad6b7 100644 --- a/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetViewModelTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/customersheet/CustomerSheetViewModelTest.kt @@ -2681,8 +2681,7 @@ class CustomerSheetViewModelTest { ) ) - val selectPaymentMethodState = awaitViewState() - + awaitViewState() } } diff --git a/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadataTest.kt b/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadataTest.kt index 6d7ba2b1b7d..dd04b1453fc 100644 --- a/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadataTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/CustomerMetadataTest.kt @@ -30,6 +30,32 @@ internal class CustomerMetadataTest { assertThat(metadata.canUpdateCardBrandChoice).isFalse() } + @Test + fun `CustomerSession and legacy ephemeral key should support card brand updates`() { + val customerSessionMetadata = CustomerMetadata.CustomerSession( + id = "cus_123", + ephemeralKeySecret = "ek_123", + customerSessionClientSecret = "cuss_123", + isPaymentMethodSetAsDefaultEnabled = false, + removePaymentMethod = PaymentMethodRemovePermission.Full, + saveConsent = PaymentMethodSaveConsentBehavior.Legacy, + canRemoveLastPaymentMethod = true, + canUpdateCardExpiryAndBillingDetails = true, + ) + val legacyEphemeralKeyMetadata = CustomerMetadata.LegacyEphemeralKey( + id = "cus_123", + ephemeralKeySecret = "ek_123", + isPaymentMethodSetAsDefaultEnabled = false, + removePaymentMethod = PaymentMethodRemovePermission.Full, + saveConsent = PaymentMethodSaveConsentBehavior.Legacy, + canRemoveLastPaymentMethod = true, + canUpdateCardExpiryAndBillingDetails = false, + ) + + assertThat(customerSessionMetadata.canUpdateCardBrandChoice).isTrue() + assertThat(legacyEphemeralKeyMetadata.canUpdateCardBrandChoice).isTrue() + } + @Test fun `Should create 'Permissions' for customer session properly with permissions disabled`() { customerSessionPermissionsTest( 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 9dbc2638103..c84827aa8ca 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 @@ -106,7 +106,6 @@ internal object PaymentMethodMetadataFactory { saveConsent = saveConsent, canRemoveLastPaymentMethod = canRemoveLastPaymentMethod, canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, - canUpdateCardBrandChoice = true, ) } else { CustomerMetadata.LegacyEphemeralKey( @@ -117,7 +116,6 @@ internal object PaymentMethodMetadataFactory { saveConsent = saveConsent, canRemoveLastPaymentMethod = canRemoveLastPaymentMethod, canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, - canUpdateCardBrandChoice = true, ) } } else { diff --git a/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/PaymentMethodMetadataFixtures.kt b/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/PaymentMethodMetadataFixtures.kt index e9797c70f46..0e910314382 100644 --- a/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/PaymentMethodMetadataFixtures.kt +++ b/paymentsheet/src/test/java/com/stripe/android/lpmfoundations/paymentmethod/PaymentMethodMetadataFixtures.kt @@ -17,7 +17,6 @@ internal object PaymentMethodMetadataFixtures { saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, canUpdateCardExpiryAndBillingDetails = false, - canUpdateCardBrandChoice = true, ) internal val DEFAULT_CUSTOMER_INTEGRATION_METADATA = IntegrationMetadata.CustomerSheet( @@ -40,7 +39,6 @@ internal object PaymentMethodMetadataFixtures { saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, canUpdateCardExpiryAndBillingDetails = false, - canUpdateCardBrandChoice = true, ) internal fun getDefaultCustomerMetadata( diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/manage/EmbeddedNavigatorTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/manage/EmbeddedNavigatorTest.kt index 6f260ff67b2..5263077dc32 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/manage/EmbeddedNavigatorTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/manage/EmbeddedNavigatorTest.kt @@ -40,7 +40,7 @@ internal class EmbeddedNavigatorTest { assertThat(navigator.canGoBack).isFalse() val newScreen = EmbeddedNavigator.Screen.ManageUpdate( - FakeUpdatePaymentMethodInteractor(canChangeCbc = true) + FakeUpdatePaymentMethodInteractor() ) navigator.performAction(EmbeddedNavigator.Action.GoToScreen(newScreen)) assertThat(awaitItem()).isEqualTo(newScreen) @@ -66,7 +66,7 @@ internal class EmbeddedNavigatorTest { assertThat(awaitItem()).isEqualTo(initialScreen) val newScreen = EmbeddedNavigator.Screen.ManageUpdate( - FakeUpdatePaymentMethodInteractor(canChangeCbc = true) + FakeUpdatePaymentMethodInteractor() ) navigator.performAction(EmbeddedNavigator.Action.GoToScreen(newScreen)) assertThat(awaitItem()).isEqualTo(newScreen) @@ -141,7 +141,7 @@ internal class EmbeddedNavigatorTest { @Test fun `Close while on ManageUpdate calls onHideEditablePaymentOption`() = testScenario { val manageUpdateScreen = EmbeddedNavigator.Screen.ManageUpdate( - FakeUpdatePaymentMethodInteractor(canChangeCbc = true) + FakeUpdatePaymentMethodInteractor() ) navigator.screen.test { assertThat(awaitItem()).isEqualTo(initialScreen) @@ -161,7 +161,7 @@ internal class EmbeddedNavigatorTest { coroutineScope = this, eventReporter = eventReporter, initialScreen = EmbeddedNavigator.Screen.ManageUpdate( - FakeUpdatePaymentMethodInteractor(canChangeCbc = true) + FakeUpdatePaymentMethodInteractor() ), ) assertThat(eventReporter.showEditablePaymentOptionCalls.awaitItem()).isEqualTo(Unit) @@ -222,7 +222,7 @@ internal class EmbeddedNavigatorTest { @Test fun `ManageUpdate topBarState returns interactor topBarState`() { - val interactor = FakeUpdatePaymentMethodInteractor(canChangeCbc = true) + val interactor = FakeUpdatePaymentMethodInteractor() val screen = EmbeddedNavigator.Screen.ManageUpdate(interactor) val topBarState = screen.topBarState().value @@ -231,7 +231,7 @@ internal class EmbeddedNavigatorTest { @Test fun `ManageUpdate title returns interactor screenTitle`() { - val interactor = FakeUpdatePaymentMethodInteractor(canChangeCbc = true) + val interactor = FakeUpdatePaymentMethodInteractor() val screen = EmbeddedNavigator.Screen.ManageUpdate(interactor) val title = screen.title().value @@ -241,7 +241,6 @@ internal class EmbeddedNavigatorTest { @Test fun `ManageUpdate isPerformingNetworkOperation when idle returns false`() { val interactor = FakeUpdatePaymentMethodInteractor( - canChangeCbc = true, initialState = UpdatePaymentMethodInteractor.State( error = null, status = UpdatePaymentMethodInteractor.Status.Idle, @@ -256,7 +255,6 @@ internal class EmbeddedNavigatorTest { @Test fun `ManageUpdate isPerformingNetworkOperation when updating returns true`() { val interactor = FakeUpdatePaymentMethodInteractor( - canChangeCbc = true, initialState = UpdatePaymentMethodInteractor.State( error = null, status = UpdatePaymentMethodInteractor.Status.Updating, diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/manage/InitialManageScreenFactoryTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/manage/InitialManageScreenFactoryTest.kt index a4aea861652..0c24cb8f83d 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/manage/InitialManageScreenFactoryTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentelement/embedded/manage/InitialManageScreenFactoryTest.kt @@ -58,7 +58,6 @@ internal class InitialManageScreenFactoryTest { FakeUpdatePaymentMethodInteractor( displayableSavedPaymentMethod = displayableSavedPaymentMethod, canRemove = customerStateHolder.canRemove.value, - canChangeCbc = true, isExpiredCard = false, isModifiablePaymentMethod = true, viewActionRecorder = ViewActionRecorder(), diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethodModifiableTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethodModifiableTest.kt index 2a74eea26ac..9e9ac413597 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethodModifiableTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/DisplayableSavedPaymentMethodModifiableTest.kt @@ -3,7 +3,6 @@ package com.stripe.android.paymentsheet import com.google.common.truth.Truth.assertThat import com.stripe.android.model.PaymentMethod import com.stripe.android.model.PaymentMethodFixtures -import junit.framework.TestCase.assertEquals import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.Parameterized @@ -20,19 +19,6 @@ class DisplayableSavedPaymentMethodModifiableTest(private val params: IsModifiab ) ) - assertEquals( - "Expected isModifiable to be ${params.expectedResult} for parameters: " + - "canUpdatePaymentMethod=${params.canUpdatePaymentMethod}, " + - "canChangeCbc=${params.canChangeCbc}, " + - "availableNetworks=${params.availableNetworks}, " + - "cardExpired=${params.cardExpired}", - params.expectedResult, - paymentMethod.isModifiable( - canUpdateCardExpiryAndBillingDetails = params.canUpdatePaymentMethod, - canChangeCbc = params.canChangeCbc, - ) - ) - assertThat( paymentMethod.isModifiable( canUpdateCardExpiryAndBillingDetails = params.canUpdatePaymentMethod, @@ -43,12 +29,62 @@ class DisplayableSavedPaymentMethodModifiableTest(private val params: IsModifiab @Test fun `isModifiable returns false for non-card payment methods`() { - assertThat( - PaymentMethodFixtures.LINK_PAYMENT_METHOD.isModifiable( - canUpdateCardExpiryAndBillingDetails = true, - canChangeCbc = true, + listOf( + PaymentMethodFixtures.LINK_PAYMENT_METHOD, + PaymentMethodFixtures.US_BANK_ACCOUNT, + ).forEach { paymentMethod -> + assertThat( + paymentMethod.isModifiable( + canUpdateCardExpiryAndBillingDetails = true, + canChangeCbc = true, + ) + ).isFalse() + } + } + + @Test + fun `isExpired returns false when expiry date is missing`() { + listOf( + PaymentMethodFixtures.CARD_PAYMENT_METHOD.card?.copy( + expiryMonth = null, + expiryYear = 2099, + ), + PaymentMethodFixtures.CARD_PAYMENT_METHOD.card?.copy( + expiryMonth = 12, + expiryYear = null, + ), + PaymentMethodFixtures.CARD_PAYMENT_METHOD.card?.copy( + expiryMonth = null, + expiryYear = null, + ) + ).forEach { card -> + assertThat(card?.isExpired()).isFalse() + } + } + + @Test + fun `isModifiable allows cbc updates when expiry date is missing`() { + listOf( + PaymentMethodFixtures.CARD_WITH_NETWORKS_PAYMENT_METHOD.card?.copy( + expiryMonth = null, + expiryYear = 2099, + ), + PaymentMethodFixtures.CARD_WITH_NETWORKS_PAYMENT_METHOD.card?.copy( + expiryMonth = 12, + expiryYear = null, ) - ).isFalse() + ).forEach { card -> + val paymentMethod = PaymentMethodFixtures.CARD_WITH_NETWORKS_PAYMENT_METHOD.copy( + card = card, + ) + + assertThat( + paymentMethod.isModifiable( + canUpdateCardExpiryAndBillingDetails = false, + canChangeCbc = true, + ) + ).isTrue() + } } data class IsModifiableParams( diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/repositories/DefaultSavedPaymentMethodRepositoryTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/repositories/DefaultSavedPaymentMethodRepositoryTest.kt index da5ae6e5ec8..a227dee060d 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/repositories/DefaultSavedPaymentMethodRepositoryTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/repositories/DefaultSavedPaymentMethodRepositoryTest.kt @@ -295,7 +295,6 @@ class DefaultSavedPaymentMethodRepositoryTest { saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, canUpdateCardExpiryAndBillingDetails = false, - canUpdateCardBrandChoice = true, ) private val LEGACY_METADATA = CustomerMetadata.LegacyEphemeralKey( @@ -306,7 +305,6 @@ class DefaultSavedPaymentMethodRepositoryTest { saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, canUpdateCardExpiryAndBillingDetails = false, - canUpdateCardBrandChoice = true, ) } } diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/CreateCustomerStateTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/CreateCustomerStateTest.kt index 02ff9507190..76c22fcb071 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/CreateCustomerStateTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/CreateCustomerStateTest.kt @@ -273,7 +273,6 @@ internal class CreateCustomerStateTest { saveConsent = PaymentMethodSaveConsentBehavior.Enabled, canRemoveLastPaymentMethod = true, canUpdateCardExpiryAndBillingDetails = true, - canUpdateCardBrandChoice = true, ) val LEGACY_EK_METADATA = CustomerMetadata.LegacyEphemeralKey( @@ -284,7 +283,6 @@ internal class CreateCustomerStateTest { saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, canUpdateCardExpiryAndBillingDetails = false, - canUpdateCardBrandChoice = true, ) fun createElementsSessionCustomer( diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultAnalyticsMetadataFactoryTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultAnalyticsMetadataFactoryTest.kt index fd453ef2bea..de850bcaa27 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultAnalyticsMetadataFactoryTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultAnalyticsMetadataFactoryTest.kt @@ -840,7 +840,6 @@ class DefaultAnalyticsMetadataFactoryTest { saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, canUpdateCardExpiryAndBillingDetails = true, - canUpdateCardBrandChoice = true, ) private fun createElementsSessionCustomer(): ElementsSession.Customer { diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultPaymentMethodFilterTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultPaymentMethodFilterTest.kt index 806bd95c128..81bd1d0244f 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultPaymentMethodFilterTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultPaymentMethodFilterTest.kt @@ -217,7 +217,6 @@ class DefaultPaymentMethodFilterTest { saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = false, canUpdateCardExpiryAndBillingDetails = false, - canUpdateCardBrandChoice = true, ), remoteDefaultPaymentMethodId = remoteDefaultPaymentMethodId, localSavedSelection = CompletableDeferred(localSavedSelection), diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultRetrieveCustomerEmailTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultRetrieveCustomerEmailTest.kt index 851a09f91ea..5daf8d5ebb5 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultRetrieveCustomerEmailTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/state/DefaultRetrieveCustomerEmailTest.kt @@ -158,7 +158,6 @@ internal class DefaultRetrieveCustomerEmailTest { saveConsent = PaymentMethodSaveConsentBehavior.Disabled(overrideAllowRedisplay = null), canRemoveLastPaymentMethod = false, canUpdateCardExpiryAndBillingDetails = false, - canUpdateCardBrandChoice = true, ) val LEGACY_EK_METADATA = CustomerMetadata.LegacyEphemeralKey( @@ -169,7 +168,6 @@ internal class DefaultRetrieveCustomerEmailTest { saveConsent = PaymentMethodSaveConsentBehavior.Legacy, canRemoveLastPaymentMethod = true, canUpdateCardExpiryAndBillingDetails = false, - canUpdateCardBrandChoice = true, ) val CHECKOUT_SESSION_METADATA = CustomerMetadata.CheckoutSession( diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/DefaultUpdatePaymentMethodInteractorTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/DefaultUpdatePaymentMethodInteractorTest.kt index 72476b3dd70..3708367398d 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/DefaultUpdatePaymentMethodInteractorTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/DefaultUpdatePaymentMethodInteractorTest.kt @@ -47,7 +47,6 @@ class DefaultUpdatePaymentMethodInteractorTest { canRemove = true, displayableSavedPaymentMethod = paymentMethod, onRemovePaymentMethod = ::onRemovePaymentMethod, - canChangeCbc = true, ) { interactor.handleViewAction(UpdatePaymentMethodInteractor.ViewAction.RemovePaymentMethod) @@ -58,7 +57,6 @@ class DefaultUpdatePaymentMethodInteractorTest { @Test fun creatingInteractorInLiveMode_setsTopBarStateCorrectly() = runScenario( isLiveMode = true, - canChangeCbc = true, ) { assertThat(interactor.topBarState.showTestModeLabel).isFalse() } @@ -66,7 +64,6 @@ class DefaultUpdatePaymentMethodInteractorTest { @Test fun creatingInteractorInTestMode_setsTopBarStateCorrectly() = runScenario( isLiveMode = false, - canChangeCbc = true, ) { assertThat(interactor.topBarState.showTestModeLabel).isTrue() } @@ -84,7 +81,6 @@ class DefaultUpdatePaymentMethodInteractorTest { canRemove = true, displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), onRemovePaymentMethod = ::onRemovePaymentMethod, - canChangeCbc = true, ) { interactor.handleViewAction(UpdatePaymentMethodInteractor.ViewAction.RemovePaymentMethod) @@ -100,7 +96,6 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures .EXPIRED_CARD_PAYMENT_METHOD .toDisplayableSavedPaymentMethod(), - canChangeCbc = true, ) { interactor.state.test { assertThat(awaitItem().error).isEqualTo( @@ -116,7 +111,6 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures .EXPIRED_CARD_PAYMENT_METHOD .toDisplayableSavedPaymentMethod(), - canChangeCbc = true, ) { assertThat(interactor.isModifiablePaymentMethod).isFalse() } @@ -126,7 +120,6 @@ class DefaultUpdatePaymentMethodInteractorTest { fun nonExpiredCard_hasNoInitialError() { runScenario( displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), - canChangeCbc = true, ) { interactor.state.test { assertThat(awaitItem().error).isNull() @@ -140,7 +133,6 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures .CARD_WITH_NETWORKS_PAYMENT_METHOD .toDisplayableSavedPaymentMethod(), - canChangeCbc = true, ) { assertThat(interactor.isModifiablePaymentMethod).isTrue() } @@ -152,7 +144,6 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures.CARD_WITH_NETWORKS_PAYMENT_METHOD.toDisplayableSavedPaymentMethod(), updatePaymentMethodExecutor = { paymentMethod, _ -> Result.success(paymentMethod) }, - canChangeCbc = true, ) { interactor.cardParamsUpdateAction(CardBrand.Visa) @@ -176,7 +167,6 @@ class DefaultUpdatePaymentMethodInteractorTest { updatedPaymentMethod = paymentMethod Result.success(paymentMethod) }, - canChangeCbc = true, ) { interactor.cardParamsUpdateAction(CardBrand.CartesBancaires) @@ -220,7 +210,6 @@ class DefaultUpdatePaymentMethodInteractorTest { runScenario( displayableSavedPaymentMethod = initialPaymentMethod.toDisplayableSavedPaymentMethod(), updatePaymentMethodExecutor = ::updatePaymentMethodExecutor, - canChangeCbc = true, ) { interactor.handleViewAction(UpdatePaymentMethodInteractor.ViewAction.SaveButtonPressed) @@ -243,7 +232,6 @@ class DefaultUpdatePaymentMethodInteractorTest { .CARD_WITH_NETWORKS_PAYMENT_METHOD .toDisplayableSavedPaymentMethod(), updatePaymentMethodExecutor = ::updatePaymentMethodExecutor, - canChangeCbc = true, ) { interactor.cardParamsUpdateAction(CardBrand.CartesBancaires) interactor.handleViewAction(UpdatePaymentMethodInteractor.ViewAction.SaveButtonPressed) @@ -262,7 +250,6 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures.SEPA_DEBIT_PAYMENT_METHOD.toDisplayableSavedPaymentMethod(), shouldShowSetAsDefaultCheckbox = true, - canChangeCbc = true, ) { assertThat(interactor.shouldShowSetAsDefaultCheckbox).isTrue() } @@ -271,7 +258,6 @@ class DefaultUpdatePaymentMethodInteractorTest { fun setAsDefaultCheckbox_shownForCards() = runScenario( displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), shouldShowSetAsDefaultCheckbox = true, - canChangeCbc = true, ) { assertThat(interactor.shouldShowSetAsDefaultCheckbox).isTrue() } @@ -280,7 +266,6 @@ class DefaultUpdatePaymentMethodInteractorTest { fun setAsDefaultCheckbox_shownForUsBankAccount() = runScenario( displayableSavedPaymentMethod = PaymentMethodFixtures.US_BANK_ACCOUNT.toDisplayableSavedPaymentMethod(), shouldShowSetAsDefaultCheckbox = true, - canChangeCbc = true, ) { assertThat(interactor.shouldShowSetAsDefaultCheckbox).isTrue() } @@ -290,7 +275,6 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), shouldShowSetAsDefaultCheckbox = true, isDefaultPaymentMethod = true, - canChangeCbc = true, ) { assertThat(interactor.shouldShowSaveButton).isFalse() } @@ -302,7 +286,6 @@ class DefaultUpdatePaymentMethodInteractorTest { .toDisplayableSavedPaymentMethod(), shouldShowSetAsDefaultCheckbox = true, isDefaultPaymentMethod = true, - canChangeCbc = true, ) { assertThat(interactor.shouldShowSaveButton).isTrue() } @@ -314,7 +297,6 @@ class DefaultUpdatePaymentMethodInteractorTest { .toDisplayableSavedPaymentMethod(), shouldShowSetAsDefaultCheckbox = true, isDefaultPaymentMethod = true, - canChangeCbc = true, ) { interactor.state.test { assertThat(awaitItem().isSaveButtonEnabled).isFalse() @@ -332,7 +314,6 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), shouldShowSetAsDefaultCheckbox = true, isDefaultPaymentMethod = true, - canChangeCbc = true, ) { interactor.state.test { assertThat(awaitItem().setAsDefaultCheckboxChecked).isTrue() @@ -344,7 +325,6 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), shouldShowSetAsDefaultCheckbox = true, isDefaultPaymentMethod = true, - canChangeCbc = true, ) { assertThat(interactor.setAsDefaultCheckboxEnabled).isFalse() } @@ -354,7 +334,6 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), shouldShowSetAsDefaultCheckbox = true, isDefaultPaymentMethod = false, - canChangeCbc = true, ) { assertThat(interactor.setAsDefaultCheckboxEnabled).isTrue() } @@ -362,7 +341,6 @@ class DefaultUpdatePaymentMethodInteractorTest { @Test fun setAsDefaultCheckboxChangedViewAction_updatesState() = runScenario( shouldShowSetAsDefaultCheckbox = true, - canChangeCbc = true, ) { val expectedInitialCheckedValue = false val expectedUpdatedCheckedValue = true @@ -389,7 +367,6 @@ class DefaultUpdatePaymentMethodInteractorTest { runScenario( shouldShowSetAsDefaultCheckbox = true, onSetDefaultPaymentMethod = { Result.success(Unit) }, - canChangeCbc = true, ) { interactor.handleViewAction(UpdatePaymentMethodInteractor.ViewAction.SaveButtonPressed) } @@ -400,7 +377,6 @@ class DefaultUpdatePaymentMethodInteractorTest { runScenario( shouldShowSetAsDefaultCheckbox = true, onSetDefaultPaymentMethod = { Result.success(Unit) }, - canChangeCbc = true, ) { interactor.handleViewAction( UpdatePaymentMethodInteractor.ViewAction.SetAsDefaultCheckboxChanged( @@ -418,7 +394,6 @@ class DefaultUpdatePaymentMethodInteractorTest { fun setAsDefault_failure_displaysErrorMessage() = runScenario( shouldShowSetAsDefaultCheckbox = true, onSetDefaultPaymentMethod = { Result.failure(IllegalStateException("Fake error")) }, - canChangeCbc = true, ) { interactor.handleViewAction( UpdatePaymentMethodInteractor.ViewAction.SetAsDefaultCheckboxChanged( @@ -444,7 +419,6 @@ class DefaultUpdatePaymentMethodInteractorTest { shouldShowSetAsDefaultCheckbox = true, onSetDefaultPaymentMethod = { Result.success(Unit) }, updatePaymentMethodExecutor = { _, _ -> Result.failure(expectedError) }, - canChangeCbc = true, ) { updateCardAndDefaultPaymentMethod(interactor) @@ -463,7 +437,6 @@ class DefaultUpdatePaymentMethodInteractorTest { shouldShowSetAsDefaultCheckbox = true, onSetDefaultPaymentMethod = { Result.failure(IllegalStateException("Fake error")) }, updatePaymentMethodExecutor = { paymentMethod, _ -> Result.success(paymentMethod) }, - canChangeCbc = true, ) { updateCardAndDefaultPaymentMethod(interactor) @@ -482,7 +455,6 @@ class DefaultUpdatePaymentMethodInteractorTest { shouldShowSetAsDefaultCheckbox = true, onSetDefaultPaymentMethod = { Result.failure(IllegalStateException("Fake error")) }, updatePaymentMethodExecutor = { _, _ -> Result.failure(IllegalStateException("Fake error")) }, - canChangeCbc = true, ) { updateCardAndDefaultPaymentMethod(interactor) @@ -497,7 +469,6 @@ class DefaultUpdatePaymentMethodInteractorTest { displayableSavedPaymentMethod = PaymentMethodFixtures .CARD_WITH_NETWORKS_PAYMENT_METHOD .toDisplayableSavedPaymentMethod(), - canChangeCbc = true, ) { assertThat(interactor.shouldShowSaveButton).isTrue() } @@ -506,7 +477,6 @@ class DefaultUpdatePaymentMethodInteractorTest { fun shouldShowSaveButton_whenSetAsDefaultCheckboxShown() = runScenario( displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), shouldShowSetAsDefaultCheckbox = true, - canChangeCbc = true, ) { assertThat(interactor.shouldShowSaveButton).isTrue() } @@ -517,7 +487,6 @@ class DefaultUpdatePaymentMethodInteractorTest { .CARD_WITH_NETWORKS_PAYMENT_METHOD .toDisplayableSavedPaymentMethod(), shouldShowSetAsDefaultCheckbox = true, - canChangeCbc = true, ) { assertThat(interactor.shouldShowSaveButton).isTrue() } @@ -526,7 +495,6 @@ class DefaultUpdatePaymentMethodInteractorTest { fun shouldNotShowSaveButton_whenNothingIsChangeable() = runScenario( displayableSavedPaymentMethod = PaymentMethodFixtures.displayableCard(), shouldShowSetAsDefaultCheckbox = false, - canChangeCbc = true, ) { assertThat(interactor.shouldShowSaveButton).isFalse() } @@ -536,7 +504,6 @@ class DefaultUpdatePaymentMethodInteractorTest { isDefaultPaymentMethod = true, onSetDefaultPaymentMethod = { _ -> notImplemented() }, updatePaymentMethodExecutor = { _, _ -> notImplemented() }, - canChangeCbc = true, ) { interactor.handleViewAction(UpdatePaymentMethodInteractor.ViewAction.SaveButtonPressed) @@ -544,9 +511,7 @@ class DefaultUpdatePaymentMethodInteractorTest { } @Test - fun shouldCreateEditCardInteractor_whenPaymentMethodIsCard() = runScenario( - canChangeCbc = true, - ) { + fun shouldCreateEditCardInteractor_whenPaymentMethodIsCard() = runScenario { assertThat(interactor.editCardDetailsInteractor).isNotNull() } @@ -557,7 +522,6 @@ class DefaultUpdatePaymentMethodInteractorTest { runScenario( displayableSavedPaymentMethod = displayableSavedPaymentMethod, canUpdateCardExpiryAndBillingDetails = true, - canChangeCbc = true, ) { val state = interactor.editCardDetailsInteractor.state.value assertThat(state.cardDetailsState?.shouldShowCardBrandDropdown).isTrue() @@ -589,7 +553,6 @@ class DefaultUpdatePaymentMethodInteractorTest { runScenario( displayableSavedPaymentMethod = displayableSavedPaymentMethod, canUpdateCardExpiryAndBillingDetails = false, - canChangeCbc = true, ) { val state = interactor.editCardDetailsInteractor.state.value assertThat(state.cardDetailsState?.shouldShowCardBrandDropdown).isTrue() @@ -602,7 +565,6 @@ class DefaultUpdatePaymentMethodInteractorTest { fun shouldCreateEditCardInteractorCorrectly_whenCbcIneligible_andCanUpdateCardExpiryAndBillingDetails() { runScenario( canUpdateCardExpiryAndBillingDetails = true, - canChangeCbc = true, ) { val state = interactor.editCardDetailsInteractor.state.value assertThat(state.cardDetailsState?.shouldShowCardBrandDropdown).isFalse() @@ -615,7 +577,6 @@ class DefaultUpdatePaymentMethodInteractorTest { fun shouldCreateEditCardInteractorCorrectly_whenCbcIneligible_andCanNotUpdateCardExpiryAndBillingDetails() { runScenario( canUpdateCardExpiryAndBillingDetails = false, - canChangeCbc = true, ) { val state = interactor.editCardDetailsInteractor.state.value assertThat(state.cardDetailsState?.shouldShowCardBrandDropdown).isFalse() @@ -627,7 +588,6 @@ class DefaultUpdatePaymentMethodInteractorTest { @Test fun shouldNotCreateEditCardInteractor_whenPaymentMethodIsNotCard() = runScenario( displayableSavedPaymentMethod = PaymentMethodFixtures.US_BANK_ACCOUNT.toDisplayableSavedPaymentMethod(), - canChangeCbc = true, ) { val exception = assertThrows(IllegalArgumentException::class.java) { interactor.editCardDetailsInteractor @@ -642,7 +602,6 @@ class DefaultUpdatePaymentMethodInteractorTest { val editCardDetailsInteractorFactory = FakeEditCardDetailsInteractorFactory() runScenario( editCardDetailsInteractorFactory = editCardDetailsInteractorFactory, - canChangeCbc = true, ) { interactor.editCardDetailsInteractor editCardDetailsInteractorFactory.onCardUpdateParamsChanged?.invoke( @@ -658,7 +617,6 @@ class DefaultUpdatePaymentMethodInteractorTest { val editCardDetailsInteractorFactory = FakeEditCardDetailsInteractorFactory() runScenario( editCardDetailsInteractorFactory = editCardDetailsInteractorFactory, - canChangeCbc = true, ) { editCardDetailsInteractorFactory.onCardUpdateParamsChanged?.invoke( CardUpdateParams(cardBrand = CardBrand.Visa) @@ -677,7 +635,6 @@ class DefaultUpdatePaymentMethodInteractorTest { addressCollectionMode = AddressCollectionMode.Full, allowedBillingCountries = setOf("us", "CA"), editCardDetailsInteractorFactory = editCardDetailsInteractorFactory, - canChangeCbc = true, ) { assertThat(interactor.editCardDetailsInteractor.state.value).isNotNull() @@ -704,7 +661,6 @@ class DefaultUpdatePaymentMethodInteractorTest { addressCollectionMode = AddressCollectionMode.Full, allowedBillingCountries = setOf("us", "CA"), editCardDetailsInteractorFactory = editCardDetailsInteractorFactory, - canChangeCbc = true, ) { assertThat(interactor.editCardDetailsInteractor.state.value).isNotNull() @@ -730,7 +686,6 @@ class DefaultUpdatePaymentMethodInteractorTest { addressCollectionMode = AddressCollectionMode.Full, allowedBillingCountries = setOf("us", "CA"), editCardDetailsInteractorFactory = FakeEditCardDetailsInteractorFactory(), - canChangeCbc = true, ) { assertThat(interactor.editCardDetailsInteractor).isInstanceOf() @@ -773,7 +728,7 @@ class DefaultUpdatePaymentMethodInteractorTest { shouldShowSetAsDefaultCheckbox: Boolean = false, isDefaultPaymentMethod: Boolean = false, canUpdateCardExpiryAndBillingDetails: Boolean = false, - canChangeCbc: Boolean, + canChangeCbc: Boolean = true, addressCollectionMode: AddressCollectionMode = AddressCollectionMode.Automatic, allowedBillingCountries: Set = setOf("US", "CA"), editCardDetailsInteractorFactory: EditCardDetailsInteractor.Factory = DefaultEditCardDetailsInteractor diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/FakeUpdatePaymentMethodInteractor.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/FakeUpdatePaymentMethodInteractor.kt index 7458654fb7b..0dbbadc9931 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/FakeUpdatePaymentMethodInteractor.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/FakeUpdatePaymentMethodInteractor.kt @@ -7,10 +7,10 @@ import com.stripe.android.model.PaymentMethodFixtures import com.stripe.android.model.PaymentMethodFixtures.toDisplayableSavedPaymentMethod import com.stripe.android.paymentsheet.DisplayableSavedPaymentMethod import com.stripe.android.paymentsheet.PaymentSheet -import com.stripe.android.paymentsheet.hasMultipleNetworks -import com.stripe.android.paymentsheet.isModifiable import com.stripe.android.paymentsheet.PaymentSheet.BillingDetailsCollectionConfiguration.AddressCollectionMode import com.stripe.android.paymentsheet.ViewActionRecorder +import com.stripe.android.paymentsheet.hasMultipleNetworks +import com.stripe.android.paymentsheet.isModifiable import com.stripe.android.testing.PaymentMethodFactory import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -40,7 +40,7 @@ internal class FakeUpdatePaymentMethodInteractor( ), override val setAsDefaultCheckboxEnabled: Boolean = true, override val canUpdateCardExpiryAndBillingDetails: Boolean = false, - override val canChangeCbc: Boolean, + override val canChangeCbc: Boolean = true, private val editCardDetailsInteractorFactory: EditCardDetailsInteractor.Factory = DefaultEditCardDetailsInteractor .Factory(), ) : UpdatePaymentMethodInteractor { diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentSheetScreenUpdatePaymentMethodScreenshotTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentSheetScreenUpdatePaymentMethodScreenshotTest.kt index ade1cc9b0a1..060dda75f82 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentSheetScreenUpdatePaymentMethodScreenshotTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentSheetScreenUpdatePaymentMethodScreenshotTest.kt @@ -227,7 +227,6 @@ internal class PaymentSheetScreenUpdatePaymentMethodScreenshotTest { shouldShowSaveButton = isModifiablePaymentMethod || shouldShowSetAsDefaultCheckbox, addressCollectionMode = addressCollectionMode, canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, - canChangeCbc = true, ).apply { if (validating) { editCardDetailsInteractor.handleViewAction(EditCardDetailsInteractor.ViewAction.Validate) diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUIScreenshotTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUIScreenshotTest.kt index 8378a674e57..6ec3210d46f 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUIScreenshotTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUIScreenshotTest.kt @@ -54,7 +54,6 @@ class UpdatePaymentMethodUIScreenshotTest { shouldShowSetAsDefaultCheckbox = false, shouldShowSaveButton = true, setAsDefaultCheckboxEnabled = false, - canChangeCbc = true, initialState = UpdatePaymentMethodInteractor.State( error = null, status = status, diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUITest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUITest.kt index 33a92f13138..29d9c106583 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUITest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUITest.kt @@ -339,7 +339,6 @@ class UpdatePaymentMethodUITest { shouldShowSetAsDefaultCheckbox = shouldShowSetAsDefaultCheckbox, shouldShowSaveButton = shouldShowSaveButton, setAsDefaultCheckboxEnabled = setAsDefaultCheckboxEnabled, - canChangeCbc = true, initialState = UpdatePaymentMethodInteractor.State( error = errorMessage, status = UpdatePaymentMethodInteractor.Status.Idle, From 760f71f4734f1d7b728d25434aa918a1bd257d39 Mon Sep 17 00:00:00 2001 From: Chengtin Tsai Date: Mon, 6 Jul 2026 15:21:12 -0700 Subject: [PATCH 7/7] Fix shouldShowCardBrandDropdown not passed to test fakes and simplify createEditCardDetailsInteractorForCard Co-Authored-By: Claude Opus 4.6 (1M context) Committed-By-Agent: claude --- .../paymentsheet/ui/UpdatePaymentMethodInteractor.kt | 11 +++-------- ...entSheetScreenUpdatePaymentMethodScreenshotTest.kt | 3 +++ .../paymentsheet/ui/UpdatePaymentMethodUITest.kt | 5 ++++- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodInteractor.kt b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodInteractor.kt index 38a8b2b76a8..e9afe885653 100644 --- a/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodInteractor.kt +++ b/paymentsheet/src/main/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodInteractor.kt @@ -187,17 +187,12 @@ internal class DefaultUpdatePaymentMethodInteractor( private fun createEditCardDetailsInteractorForCard( savedPaymentMethodCard: SavedPaymentMethod.Card, ): EditCardDetailsInteractor { - val isModifiable = displayableSavedPaymentMethod.paymentMethod.isModifiable( - canUpdateCardExpiryAndBillingDetails = canUpdateCardExpiryAndBillingDetails, - canChangeCbc = canChangeCbc, - ) val payload = EditCardPayload.create(savedPaymentMethodCard.card, savedPaymentMethodCard.billingDetails) val cardEditConfiguration = CardEditConfiguration( cardBrandFilter = cardBrandFilter, - isCbcModifiable = isModifiable && - canChangeCbc && - displayableSavedPaymentMethod.paymentMethod.hasMultipleNetworks(), - areExpiryDateAndAddressModificationSupported = isModifiable && canUpdateCardExpiryAndBillingDetails, + isCbcModifiable = shouldShowCardBrandDropdown, + areExpiryDateAndAddressModificationSupported = + isModifiablePaymentMethod && canUpdateCardExpiryAndBillingDetails, ) return editCardDetailsInteractorFactory.create( payload = payload, diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentSheetScreenUpdatePaymentMethodScreenshotTest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentSheetScreenUpdatePaymentMethodScreenshotTest.kt index 060dda75f82..7c0d90fdda0 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentSheetScreenUpdatePaymentMethodScreenshotTest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/PaymentSheetScreenUpdatePaymentMethodScreenshotTest.kt @@ -37,6 +37,7 @@ internal class PaymentSheetScreenUpdatePaymentMethodScreenshotTest { .toDisplayableSavedPaymentMethod(), canRemove = false, isModifiablePaymentMethod = true, + shouldShowCardBrandDropdown = true, ) } } @@ -204,6 +205,7 @@ internal class PaymentSheetScreenUpdatePaymentMethodScreenshotTest { isExpiredCard: Boolean = false, error: String? = null, shouldShowSetAsDefaultCheckbox: Boolean = false, + shouldShowCardBrandDropdown: Boolean = false, canUpdateCardExpiryAndBillingDetails: Boolean = false, addressCollectionMode: AddressCollectionMode = AddressCollectionMode.Never, useDefaultBillingDetails: Boolean = true, @@ -214,6 +216,7 @@ internal class PaymentSheetScreenUpdatePaymentMethodScreenshotTest { canRemove = canRemove, isExpiredCard = isExpiredCard, isModifiablePaymentMethod = isModifiablePaymentMethod, + shouldShowCardBrandDropdown = shouldShowCardBrandDropdown, shouldShowSetAsDefaultCheckbox = shouldShowSetAsDefaultCheckbox, setAsDefaultCheckboxEnabled = true, viewActionRecorder = null, diff --git a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUITest.kt b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUITest.kt index 29d9c106583..d5bddc8a754 100644 --- a/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUITest.kt +++ b/paymentsheet/src/test/java/com/stripe/android/paymentsheet/ui/UpdatePaymentMethodUITest.kt @@ -171,7 +171,8 @@ class UpdatePaymentMethodUITest { runScenario( displayableSavedPaymentMethod = PaymentMethodFixtures .CARD_WITH_NETWORKS_PAYMENT_METHOD - .toDisplayableSavedPaymentMethod() + .toDisplayableSavedPaymentMethod(), + shouldShowCardBrandDropdown = true, ) { composeRule.onNodeWithTag(UPDATE_PM_DETAILS_SUBTITLE_TEST_TAG).assertTextEquals( "Only card brand can be changed." @@ -318,6 +319,7 @@ class UpdatePaymentMethodUITest { canRemove: Boolean = true, isModifiablePaymentMethod: Boolean = true, hasValidBrandChoices: Boolean = true, + shouldShowCardBrandDropdown: Boolean = false, setAsDefaultCheckboxChecked: Boolean = false, setAsDefaultCheckboxEnabled: Boolean = true, cardBrandFilter: CardBrandFilter = DefaultCardBrandFilter, @@ -336,6 +338,7 @@ class UpdatePaymentMethodUITest { cardBrandFilter = cardBrandFilter, viewActionRecorder = viewActionRecorder, hasValidBrandChoices = hasValidBrandChoices, + shouldShowCardBrandDropdown = shouldShowCardBrandDropdown, shouldShowSetAsDefaultCheckbox = shouldShowSetAsDefaultCheckbox, shouldShowSaveButton = shouldShowSaveButton, setAsDefaultCheckboxEnabled = setAsDefaultCheckboxEnabled,