From 98a63902b0cda4fb310f643156697750fe164daf Mon Sep 17 00:00:00 2001 From: AnirudhBhat Date: Wed, 31 Jul 2024 08:08:57 +0530 Subject: [PATCH 01/13] Add logic to ignore Stripe account pending error for POS mode. Since we don't support any onboarding flow in POS, we skip this step automatically in the POS mode. In phone, merchant has to manually skip this step in the onboarding fragment. --- .../CardReaderStatusCheckerViewModel.kt | 91 +++++++++++++++++-- 1 file changed, 84 insertions(+), 7 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModel.kt index 936ef06809b..dceb10b5069 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModel.kt @@ -83,21 +83,98 @@ class CardReaderStatusCheckerViewModel when (val state = cardReaderChecker.getOnboardingState()) { is CardReaderOnboardingState.OnboardingCompleted -> { if (appPrefsWrapper.isCardReaderWelcomeDialogShown()) { - triggerEvent(NavigateToConnection(param, arguments.cardReaderType)) + triggerEvent( + NavigateToConnection( + param, + arguments.cardReaderType + ) + ) } else { - triggerEvent(StatusCheckerEvent.NavigateToWelcome(param, arguments.cardReaderType)) + triggerEvent( + StatusCheckerEvent.NavigateToWelcome( + param, + arguments.cardReaderType + ) + ) } } - else -> triggerEvent( - StatusCheckerEvent.NavigateToOnboarding( - CardReaderOnboardingParams.Failed(param, state), - arguments.cardReaderType - ) + else -> { + when (param) { + is CardReaderFlowParam.CardReadersHub, is CardReaderFlowParam.PaymentOrRefund.Refund -> { + navigateToOnboardingFailed(param, state, arguments.cardReaderType) + } + + is CardReaderFlowParam.PaymentOrRefund.Payment -> { + handlePaymentType(param, arguments.cardReaderType, state) + } + + CardReaderFlowParam.WooPosConnection -> { + if (state is CardReaderOnboardingState.StripeAccountPendingRequirement) { + navigateToConnection( + param, + arguments.cardReaderType + ) + } else { + navigateToOnboardingFailed( + param, + state, + arguments.cardReaderType + ) + } + } + } + } + } + } + + private fun navigateToOnboardingFailed( + param: CardReaderFlowParam, + state: CardReaderOnboardingState, + cardReaderType: CardReaderType + ) { + triggerEvent( + StatusCheckerEvent.NavigateToOnboarding( + CardReaderOnboardingParams.Failed( + param, + state + ), + cardReaderType + ) + ) + } + + private fun handlePaymentType( + param: CardReaderFlowParam.PaymentOrRefund.Payment, + cardReaderType: CardReaderType, + state: CardReaderOnboardingState, + ) { + if ( + param.paymentType == CardReaderFlowParam.PaymentOrRefund.Payment.PaymentType.WOO_POS && + state is CardReaderOnboardingState.StripeAccountPendingRequirement + ) { + navigateToConnection( + param, + cardReaderType + ) + } else { + navigateToOnboardingFailed( + param, + state, + cardReaderType ) } } + private fun navigateToConnection(param: CardReaderFlowParam, cardReaderType: CardReaderType) { + triggerEvent( + NavigateToConnection( + param, + cardReaderType + ) + ) + } + private fun CardReader.toCardReaderType() = if (ReaderType.isExternalReaderType(type)) { EXTERNAL From d976a5aceb33ed60bad57c0068854ce2a6aca0f2 Mon Sep 17 00:00:00 2001 From: AnirudhBhat Date: Wed, 31 Jul 2024 08:16:53 +0530 Subject: [PATCH 02/13] Add test to verify that when onboarding fails due to stripe account pending error while connecting reader in pos mode, we skit it and connect to reader --- .../CardReaderStatusCheckerViewModelTest.kt | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt index bca4610e06f..6414f44b4f6 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt @@ -6,6 +6,7 @@ import com.woocommerce.android.cardreader.connection.CardReader import com.woocommerce.android.cardreader.connection.CardReaderStatus import com.woocommerce.android.cardreader.connection.ReaderType import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderFlowParam +import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderFlowParam.PaymentOrRefund.Payment.PaymentType import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderFlowParam.PaymentOrRefund.Payment.PaymentType.ORDER import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderOnboardingChecker import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderOnboardingParams @@ -436,6 +437,37 @@ class CardReaderStatusCheckerViewModelTest : BaseUnitTest() { ) } + @Test + fun `given woo pos connection and onboarding failed with stripe pending requirements, when vm init, then navigates to connection`() = + testBlocking { + // GIVEN + val orderId = 1L + val param = CardReaderFlowParam.PaymentOrRefund.Payment( + orderId = orderId, + paymentType = PaymentType.WOO_POS + ) + whenever(cardReaderManager.readerStatus).thenReturn(MutableStateFlow(CardReaderStatus.NotConnected())) + val onboardingState = CardReaderOnboardingState.StripeAccountPendingRequirement( + dueDate = 0L, + preferredPlugin = PluginType.WOOCOMMERCE_PAYMENTS, + version = pluginVersion, + countryCode = countryCode + ) + whenever(cardReaderChecker.getOnboardingState()).thenReturn(onboardingState) + + // WHEN + val vm = initViewModel(param) + + // THEN + assertThat(vm.event.value) + .isEqualTo( + CardReaderStatusCheckerViewModel.StatusCheckerEvent.NavigateToConnection( + param, + CardReaderType.EXTERNAL + ) + ) + } + private fun initViewModel( param: CardReaderFlowParam, cardReaderType: CardReaderType = CardReaderType.EXTERNAL From 34bf43fcab2e2e70b4638308477d147f8ff18b46 Mon Sep 17 00:00:00 2001 From: AnirudhBhat Date: Wed, 31 Jul 2024 08:18:18 +0530 Subject: [PATCH 03/13] Add test to verify that when onboarding fails due to any other error than stripe account pending error while connecting reader in pos mode, we navigate to onboarding flow --- .../CardReaderStatusCheckerViewModelTest.kt | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt index 6414f44b4f6..ea198e904e8 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt @@ -8,6 +8,7 @@ import com.woocommerce.android.cardreader.connection.ReaderType import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderFlowParam import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderFlowParam.PaymentOrRefund.Payment.PaymentType import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderFlowParam.PaymentOrRefund.Payment.PaymentType.ORDER +import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderFlowParam.PaymentOrRefund.Payment.PaymentType.WOO_POS import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderOnboardingChecker import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderOnboardingParams import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderOnboardingState @@ -444,7 +445,7 @@ class CardReaderStatusCheckerViewModelTest : BaseUnitTest() { val orderId = 1L val param = CardReaderFlowParam.PaymentOrRefund.Payment( orderId = orderId, - paymentType = PaymentType.WOO_POS + paymentType = WOO_POS ) whenever(cardReaderManager.readerStatus).thenReturn(MutableStateFlow(CardReaderStatus.NotConnected())) val onboardingState = CardReaderOnboardingState.StripeAccountPendingRequirement( @@ -468,6 +469,26 @@ class CardReaderStatusCheckerViewModelTest : BaseUnitTest() { ) } + @Test + fun `given woo pos connection and onboarding failed with error other than stripe pending requirements, when vm init, then navigates to onboarding`() = + testBlocking { + // GIVEN + val orderId = 1L + val param = CardReaderFlowParam.PaymentOrRefund.Payment(orderId = orderId, paymentType = WOO_POS) + whenever(cardReaderManager.readerStatus).thenReturn(MutableStateFlow(CardReaderStatus.NotConnected())) + val onboardingState = CardReaderOnboardingState.StripeAccountRejected( + preferredPlugin = PluginType.WOOCOMMERCE_PAYMENTS, + ) + whenever(cardReaderChecker.getOnboardingState()).thenReturn(onboardingState) + + // WHEN + val vm = initViewModel(param) + + // THEN + assertThat(vm.event.value) + .isInstanceOf(CardReaderStatusCheckerViewModel.StatusCheckerEvent.NavigateToOnboarding::class.java) + } + private fun initViewModel( param: CardReaderFlowParam, cardReaderType: CardReaderType = CardReaderType.EXTERNAL From 0a86c6ce59218eaace240d2b7cab77e9037356a4 Mon Sep 17 00:00:00 2001 From: AnirudhBhat Date: Wed, 31 Jul 2024 08:19:35 +0530 Subject: [PATCH 04/13] Add test to verify that when onboarding fails due to stripe account pending error while taking payment in pos mode, we navigate to connection --- .../CardReaderStatusCheckerViewModelTest.kt | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt index ea198e904e8..9495a7191be 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt @@ -6,7 +6,6 @@ import com.woocommerce.android.cardreader.connection.CardReader import com.woocommerce.android.cardreader.connection.CardReaderStatus import com.woocommerce.android.cardreader.connection.ReaderType import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderFlowParam -import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderFlowParam.PaymentOrRefund.Payment.PaymentType import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderFlowParam.PaymentOrRefund.Payment.PaymentType.ORDER import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderFlowParam.PaymentOrRefund.Payment.PaymentType.WOO_POS import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderOnboardingChecker @@ -489,6 +488,29 @@ class CardReaderStatusCheckerViewModelTest : BaseUnitTest() { .isInstanceOf(CardReaderStatusCheckerViewModel.StatusCheckerEvent.NavigateToOnboarding::class.java) } + @Test + fun `given payment flow for woo pos and onboarding failed with stripe pending requirements, when vm init, then navigates to connection`() = + testBlocking { + // GIVEN + val orderId = 1L + val param = CardReaderFlowParam.PaymentOrRefund.Payment(orderId = orderId, paymentType = WOO_POS) + whenever(cardReaderManager.readerStatus).thenReturn(MutableStateFlow(CardReaderStatus.NotConnected())) + val onboardingState = CardReaderOnboardingState.StripeAccountPendingRequirement( + dueDate = 0L, + preferredPlugin = PluginType.WOOCOMMERCE_PAYMENTS, + version = pluginVersion, + countryCode = countryCode + ) + whenever(cardReaderChecker.getOnboardingState()).thenReturn(onboardingState) + + // WHEN + val vm = initViewModel(param) + + // THEN + assertThat(vm.event.value) + .isInstanceOf(CardReaderStatusCheckerViewModel.StatusCheckerEvent.NavigateToConnection::class.java) + } + private fun initViewModel( param: CardReaderFlowParam, cardReaderType: CardReaderType = CardReaderType.EXTERNAL From 84998ceffd40230114359adf3f28f8439c74af1c Mon Sep 17 00:00:00 2001 From: AnirudhBhat Date: Wed, 31 Jul 2024 08:20:12 +0530 Subject: [PATCH 05/13] Add test to verify that when onboarding fails due to any other error than stripe account pending error while taking payment in pos mode, we navigate to onboarding flow --- .../CardReaderStatusCheckerViewModelTest.kt | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt index 9495a7191be..5fca1572582 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt @@ -511,6 +511,26 @@ class CardReaderStatusCheckerViewModelTest : BaseUnitTest() { .isInstanceOf(CardReaderStatusCheckerViewModel.StatusCheckerEvent.NavigateToConnection::class.java) } + @Test + fun `given payment flow for woo pos and onboarding failed with error other than stripe pending requirements, when vm init, then navigates to onboarding`() = + testBlocking { + // GIVEN + val orderId = 1L + val param = CardReaderFlowParam.PaymentOrRefund.Payment(orderId = orderId, paymentType = WOO_POS) + whenever(cardReaderManager.readerStatus).thenReturn(MutableStateFlow(CardReaderStatus.NotConnected())) + val onboardingState = CardReaderOnboardingState.StripeAccountRejected( + preferredPlugin = PluginType.WOOCOMMERCE_PAYMENTS, + ) + whenever(cardReaderChecker.getOnboardingState()).thenReturn(onboardingState) + + // WHEN + val vm = initViewModel(param) + + // THEN + assertThat(vm.event.value) + .isInstanceOf(CardReaderStatusCheckerViewModel.StatusCheckerEvent.NavigateToOnboarding::class.java) + } + private fun initViewModel( param: CardReaderFlowParam, cardReaderType: CardReaderType = CardReaderType.EXTERNAL From b5bc6dc4145afc2a977a8fc26551bb165800ff94 Mon Sep 17 00:00:00 2001 From: AnirudhBhat Date: Wed, 31 Jul 2024 08:21:54 +0530 Subject: [PATCH 06/13] refactor - extract into method for readability --- .../CardReaderStatusCheckerViewModel.kt | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModel.kt index dceb10b5069..69ed58610bb 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModel.kt @@ -110,24 +110,31 @@ class CardReaderStatusCheckerViewModel } CardReaderFlowParam.WooPosConnection -> { - if (state is CardReaderOnboardingState.StripeAccountPendingRequirement) { - navigateToConnection( - param, - arguments.cardReaderType - ) - } else { - navigateToOnboardingFailed( - param, - state, - arguments.cardReaderType - ) - } + handleCardReaderConnection(state, param) } } } } } + private fun handleCardReaderConnection( + state: CardReaderOnboardingState, + param: CardReaderFlowParam + ) { + if (state is CardReaderOnboardingState.StripeAccountPendingRequirement) { + navigateToConnection( + param, + arguments.cardReaderType + ) + } else { + navigateToOnboardingFailed( + param, + state, + arguments.cardReaderType + ) + } + } + private fun navigateToOnboardingFailed( param: CardReaderFlowParam, state: CardReaderOnboardingState, From 650ca40ec1853a577a4047cfbc9e3caaf3601c0a Mon Sep 17 00:00:00 2001 From: AnirudhBhat Date: Wed, 31 Jul 2024 08:49:23 +0530 Subject: [PATCH 07/13] refactor - extract into method for readability --- .../CardReaderStatusCheckerViewModel.kt | 64 +++++++++++-------- 1 file changed, 37 insertions(+), 27 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModel.kt index 69ed58610bb..3aefccfc99c 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModel.kt @@ -82,37 +82,47 @@ class CardReaderStatusCheckerViewModel private suspend fun handleOnboardingStatus(param: CardReaderFlowParam) { when (val state = cardReaderChecker.getOnboardingState()) { is CardReaderOnboardingState.OnboardingCompleted -> { - if (appPrefsWrapper.isCardReaderWelcomeDialogShown()) { - triggerEvent( - NavigateToConnection( - param, - arguments.cardReaderType - ) - ) - } else { - triggerEvent( - StatusCheckerEvent.NavigateToWelcome( - param, - arguments.cardReaderType - ) - ) - } + handleOnboardingCompletedState(param) } - else -> { - when (param) { - is CardReaderFlowParam.CardReadersHub, is CardReaderFlowParam.PaymentOrRefund.Refund -> { - navigateToOnboardingFailed(param, state, arguments.cardReaderType) - } + handleOnboardingNotCompletedState(param, state) + } + } + } - is CardReaderFlowParam.PaymentOrRefund.Payment -> { - handlePaymentType(param, arguments.cardReaderType, state) - } + private fun handleOnboardingCompletedState(param: CardReaderFlowParam) { + if (appPrefsWrapper.isCardReaderWelcomeDialogShown()) { + triggerEvent( + NavigateToConnection( + param, + arguments.cardReaderType + ) + ) + } else { + triggerEvent( + StatusCheckerEvent.NavigateToWelcome( + param, + arguments.cardReaderType + ) + ) + } + } - CardReaderFlowParam.WooPosConnection -> { - handleCardReaderConnection(state, param) - } - } + private fun handleOnboardingNotCompletedState( + param: CardReaderFlowParam, + state: CardReaderOnboardingState + ) { + when (param) { + is CardReaderFlowParam.CardReadersHub, is CardReaderFlowParam.PaymentOrRefund.Refund -> { + navigateToOnboardingFailed(param, state, arguments.cardReaderType) + } + + is CardReaderFlowParam.PaymentOrRefund.Payment -> { + handlePaymentType(param, arguments.cardReaderType, state) + } + + CardReaderFlowParam.WooPosConnection -> { + handleCardReaderConnection(state, param) } } } From 935a97f59b48a5f371572ad7192883183a507e04 Mon Sep 17 00:00:00 2001 From: AnirudhBhat Date: Wed, 31 Jul 2024 09:32:36 +0530 Subject: [PATCH 08/13] Make changes to test conditions to ensure correct pre-conditions are used. --- .../CardReaderStatusCheckerViewModelTest.kt | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt index 5fca1572582..50c21bf3e47 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt @@ -441,12 +441,7 @@ class CardReaderStatusCheckerViewModelTest : BaseUnitTest() { fun `given woo pos connection and onboarding failed with stripe pending requirements, when vm init, then navigates to connection`() = testBlocking { // GIVEN - val orderId = 1L - val param = CardReaderFlowParam.PaymentOrRefund.Payment( - orderId = orderId, - paymentType = WOO_POS - ) - whenever(cardReaderManager.readerStatus).thenReturn(MutableStateFlow(CardReaderStatus.NotConnected())) + val param = CardReaderFlowParam.WooPosConnection val onboardingState = CardReaderOnboardingState.StripeAccountPendingRequirement( dueDate = 0L, preferredPlugin = PluginType.WOOCOMMERCE_PAYMENTS, @@ -472,9 +467,7 @@ class CardReaderStatusCheckerViewModelTest : BaseUnitTest() { fun `given woo pos connection and onboarding failed with error other than stripe pending requirements, when vm init, then navigates to onboarding`() = testBlocking { // GIVEN - val orderId = 1L - val param = CardReaderFlowParam.PaymentOrRefund.Payment(orderId = orderId, paymentType = WOO_POS) - whenever(cardReaderManager.readerStatus).thenReturn(MutableStateFlow(CardReaderStatus.NotConnected())) + val param = CardReaderFlowParam.WooPosConnection val onboardingState = CardReaderOnboardingState.StripeAccountRejected( preferredPlugin = PluginType.WOOCOMMERCE_PAYMENTS, ) From c6e8c11f19cac19da1da8d64c9a5fb6e77e04ff0 Mon Sep 17 00:00:00 2001 From: AnirudhBhat Date: Wed, 31 Jul 2024 09:40:26 +0530 Subject: [PATCH 09/13] Add missing test for existing refund flow --- .../CardReaderStatusCheckerViewModelTest.kt | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt index 50c21bf3e47..05b72c68411 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt @@ -22,6 +22,7 @@ import org.junit.Test import org.mockito.kotlin.mock import org.mockito.kotlin.verify import org.mockito.kotlin.whenever +import java.math.BigDecimal @ExperimentalCoroutinesApi class CardReaderStatusCheckerViewModelTest : BaseUnitTest() { @@ -524,6 +525,34 @@ class CardReaderStatusCheckerViewModelTest : BaseUnitTest() { .isInstanceOf(CardReaderStatusCheckerViewModel.StatusCheckerEvent.NavigateToOnboarding::class.java) } + @Test + fun `given refund flow and not connected and error, when vm init, then navigates to onboarding with fail`() = + testBlocking { + // GIVEN + val orderId = 1L + val param = CardReaderFlowParam.PaymentOrRefund.Refund(orderId = orderId, BigDecimal.TEN) + whenever(cardReaderManager.readerStatus).thenReturn(MutableStateFlow(CardReaderStatus.NotConnected())) + val onboardingError = CardReaderOnboardingState.StripeAccountPendingRequirement( + dueDate = 0L, + preferredPlugin = PluginType.WOOCOMMERCE_PAYMENTS, + version = pluginVersion, + countryCode = countryCode + ) + whenever(cardReaderChecker.getOnboardingState()).thenReturn(onboardingError) + + // WHEN + val vm = initViewModel(param) + + // THEN + assertThat(vm.event.value) + .isEqualTo( + CardReaderStatusCheckerViewModel.StatusCheckerEvent.NavigateToOnboarding( + CardReaderOnboardingParams.Failed(param, onboardingError), + CardReaderType.EXTERNAL + ) + ) + } + private fun initViewModel( param: CardReaderFlowParam, cardReaderType: CardReaderType = CardReaderType.EXTERNAL From 1c9985c96a3f55b6bd9ea4fa543bc9106dc15250 Mon Sep 17 00:00:00 2001 From: AnirudhBhat Date: Wed, 31 Jul 2024 09:42:38 +0530 Subject: [PATCH 10/13] Add missing test for existing card reader hub flow --- .../CardReaderStatusCheckerViewModelTest.kt | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt index 05b72c68411..16b38b56476 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt @@ -553,6 +553,30 @@ class CardReaderStatusCheckerViewModelTest : BaseUnitTest() { ) } + @Test + fun `given card reader hub flow and not connected and error, when vm init, then navigates to onboarding with fail`() = + testBlocking { + // GIVEN + val param = CardReaderFlowParam.CardReadersHub() + whenever(cardReaderManager.readerStatus).thenReturn(MutableStateFlow(CardReaderStatus.NotConnected())) + val onboardingError = CardReaderOnboardingState.StripeAccountPendingRequirement( + dueDate = 0L, + preferredPlugin = PluginType.WOOCOMMERCE_PAYMENTS, + version = pluginVersion, + countryCode = countryCode + ) + whenever(cardReaderChecker.getOnboardingState()).thenReturn(onboardingError) + + // WHEN + val vm = initViewModel(param) + + // THEN + assertThat(vm.event.value) + .isInstanceOf( + CardReaderStatusCheckerViewModel.StatusCheckerEvent.NavigateToOnboarding::class.java + ) + } + private fun initViewModel( param: CardReaderFlowParam, cardReaderType: CardReaderType = CardReaderType.EXTERNAL From 07030c23938cb9f4913f4c51eec9ce5e0cd22a05 Mon Sep 17 00:00:00 2001 From: AnirudhBhat Date: Wed, 31 Jul 2024 09:46:43 +0530 Subject: [PATCH 11/13] Add missing test for existing card reader payment flow during simple payment --- .../CardReaderStatusCheckerViewModelTest.kt | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt index 16b38b56476..299767908d5 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt @@ -7,6 +7,7 @@ import com.woocommerce.android.cardreader.connection.CardReaderStatus import com.woocommerce.android.cardreader.connection.ReaderType import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderFlowParam import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderFlowParam.PaymentOrRefund.Payment.PaymentType.ORDER +import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderFlowParam.PaymentOrRefund.Payment.PaymentType.SIMPLE import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderFlowParam.PaymentOrRefund.Payment.PaymentType.WOO_POS import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderOnboardingChecker import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderOnboardingParams @@ -577,6 +578,31 @@ class CardReaderStatusCheckerViewModelTest : BaseUnitTest() { ) } + @Test + fun `given payment flow during IPP and not connected and error, when vm init, then navigates to onboarding with fail`() = + testBlocking { + // GIVEN + val orderId = 1L + val param = CardReaderFlowParam.PaymentOrRefund.Payment(orderId = orderId, paymentType = SIMPLE) + whenever(cardReaderManager.readerStatus).thenReturn(MutableStateFlow(CardReaderStatus.NotConnected())) + val onboardingError = CardReaderOnboardingState.StripeAccountPendingRequirement( + dueDate = 0L, + preferredPlugin = PluginType.WOOCOMMERCE_PAYMENTS, + version = pluginVersion, + countryCode = countryCode + ) + whenever(cardReaderChecker.getOnboardingState()).thenReturn(onboardingError) + + // WHEN + val vm = initViewModel(param) + + // THEN + assertThat(vm.event.value) + .isInstanceOf( + CardReaderStatusCheckerViewModel.StatusCheckerEvent.NavigateToOnboarding::class.java + ) + } + private fun initViewModel( param: CardReaderFlowParam, cardReaderType: CardReaderType = CardReaderType.EXTERNAL From a615ccbd58dc3963c89cd8f71060c88420f7bf88 Mon Sep 17 00:00:00 2001 From: AnirudhBhat Date: Wed, 31 Jul 2024 13:07:00 +0530 Subject: [PATCH 12/13] Remove unnecessary mock --- .../statuschecker/CardReaderStatusCheckerViewModelTest.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt index 299767908d5..8e20f5c80cc 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt @@ -559,7 +559,6 @@ class CardReaderStatusCheckerViewModelTest : BaseUnitTest() { testBlocking { // GIVEN val param = CardReaderFlowParam.CardReadersHub() - whenever(cardReaderManager.readerStatus).thenReturn(MutableStateFlow(CardReaderStatus.NotConnected())) val onboardingError = CardReaderOnboardingState.StripeAccountPendingRequirement( dueDate = 0L, preferredPlugin = PluginType.WOOCOMMERCE_PAYMENTS, From faa6679f7b988194749aebd29bee2433fbd67beb Mon Sep 17 00:00:00 2001 From: AnirudhBhat Date: Thu, 1 Aug 2024 07:59:07 +0530 Subject: [PATCH 13/13] Change of plan We have decided to not show the POS entry point when there are Stripe pending errors. This is being done so that we touch existing IPP code as minimal as possible --- .../CardReaderStatusCheckerViewModel.kt | 110 ++---------------- .../android/ui/woopos/WooPosIsEnabled.kt | 2 +- .../CardReaderStatusCheckerViewModelTest.kt | 98 +--------------- .../android/ui/woopos/WooPosIsEnabledTest.kt | 4 +- 4 files changed, 12 insertions(+), 202 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModel.kt index 3aefccfc99c..936ef06809b 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModel.kt @@ -82,116 +82,22 @@ class CardReaderStatusCheckerViewModel private suspend fun handleOnboardingStatus(param: CardReaderFlowParam) { when (val state = cardReaderChecker.getOnboardingState()) { is CardReaderOnboardingState.OnboardingCompleted -> { - handleOnboardingCompletedState(param) - } - else -> { - handleOnboardingNotCompletedState(param, state) + if (appPrefsWrapper.isCardReaderWelcomeDialogShown()) { + triggerEvent(NavigateToConnection(param, arguments.cardReaderType)) + } else { + triggerEvent(StatusCheckerEvent.NavigateToWelcome(param, arguments.cardReaderType)) + } } - } - } - private fun handleOnboardingCompletedState(param: CardReaderFlowParam) { - if (appPrefsWrapper.isCardReaderWelcomeDialogShown()) { - triggerEvent( - NavigateToConnection( - param, - arguments.cardReaderType - ) - ) - } else { - triggerEvent( - StatusCheckerEvent.NavigateToWelcome( - param, + else -> triggerEvent( + StatusCheckerEvent.NavigateToOnboarding( + CardReaderOnboardingParams.Failed(param, state), arguments.cardReaderType ) ) } } - private fun handleOnboardingNotCompletedState( - param: CardReaderFlowParam, - state: CardReaderOnboardingState - ) { - when (param) { - is CardReaderFlowParam.CardReadersHub, is CardReaderFlowParam.PaymentOrRefund.Refund -> { - navigateToOnboardingFailed(param, state, arguments.cardReaderType) - } - - is CardReaderFlowParam.PaymentOrRefund.Payment -> { - handlePaymentType(param, arguments.cardReaderType, state) - } - - CardReaderFlowParam.WooPosConnection -> { - handleCardReaderConnection(state, param) - } - } - } - - private fun handleCardReaderConnection( - state: CardReaderOnboardingState, - param: CardReaderFlowParam - ) { - if (state is CardReaderOnboardingState.StripeAccountPendingRequirement) { - navigateToConnection( - param, - arguments.cardReaderType - ) - } else { - navigateToOnboardingFailed( - param, - state, - arguments.cardReaderType - ) - } - } - - private fun navigateToOnboardingFailed( - param: CardReaderFlowParam, - state: CardReaderOnboardingState, - cardReaderType: CardReaderType - ) { - triggerEvent( - StatusCheckerEvent.NavigateToOnboarding( - CardReaderOnboardingParams.Failed( - param, - state - ), - cardReaderType - ) - ) - } - - private fun handlePaymentType( - param: CardReaderFlowParam.PaymentOrRefund.Payment, - cardReaderType: CardReaderType, - state: CardReaderOnboardingState, - ) { - if ( - param.paymentType == CardReaderFlowParam.PaymentOrRefund.Payment.PaymentType.WOO_POS && - state is CardReaderOnboardingState.StripeAccountPendingRequirement - ) { - navigateToConnection( - param, - cardReaderType - ) - } else { - navigateToOnboardingFailed( - param, - state, - cardReaderType - ) - } - } - - private fun navigateToConnection(param: CardReaderFlowParam, cardReaderType: CardReaderType) { - triggerEvent( - NavigateToConnection( - param, - cardReaderType - ) - ) - } - private fun CardReader.toCardReaderType() = if (ReaderType.isExternalReaderType(type)) { EXTERNAL diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/WooPosIsEnabled.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/WooPosIsEnabled.kt index ec4901756b4..4f5bb0ee216 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/WooPosIsEnabled.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/WooPosIsEnabled.kt @@ -73,10 +73,10 @@ class WooPosIsEnabled @Inject constructor( is CardReaderOnboardingState.StripeAccountOverdueRequirement, is CardReaderOnboardingState.StripeAccountRejected, is CardReaderOnboardingState.StripeAccountUnderReview, + is CardReaderOnboardingState.StripeAccountPendingRequirement, CardReaderOnboardingState.WcpayNotActivated, CardReaderOnboardingState.WcpayNotInstalled -> false - is CardReaderOnboardingState.StripeAccountPendingRequirement, is CardReaderOnboardingState.OnboardingCompleted -> true } diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt index 8e20f5c80cc..72395e022e2 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/statuschecker/CardReaderStatusCheckerViewModelTest.kt @@ -7,8 +7,6 @@ import com.woocommerce.android.cardreader.connection.CardReaderStatus import com.woocommerce.android.cardreader.connection.ReaderType import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderFlowParam import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderFlowParam.PaymentOrRefund.Payment.PaymentType.ORDER -import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderFlowParam.PaymentOrRefund.Payment.PaymentType.SIMPLE -import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderFlowParam.PaymentOrRefund.Payment.PaymentType.WOO_POS import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderOnboardingChecker import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderOnboardingParams import com.woocommerce.android.ui.payments.cardreader.onboarding.CardReaderOnboardingState @@ -440,79 +438,10 @@ class CardReaderStatusCheckerViewModelTest : BaseUnitTest() { } @Test - fun `given woo pos connection and onboarding failed with stripe pending requirements, when vm init, then navigates to connection`() = + fun `given woo pos connection and onboarding failed with error, when vm init, then navigates to onboarding`() = testBlocking { // GIVEN val param = CardReaderFlowParam.WooPosConnection - val onboardingState = CardReaderOnboardingState.StripeAccountPendingRequirement( - dueDate = 0L, - preferredPlugin = PluginType.WOOCOMMERCE_PAYMENTS, - version = pluginVersion, - countryCode = countryCode - ) - whenever(cardReaderChecker.getOnboardingState()).thenReturn(onboardingState) - - // WHEN - val vm = initViewModel(param) - - // THEN - assertThat(vm.event.value) - .isEqualTo( - CardReaderStatusCheckerViewModel.StatusCheckerEvent.NavigateToConnection( - param, - CardReaderType.EXTERNAL - ) - ) - } - - @Test - fun `given woo pos connection and onboarding failed with error other than stripe pending requirements, when vm init, then navigates to onboarding`() = - testBlocking { - // GIVEN - val param = CardReaderFlowParam.WooPosConnection - val onboardingState = CardReaderOnboardingState.StripeAccountRejected( - preferredPlugin = PluginType.WOOCOMMERCE_PAYMENTS, - ) - whenever(cardReaderChecker.getOnboardingState()).thenReturn(onboardingState) - - // WHEN - val vm = initViewModel(param) - - // THEN - assertThat(vm.event.value) - .isInstanceOf(CardReaderStatusCheckerViewModel.StatusCheckerEvent.NavigateToOnboarding::class.java) - } - - @Test - fun `given payment flow for woo pos and onboarding failed with stripe pending requirements, when vm init, then navigates to connection`() = - testBlocking { - // GIVEN - val orderId = 1L - val param = CardReaderFlowParam.PaymentOrRefund.Payment(orderId = orderId, paymentType = WOO_POS) - whenever(cardReaderManager.readerStatus).thenReturn(MutableStateFlow(CardReaderStatus.NotConnected())) - val onboardingState = CardReaderOnboardingState.StripeAccountPendingRequirement( - dueDate = 0L, - preferredPlugin = PluginType.WOOCOMMERCE_PAYMENTS, - version = pluginVersion, - countryCode = countryCode - ) - whenever(cardReaderChecker.getOnboardingState()).thenReturn(onboardingState) - - // WHEN - val vm = initViewModel(param) - - // THEN - assertThat(vm.event.value) - .isInstanceOf(CardReaderStatusCheckerViewModel.StatusCheckerEvent.NavigateToConnection::class.java) - } - - @Test - fun `given payment flow for woo pos and onboarding failed with error other than stripe pending requirements, when vm init, then navigates to onboarding`() = - testBlocking { - // GIVEN - val orderId = 1L - val param = CardReaderFlowParam.PaymentOrRefund.Payment(orderId = orderId, paymentType = WOO_POS) - whenever(cardReaderManager.readerStatus).thenReturn(MutableStateFlow(CardReaderStatus.NotConnected())) val onboardingState = CardReaderOnboardingState.StripeAccountRejected( preferredPlugin = PluginType.WOOCOMMERCE_PAYMENTS, ) @@ -577,31 +506,6 @@ class CardReaderStatusCheckerViewModelTest : BaseUnitTest() { ) } - @Test - fun `given payment flow during IPP and not connected and error, when vm init, then navigates to onboarding with fail`() = - testBlocking { - // GIVEN - val orderId = 1L - val param = CardReaderFlowParam.PaymentOrRefund.Payment(orderId = orderId, paymentType = SIMPLE) - whenever(cardReaderManager.readerStatus).thenReturn(MutableStateFlow(CardReaderStatus.NotConnected())) - val onboardingError = CardReaderOnboardingState.StripeAccountPendingRequirement( - dueDate = 0L, - preferredPlugin = PluginType.WOOCOMMERCE_PAYMENTS, - version = pluginVersion, - countryCode = countryCode - ) - whenever(cardReaderChecker.getOnboardingState()).thenReturn(onboardingError) - - // WHEN - val vm = initViewModel(param) - - // THEN - assertThat(vm.event.value) - .isInstanceOf( - CardReaderStatusCheckerViewModel.StatusCheckerEvent.NavigateToOnboarding::class.java - ) - } - private fun initViewModel( param: CardReaderFlowParam, cardReaderType: CardReaderType = CardReaderType.EXTERNAL diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/WooPosIsEnabledTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/WooPosIsEnabledTest.kt index f9374ba5681..39260ccef3d 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/WooPosIsEnabledTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/WooPosIsEnabledTest.kt @@ -102,12 +102,12 @@ class WooPosIsEnabledTest : BaseUnitTest() { } @Test - fun `given ipp onboarding is Pending Requirements, then return true`() = testBlocking { + fun `given ipp onboarding is Pending Requirements, then return false`() = testBlocking { val onboardingCompleted = mock() whenever(onboardingCompleted.preferredPlugin).thenReturn(PluginType.WOOCOMMERCE_PAYMENTS) whenever(cardReaderOnboardingChecker.getOnboardingState()).thenReturn(onboardingCompleted) - assertTrue(sut()) + assertFalse(sut()) } @Test