Skip to content

Commit

Permalink
Add VM tests
Browse files Browse the repository at this point in the history
  • Loading branch information
toluo-stripe committed Jan 15, 2025
1 parent d94e52e commit 9d384b8
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ internal class LinkActivity : ComponentActivity() {
}
}


EventReporterProvider(
eventReporter = vm.eventReporter
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,19 @@ package com.stripe.android.link.ui.paymentmenthod
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import com.stripe.android.core.strings.resolvableString
import com.stripe.android.link.ui.ErrorText
import com.stripe.android.link.ui.PrimaryButton
import com.stripe.android.link.ui.ScrollableTopLevelColumn
import com.stripe.android.paymentsheet.ui.ErrorMessage
import com.stripe.android.paymentsheet.R
import com.stripe.android.paymentsheet.ui.PaymentMethodForm
import com.stripe.android.uicore.utils.collectAsState
import java.util.UUID
Expand All @@ -25,6 +29,12 @@ internal fun PaymentMethodScreen(
val uuid = rememberSaveable { UUID.randomUUID().toString() }

ScrollableTopLevelColumn {
Text(
modifier = Modifier
.padding(bottom = 32.dp),
text = R.string.stripe_add_payment_method.resolvableString.resolve(context),
style = MaterialTheme.typography.h2
)
PaymentMethodForm(
uuid = uuid,
args = state.formArguments,
Expand All @@ -38,11 +48,11 @@ internal fun PaymentMethodScreen(
AnimatedVisibility(
visible = state.errorMessage != null
) {
ErrorMessage(
ErrorText(
modifier = Modifier
.fillMaxWidth()
.padding(top = 16.dp),
error = state.errorMessage?.resolve(context).orEmpty()
text = state.errorMessage?.resolve(context).orEmpty()
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import com.stripe.android.link.account.FakeLinkAccountManager
import com.stripe.android.link.account.LinkAccountManager
import com.stripe.android.link.model.AccountStatus
import com.stripe.android.paymentelement.confirmation.FakeConfirmationHandler
import com.stripe.android.paymentsheet.analytics.FakeEventReporter
import com.stripe.android.testing.CoroutineTestRule
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.advanceUntilIdle
Expand Down Expand Up @@ -318,7 +319,8 @@ internal class LinkActivityViewModelTest {
return LinkActivityViewModel(
linkAccountManager = linkAccountManager,
activityRetainedComponent = mock(),
confirmationHandlerFactory = { FakeConfirmationHandler() }
confirmationHandlerFactory = { FakeConfirmationHandler() },
eventReporter = FakeEventReporter()
).apply {
this.navController = navController
this.dismissWithResult = dismissWithResult
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package com.stripe.android.link.ui.paymentmethod

import com.google.common.truth.Truth.assertThat
import com.stripe.android.core.strings.resolvableString
import com.stripe.android.link.LinkActivityResult
import com.stripe.android.link.TestFactory
import com.stripe.android.link.confirmation.FakeLinkConfirmationHandler
import com.stripe.android.link.confirmation.LinkConfirmationHandler
import com.stripe.android.link.ui.PrimaryButtonState
import com.stripe.android.link.ui.completePaymentButtonLabel
import com.stripe.android.link.ui.paymentmenthod.PaymentMethodState
Expand All @@ -25,6 +29,7 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import com.stripe.android.link.confirmation.Result as LinkConfirmationResult

@RunWith(RobolectricTestRunner::class)
class PaymentMethodViewModelTest {
Expand Down Expand Up @@ -86,11 +91,87 @@ class PaymentMethodViewModelTest {
assertThat(formHelper.onFormFieldValuesChangedCalls.last().formValues).isNull()
}

@Test
fun `onPayClicked confirms payment successfully`() = runTest {
val linkConfirmationHandler = FakeLinkConfirmationHandler()
var result: LinkActivityResult? = null
val viewModel = createViewModel(
linkConfirmationHandler = linkConfirmationHandler,
dismissWithResult = { result = it }
)

// Simulate form completion
viewModel.formValuesChanged(FormFieldValues(userRequestedReuse = PaymentSelection.CustomerRequestedSave.NoRequest))

viewModel.onPayClicked()

assertThat(linkConfirmationHandler.calls).containsExactly(
FakeLinkConfirmationHandler.Call.WithPaymentSelection(
paymentSelection = PaymentMethodFixtures.CARD_PAYMENT_SELECTION,
linkAccount = TestFactory.LINK_ACCOUNT
)
)

assertThat(result).isEqualTo(LinkActivityResult.Completed)
assertThat(viewModel.state.value.primaryButtonState).isEqualTo(PrimaryButtonState.Processing)
}

@Test
fun `onPayClicked handles confirmation failure`() = runTest {
val linkConfirmationHandler = FakeLinkConfirmationHandler()

linkConfirmationHandler.confirmResult = LinkConfirmationResult.Failed("Payment failed".resolvableString)

val viewModel = createViewModel(linkConfirmationHandler = linkConfirmationHandler)

// Simulate form completion
viewModel.formValuesChanged(FormFieldValues(userRequestedReuse = PaymentSelection.CustomerRequestedSave.NoRequest))

viewModel.onPayClicked()

assertThat(linkConfirmationHandler.calls).hasSize(1)
assertThat(viewModel.state.value.primaryButtonState).isEqualTo(PrimaryButtonState.Enabled)
assertThat(viewModel.state.value.errorMessage).isEqualTo("Payment failed".resolvableString)
}

@Test
fun `onPayClicked handles cancellation`() = runTest {
val linkConfirmationHandler = FakeLinkConfirmationHandler()
linkConfirmationHandler.confirmResult = LinkConfirmationResult.Canceled

val viewModel = createViewModel(linkConfirmationHandler = linkConfirmationHandler)

// Simulate form completion
viewModel.formValuesChanged(FormFieldValues(userRequestedReuse = PaymentSelection.CustomerRequestedSave.NoRequest))

viewModel.onPayClicked()

assertThat(linkConfirmationHandler.calls).hasSize(1)
assertThat(viewModel.state.value.primaryButtonState).isEqualTo(PrimaryButtonState.Enabled)
assertThat(viewModel.state.value.errorMessage).isNull()
}

@Test
fun `onPayClicked does nothing when payment selection is null`() = runTest {
val linkConfirmationHandler = FakeLinkConfirmationHandler()
val viewModel = createViewModel(linkConfirmationHandler = linkConfirmationHandler)

viewModel.onPayClicked()

assertThat(linkConfirmationHandler.calls).isEmpty()
assertThat(viewModel.state.value.primaryButtonState).isEqualTo(PrimaryButtonState.Disabled)
}

private fun createViewModel(
formHelper: PaymentMethodFormHelper = PaymentMethodFormHelper(),
linkConfirmationHandler: LinkConfirmationHandler = FakeLinkConfirmationHandler(),
dismissWithResult: (LinkActivityResult) -> Unit = {}
): PaymentMethodViewModel {
return PaymentMethodViewModel(
configuration = TestFactory.LINK_CONFIGURATION,
linkAccount = TestFactory.LINK_ACCOUNT,
linkConfirmationHandler = linkConfirmationHandler,
dismissWithResult = dismissWithResult,
formHelperFactory = { updateSelection ->
formHelper.updateSelection = updateSelection
formHelper
Expand Down

0 comments on commit 9d384b8

Please sign in to comment.