diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/analytics/AnalyticsEvent.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/analytics/AnalyticsEvent.kt index ef6fc5fa382..2527475680e 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/analytics/AnalyticsEvent.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/analytics/AnalyticsEvent.kt @@ -456,6 +456,7 @@ enum class AnalyticsEvent(val siteless: Boolean = false) { RECEIPT_PRINT_CANCELED, RECEIPT_PRINT_SUCCESS, RECEIPT_VIEW_TAPPED, + RECEIPT_URL_FETCHING_FAILS, // -- Top-level navigation MAIN_MENU_SETTINGS_TAPPED, diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/OrderDetailTracker.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/OrderDetailTracker.kt index b86ef2b5a92..195b3b88586 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/OrderDetailTracker.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/OrderDetailTracker.kt @@ -4,11 +4,13 @@ import com.woocommerce.android.analytics.AnalyticsEvent import com.woocommerce.android.analytics.AnalyticsTracker import com.woocommerce.android.analytics.AnalyticsTrackerWrapper import com.woocommerce.android.model.Order +import com.woocommerce.android.ui.payments.tracking.PaymentsFlowTracker import org.wordpress.android.fluxc.store.WCOrderStore import javax.inject.Inject class OrderDetailTracker @Inject constructor( - private val trackerWrapper: AnalyticsTrackerWrapper + private val trackerWrapper: AnalyticsTrackerWrapper, + private val paymentsFlowTracker: PaymentsFlowTracker, ) { fun trackCustomFieldsTapped() { trackerWrapper.track(AnalyticsEvent.ORDER_VIEW_CUSTOM_FIELDS_TAPPED) @@ -24,9 +26,8 @@ class OrderDetailTracker @Inject constructor( ) } - fun trackReceiptViewTapped(orderId: Long, orderStatus: Order.Status) { - trackerWrapper.track( - AnalyticsEvent.RECEIPT_VIEW_TAPPED, + suspend fun trackReceiptViewTapped(orderId: Long, orderStatus: Order.Status) { + paymentsFlowTracker.trackReceiptViewTapped( mapOf( AnalyticsTracker.KEY_ORDER_ID to orderId, AnalyticsTracker.KEY_STATUS to orderStatus diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/OrderDetailViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/OrderDetailViewModel.kt index 8902a5da997..412095ef048 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/OrderDetailViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/details/OrderDetailViewModel.kt @@ -369,6 +369,9 @@ class OrderDetailViewModel @Inject constructor( if (receiptResult.isSuccess) { triggerEvent(PreviewReceipt(order.billingAddress.email, receiptResult.getOrThrow(), order.id)) } else { + paymentsFlowTracker.trackReceiptUrlFetchingFails( + errorDescription = receiptResult.exceptionOrNull()?.message ?: "Unknown error", + ) triggerEvent(ShowSnackbar(string.receipt_fetching_error)) } } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewModel.kt index de62a7ab603..72b5e18b46a 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/cardreader/payment/CardReaderPaymentViewModel.kt @@ -718,6 +718,9 @@ class CardReaderPaymentViewModel ) ) } else { + tracker.trackReceiptUrlFetchingFails( + errorDescription = receiptResult.exceptionOrNull()?.message ?: "Unknown error", + ) triggerEvent(ShowSnackbar(R.string.receipt_fetching_error)) } } @@ -749,6 +752,9 @@ class CardReaderPaymentViewModel } } } else { + tracker.trackReceiptUrlFetchingFails( + errorDescription = receiptResult.exceptionOrNull()?.message ?: "Unknown error", + ) triggerEvent(ShowSnackbar(R.string.receipt_fetching_error)) } @@ -756,18 +762,15 @@ class CardReaderPaymentViewModel } } - fun onEmailActivityNotFound() { - tracker.trackEmailReceiptFailed() - triggerEvent(ShowSnackbarInDialog(R.string.card_reader_payment_email_client_not_found)) - } - fun onPrintResult(result: PrintJobResult) { showPaymentSuccessfulState() - when (result) { - CANCELLED -> tracker.trackPrintReceiptCancelled() - FAILED -> tracker.trackPrintReceiptFailed() - STARTED -> tracker.trackPrintReceiptSucceeded() + launch { + when (result) { + CANCELLED -> tracker.trackPrintReceiptCancelled() + FAILED -> tracker.trackPrintReceiptFailed() + STARTED -> tracker.trackPrintReceiptSucceeded() + } } } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptHelper.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptHelper.kt index 8832e65cfeb..daf1bbffaee 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptHelper.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/PaymentReceiptHelper.kt @@ -77,7 +77,7 @@ class PaymentReceiptHelper @Inject constructor( } } - private suspend fun isWCCanGenerateReceipts(): Boolean { + suspend fun isWCCanGenerateReceipts(): Boolean { val currentWooCoreVersion = getWoocommerceCorePluginVersion() return currentWooCoreVersion.semverCompareTo(WC_CAN_GENERATE_RECEIPTS_VERSION) >= 0 diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewViewModel.kt index b74846b8e71..54cf312c698 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewViewModel.kt @@ -4,12 +4,6 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.SavedStateHandle import com.woocommerce.android.R.string -import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_EMAIL_TAPPED -import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_CANCELED -import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_FAILED -import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_SUCCESS -import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_TAPPED -import com.woocommerce.android.analytics.AnalyticsTrackerWrapper import com.woocommerce.android.ui.payments.receipt.PaymentReceiptShare import com.woocommerce.android.ui.payments.receipt.preview.ReceiptPreviewViewModel.ReceiptPreviewViewState.Content import com.woocommerce.android.ui.payments.receipt.preview.ReceiptPreviewViewModel.ReceiptPreviewViewState.Loading @@ -29,7 +23,6 @@ import javax.inject.Inject class ReceiptPreviewViewModel @Inject constructor( savedState: SavedStateHandle, - private val tracker: AnalyticsTrackerWrapper, private val paymentsFlowTracker: PaymentsFlowTracker, private val paymentReceiptShare: PaymentReceiptShare, ) : ScopedViewModel(savedState) { @@ -47,15 +40,17 @@ class ReceiptPreviewViewModel } fun onPrintClicked() { - tracker.track(RECEIPT_PRINT_TAPPED) - triggerEvent(PrintReceipt(args.receiptUrl, "receipt-order-${args.orderId}")) + launch { + paymentsFlowTracker.trackPrintReceiptTapped() + triggerEvent(PrintReceipt(args.receiptUrl, "receipt-order-${args.orderId}")) + } } fun onShareClicked() { launch { viewState.value = Loading - tracker.track(RECEIPT_EMAIL_TAPPED) + paymentsFlowTracker.trackEmailReceiptTapped() when (val sharingResult = paymentReceiptShare(args.receiptUrl, args.orderId)) { is PaymentReceiptShare.ReceiptShareResult.Error.FileCreation -> { paymentsFlowTracker.trackPaymentsReceiptSharingFailed(sharingResult) @@ -79,13 +74,13 @@ class ReceiptPreviewViewModel } fun onPrintResult(result: PrintJobResult) { - tracker.track( + launch { when (result) { - CANCELLED -> RECEIPT_PRINT_CANCELED - FAILED -> RECEIPT_PRINT_FAILED - STARTED -> RECEIPT_PRINT_SUCCESS + CANCELLED -> paymentsFlowTracker.trackPrintReceiptCancelled() + FAILED -> paymentsFlowTracker.trackPrintReceiptFailed() + STARTED -> paymentsFlowTracker.trackPrintReceiptSucceeded() } - ) + } } sealed class ReceiptPreviewViewState( diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/tracking/PaymentsFlowTracker.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/tracking/PaymentsFlowTracker.kt index 9cdce47de8a..0ffc92e1cb3 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/tracking/PaymentsFlowTracker.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/payments/tracking/PaymentsFlowTracker.kt @@ -53,6 +53,8 @@ import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_CANCELED import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_FAILED import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_SUCCESS import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_TAPPED +import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_URL_FETCHING_FAILS +import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_VIEW_TAPPED import com.woocommerce.android.analytics.AnalyticsTracker import com.woocommerce.android.analytics.AnalyticsTracker.Companion.KEY_CASH_ON_DELIVERY_SOURCE import com.woocommerce.android.analytics.AnalyticsTracker.Companion.KEY_ERROR_DESC @@ -73,6 +75,7 @@ import com.woocommerce.android.ui.payments.cardreader.onboarding.PluginType import com.woocommerce.android.ui.payments.cardreader.onboarding.PluginType.STRIPE_EXTENSION_GATEWAY import com.woocommerce.android.ui.payments.cardreader.onboarding.PluginType.WOOCOMMERCE_PAYMENTS import com.woocommerce.android.ui.payments.hub.PaymentsHubViewModel.CashOnDeliverySource +import com.woocommerce.android.ui.payments.receipt.PaymentReceiptHelper import com.woocommerce.android.ui.payments.receipt.PaymentReceiptShare import com.woocommerce.android.ui.payments.taptopay.TapToPayAvailabilityStatus.Result.NotAvailable import javax.inject.Inject @@ -81,7 +84,8 @@ class PaymentsFlowTracker @Inject constructor( private val trackerWrapper: AnalyticsTrackerWrapper, private val appPrefsWrapper: AppPrefsWrapper, private val selectedSite: SelectedSite, - private val cardReaderTrackingInfoProvider: CardReaderTrackingInfoProvider + private val cardReaderTrackingInfoProvider: CardReaderTrackingInfoProvider, + private val paymentReceiptHelper: PaymentReceiptHelper, ) { @VisibleForTesting fun track( @@ -156,6 +160,13 @@ class PaymentsFlowTracker @Inject constructor( } } + private suspend fun getReceiptSource(): Pair = + if (paymentReceiptHelper.isWCCanGenerateReceipts()) { + AnalyticsTracker.KEY_SOURCE to "backend" + } else { + AnalyticsTracker.KEY_SOURCE to "local" + } + @Suppress("ComplexMethod") private fun getOnboardingNotCompletedReason(state: CardReaderOnboardingState): String? = when (state) { @@ -412,28 +423,58 @@ class PaymentsFlowTracker @Inject constructor( ) } - fun trackPrintReceiptTapped() { - track(RECEIPT_PRINT_TAPPED) + suspend fun trackPrintReceiptTapped() { + track( + RECEIPT_PRINT_TAPPED, + properties = mutableMapOf(getReceiptSource()) + ) + } + + suspend fun trackEmailReceiptTapped() { + track( + RECEIPT_EMAIL_TAPPED, + properties = mutableMapOf(getReceiptSource()) + ) } - fun trackEmailReceiptTapped() { - track(RECEIPT_EMAIL_TAPPED) + suspend fun trackPrintReceiptCancelled() { + track( + RECEIPT_PRINT_CANCELED, + properties = mutableMapOf(getReceiptSource()) + ) } - fun trackEmailReceiptFailed() { - track(RECEIPT_EMAIL_FAILED) + suspend fun trackPrintReceiptFailed() { + track( + RECEIPT_PRINT_FAILED, + properties = mutableMapOf(getReceiptSource()) + ) } - fun trackPrintReceiptCancelled() { - track(RECEIPT_PRINT_CANCELED) + suspend fun trackPrintReceiptSucceeded() { + track( + RECEIPT_PRINT_SUCCESS, + properties = mutableMapOf(getReceiptSource()) + ) } - fun trackPrintReceiptFailed() { - track(RECEIPT_PRINT_FAILED) + suspend fun trackReceiptViewTapped(properties: Map) { + track( + RECEIPT_VIEW_TAPPED, + properties = properties.toMutableMap().also { + it.putAll( + mapOf(getReceiptSource()) + ) + } + ) } - fun trackPrintReceiptSucceeded() { - track(RECEIPT_PRINT_SUCCESS) + suspend fun trackReceiptUrlFetchingFails(errorDescription: String) { + track( + RECEIPT_URL_FETCHING_FAILS, + properties = mutableMapOf(getReceiptSource()), + errorDescription = errorDescription, + ) } fun trackPaymentCancelled(currentPaymentState: String?) { @@ -581,27 +622,32 @@ class PaymentsFlowTracker @Inject constructor( ) } - fun trackPaymentsReceiptSharingFailed(sharingResult: PaymentReceiptShare.ReceiptShareResult.Error) { + suspend fun trackPaymentsReceiptSharingFailed(sharingResult: PaymentReceiptShare.ReceiptShareResult.Error) { when (sharingResult) { is PaymentReceiptShare.ReceiptShareResult.Error.FileCreation -> { track( RECEIPT_EMAIL_FAILED, errorType = "file_creation_failed", - errorDescription = "File creation failed" + errorDescription = "File creation failed", + properties = mutableMapOf(getReceiptSource()) ) } + is PaymentReceiptShare.ReceiptShareResult.Error.FileDownload -> { track( RECEIPT_EMAIL_FAILED, errorType = "file_download_failed", - errorDescription = "File download failed" + errorDescription = "File download failed", + properties = mutableMapOf(getReceiptSource()) ) } + is PaymentReceiptShare.ReceiptShareResult.Error.Sharing -> { track( RECEIPT_EMAIL_FAILED, errorType = "no_app_found", - errorDescription = sharingResult.exception.message + errorDescription = sharingResult.exception.message, + properties = mutableMapOf(getReceiptSource()) ) } } diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/OrderDetailViewModelTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/OrderDetailViewModelTest.kt index ad4ad6ae310..d59125d1771 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/OrderDetailViewModelTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/OrderDetailViewModelTest.kt @@ -1250,7 +1250,8 @@ class OrderDetailViewModelTest : BaseUnitTest() { whenever(orderDetailRepository.fetchOrderNotes(any())).thenReturn(false) whenever(addonsRepository.containsAddonsFrom(any())).thenReturn(false) - whenever(paymentReceiptHelper.getReceiptUrl(order.id)).thenReturn(Result.failure(Exception(""))) + val errorMessage = "error" + whenever(paymentReceiptHelper.getReceiptUrl(order.id)).thenReturn(Result.failure(Exception(errorMessage))) // WHEN viewModel.start() @@ -1259,6 +1260,9 @@ class OrderDetailViewModelTest : BaseUnitTest() { // THEN assertThat((viewModel.event.value as ShowSnackbar).message).isEqualTo(string.receipt_fetching_error) + verify(paymentsFlowTracker).trackReceiptUrlFetchingFails( + errorDescription = errorMessage + ) } @Test diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/CardReaderPaymentViewModelTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/CardReaderPaymentViewModelTest.kt index d735c8f6aa2..aae2ef8311b 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/CardReaderPaymentViewModelTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/cardreader/CardReaderPaymentViewModelTest.kt @@ -2337,21 +2337,21 @@ class CardReaderPaymentViewModelTest : BaseUnitTest() { } @Test - fun `when OS accepts the print request, then print success event tracked`() { + fun `when OS accepts the print request, then print success event tracked`() = testBlocking { viewModel.onPrintResult(STARTED) verify(tracker).trackPrintReceiptSucceeded() } @Test - fun `when OS refuses the print request, then print failed event tracked`() { + fun `when OS refuses the print request, then print failed event tracked`() = testBlocking { viewModel.onPrintResult(FAILED) verify(tracker).trackPrintReceiptFailed() } @Test - fun `when manually cancels the print request, then print cancelled event tracked`() { + fun `when manually cancels the print request, then print cancelled event tracked`() = testBlocking { viewModel.onPrintResult(CANCELLED) verify(tracker).trackPrintReceiptCancelled() @@ -2568,14 +2568,6 @@ class CardReaderPaymentViewModelTest : BaseUnitTest() { assertThat(viewModel.event.value).isInstanceOf(Exit::class.java) } - @Test - fun `when email activity not found, then event tracked`() = - testBlocking { - viewModel.onEmailActivityNotFound() - - verify(tracker).trackEmailReceiptFailed() - } - @Test fun `given user presses back button, when re-fetching order, then ReFetchingOrderState shown`() = testBlocking { diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewViewModelTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewViewModelTest.kt index b4e002726cd..15af89dba90 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewViewModelTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/receipt/preview/ReceiptPreviewViewModelTest.kt @@ -2,12 +2,6 @@ package com.woocommerce.android.ui.payments.receipt.preview import androidx.lifecycle.SavedStateHandle import com.woocommerce.android.R -import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_EMAIL_TAPPED -import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_CANCELED -import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_FAILED -import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_SUCCESS -import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_TAPPED -import com.woocommerce.android.analytics.AnalyticsTrackerWrapper import com.woocommerce.android.ui.payments.receipt.PaymentReceiptShare import com.woocommerce.android.ui.payments.receipt.preview.ReceiptPreviewViewModel.ReceiptPreviewViewState.Content import com.woocommerce.android.ui.payments.receipt.preview.ReceiptPreviewViewModel.ReceiptPreviewViewState.Loading @@ -29,7 +23,6 @@ import org.mockito.kotlin.whenever class ReceiptPreviewViewModelTest : BaseUnitTest() { private lateinit var viewModel: ReceiptPreviewViewModel - private val tracker: AnalyticsTrackerWrapper = mock() private val paymentsFlowTracker: PaymentsFlowTracker = mock() private val paymentReceiptShare: PaymentReceiptShare = mock() @@ -41,7 +34,7 @@ class ReceiptPreviewViewModelTest : BaseUnitTest() { @Before fun setUp() { - viewModel = ReceiptPreviewViewModel(savedState, tracker, paymentsFlowTracker, paymentReceiptShare) + viewModel = ReceiptPreviewViewModel(savedState, paymentsFlowTracker, paymentReceiptShare) } @Test @@ -77,7 +70,7 @@ class ReceiptPreviewViewModelTest : BaseUnitTest() { testBlocking { viewModel.onShareClicked() - verify(tracker).track(RECEIPT_EMAIL_TAPPED) + verify(paymentsFlowTracker).trackEmailReceiptTapped() } @Test @@ -167,7 +160,7 @@ class ReceiptPreviewViewModelTest : BaseUnitTest() { testBlocking { viewModel.onPrintClicked() - verify(tracker).track(RECEIPT_PRINT_TAPPED) + verify(paymentsFlowTracker).trackPrintReceiptTapped() } @Test @@ -175,7 +168,7 @@ class ReceiptPreviewViewModelTest : BaseUnitTest() { testBlocking { viewModel.onPrintResult(FAILED) - verify(tracker).track(RECEIPT_PRINT_FAILED) + verify(paymentsFlowTracker).trackPrintReceiptFailed() } @Test @@ -183,7 +176,7 @@ class ReceiptPreviewViewModelTest : BaseUnitTest() { testBlocking { viewModel.onPrintResult(CANCELLED) - verify(tracker).track(RECEIPT_PRINT_CANCELED) + verify(paymentsFlowTracker).trackPrintReceiptCancelled() } @Test @@ -191,6 +184,6 @@ class ReceiptPreviewViewModelTest : BaseUnitTest() { testBlocking { viewModel.onPrintResult(STARTED) - verify(tracker).track(RECEIPT_PRINT_SUCCESS) + verify(paymentsFlowTracker).trackPrintReceiptSucceeded() } } diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/tracking/PaymentsFlowTrackerTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/tracking/PaymentsFlowTrackerTest.kt index 14e117d6353..4f78bbd6d19 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/tracking/PaymentsFlowTrackerTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/payments/tracking/PaymentsFlowTrackerTest.kt @@ -26,7 +26,6 @@ import com.woocommerce.android.analytics.AnalyticsEvent.ENABLE_CASH_ON_DELIVERY_ import com.woocommerce.android.analytics.AnalyticsEvent.PAYMENTS_FLOW_ORDER_COLLECT_PAYMENT_TAPPED import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_EMAIL_TAPPED import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_CANCELED -import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_FAILED import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_SUCCESS import com.woocommerce.android.analytics.AnalyticsEvent.RECEIPT_PRINT_TAPPED import com.woocommerce.android.analytics.AnalyticsTracker @@ -42,6 +41,7 @@ import com.woocommerce.android.ui.payments.cardreader.onboarding.PluginType.STRI import com.woocommerce.android.ui.payments.cardreader.onboarding.PluginType.WOOCOMMERCE_PAYMENTS import com.woocommerce.android.ui.payments.hub.PaymentsHubViewModel.CashOnDeliverySource.ONBOARDING import com.woocommerce.android.ui.payments.hub.PaymentsHubViewModel.CashOnDeliverySource.PAYMENTS_HUB +import com.woocommerce.android.ui.payments.receipt.PaymentReceiptHelper import com.woocommerce.android.viewmodel.BaseUnitTest import kotlinx.coroutines.ExperimentalCoroutinesApi import org.assertj.core.api.Assertions.assertThat @@ -76,13 +76,13 @@ class PaymentsFlowTrackerTest : BaseUnitTest() { } private val trackerWrapper: AnalyticsTrackerWrapper = mock() - private val appPrefsWrapper: AppPrefsWrapper = mock() { + private val appPrefsWrapper: AppPrefsWrapper = mock { on(it.getCardReaderPreferredPlugin(anyInt(), anyLong(), anyLong())).thenReturn(WOOCOMMERCE_PAYMENTS) } private val selectedSite: SelectedSite = mock { on(it.get()).thenReturn(SiteModel()) } - private val cardReaderTrackingInfoProvider: CardReaderTrackingInfoProvider = mock() { + private val cardReaderTrackingInfoProvider: CardReaderTrackingInfoProvider = mock { on { trackingInfo }.thenReturn( TrackingInfo( country = COUNTRY_CODE, @@ -93,11 +93,14 @@ class PaymentsFlowTrackerTest : BaseUnitTest() { ) } + private val paymentReceiptHelper: PaymentReceiptHelper = mock() + private val paymentsFlowTracker = PaymentsFlowTracker( trackerWrapper, appPrefsWrapper, selectedSite, - cardReaderTrackingInfoProvider + cardReaderTrackingInfoProvider, + paymentReceiptHelper, ) @Test @@ -1039,40 +1042,160 @@ class PaymentsFlowTrackerTest : BaseUnitTest() { } @Test - fun `when user clicks on print receipt button, then RECEIPT_PRINT_TAPPED tracked`() = + fun `given wc core can generate receipts, when trackPrintReceiptTapped, then RECEIPT_PRINT_TAPPED tracked`() = testBlocking { + whenever(paymentReceiptHelper.isWCCanGenerateReceipts()).thenReturn(true) + paymentsFlowTracker.trackPrintReceiptTapped() - verify(trackerWrapper).track(eq(RECEIPT_PRINT_TAPPED), any()) + verify(trackerWrapper).track( + eq(RECEIPT_PRINT_TAPPED), + check { assertThat(it["source"]).isEqualTo("backend") } + ) } @Test - fun `when OS accepts the print request, then RECEIPT_PRINT_SUCCESS tracked`() { - paymentsFlowTracker.trackPrintReceiptSucceeded() + fun `given new wc core can not generate receipts, when trackPrintReceiptTapped, then RECEIPT_PRINT_TAPPED tracked`() = + testBlocking { + whenever(paymentReceiptHelper.isWCCanGenerateReceipts()).thenReturn(false) - verify(trackerWrapper).track(eq(RECEIPT_PRINT_SUCCESS), any()) - } + paymentsFlowTracker.trackPrintReceiptTapped() + + verify(trackerWrapper).track( + eq(RECEIPT_PRINT_TAPPED), + check { assertThat(it["source"]).isEqualTo("local") } + ) + } @Test - fun `when OS refuses the print request, then RECEIPT_PRINT_FAILED tracked`() { - paymentsFlowTracker.trackPrintReceiptFailed() + fun `given wc core can generate receipts, when trackPrintReceiptSucceeded, then RECEIPT_PRINT_SUCCESS tracked`() = + testBlocking { + whenever(paymentReceiptHelper.isWCCanGenerateReceipts()).thenReturn(true) - verify(trackerWrapper).track(eq(RECEIPT_PRINT_FAILED), any()) - } + paymentsFlowTracker.trackPrintReceiptSucceeded() + + verify(trackerWrapper).track( + eq(RECEIPT_PRINT_SUCCESS), + check { assertThat(it["source"]).isEqualTo("backend") } + ) + } @Test - fun `when manually cancels the print request, then RECEIPT_PRINT_CANCELED tracked`() { - paymentsFlowTracker.trackPrintReceiptCancelled() + fun `given wc core can not generate receipts, when trackPrintReceiptSucceeded, then RECEIPT_PRINT_SUCCESS tracked`() = + testBlocking { + whenever(paymentReceiptHelper.isWCCanGenerateReceipts()).thenReturn(false) - verify(trackerWrapper).track(eq(RECEIPT_PRINT_CANCELED), any()) - } + paymentsFlowTracker.trackPrintReceiptSucceeded() + + verify(trackerWrapper).track( + eq(RECEIPT_PRINT_SUCCESS), + check { assertThat(it["source"]).isEqualTo("local") } + ) + } + + @Test + fun `given wc core can generate receipts, when trackPrintReceiptCancelled, then RECEIPT_PRINT_CANCELED tracked`() = + testBlocking { + whenever(paymentReceiptHelper.isWCCanGenerateReceipts()).thenReturn(true) + + paymentsFlowTracker.trackPrintReceiptCancelled() + + verify(trackerWrapper).track( + eq(RECEIPT_PRINT_CANCELED), + check { assertThat(it["source"]).isEqualTo("backend") } + ) + } @Test - fun `when user clicks on send receipt button, then RECEIPT_EMAIL_TAPPED tracked`() = + fun `given wc core can not generate receipts, when trackPrintReceiptCancelled, then RECEIPT_PRINT_CANCELED tracked`() = testBlocking { + whenever(paymentReceiptHelper.isWCCanGenerateReceipts()).thenReturn(false) + + paymentsFlowTracker.trackPrintReceiptCancelled() + + verify(trackerWrapper).track( + eq(RECEIPT_PRINT_CANCELED), + check { assertThat(it["source"]).isEqualTo("local") } + ) + } + + @Test + fun `given wc core can generate receipts, when trackEmailReceiptTapped, then RECEIPT_EMAIL_TAPPED tracked`() = + testBlocking { + whenever(paymentReceiptHelper.isWCCanGenerateReceipts()).thenReturn(true) + paymentsFlowTracker.trackEmailReceiptTapped() - verify(trackerWrapper).track(eq(RECEIPT_EMAIL_TAPPED), any()) + verify(trackerWrapper).track( + eq(RECEIPT_EMAIL_TAPPED), + check { assertThat(it["source"]).isEqualTo("backend") } + ) + } + + @Test + fun `given wc core can generate receipts, when trackPrintReceiptFailed, then RECEIPT_PRINT_FAILED tracked`() = + testBlocking { + whenever(paymentReceiptHelper.isWCCanGenerateReceipts()).thenReturn(true) + + paymentsFlowTracker.trackPrintReceiptFailed() + + verify(trackerWrapper).track( + eq(AnalyticsEvent.RECEIPT_PRINT_FAILED), + check { assertThat(it["source"]).isEqualTo("backend") } + ) + } + + @Test + fun `given wc core can not generate receipts, when trackPrintReceiptFailed, then RECEIPT_PRINT_FAILED tracked`() = + testBlocking { + whenever(paymentReceiptHelper.isWCCanGenerateReceipts()).thenReturn(false) + + paymentsFlowTracker.trackPrintReceiptFailed() + + verify(trackerWrapper).track( + eq(AnalyticsEvent.RECEIPT_PRINT_FAILED), + check { assertThat(it["source"]).isEqualTo("local") } + ) + } + + @Test + fun `given wc core can not generate receipts, when trackReceiptViewTapped, then RECEIPT_VIEW_TAPPED tracked`() = + testBlocking { + whenever(paymentReceiptHelper.isWCCanGenerateReceipts()).thenReturn(false) + + paymentsFlowTracker.trackReceiptViewTapped( + properties = mapOf( + "key" to "value" + ) + ) + + verify(trackerWrapper).track( + eq(AnalyticsEvent.RECEIPT_VIEW_TAPPED), + check { + assertThat(it["source"]).isEqualTo("local") + assertThat(it["key"]).isEqualTo("value") + } + ) + } + + @Test + fun `given wc core can generate receipts, when trackReceiptViewTapped, then RECEIPT_VIEW_TAPPED tracked`() = + testBlocking { + whenever(paymentReceiptHelper.isWCCanGenerateReceipts()).thenReturn(true) + + paymentsFlowTracker.trackReceiptViewTapped( + properties = mapOf( + "key" to "value" + ) + ) + + verify(trackerWrapper).track( + eq(AnalyticsEvent.RECEIPT_VIEW_TAPPED), + check { + assertThat(it["source"]).isEqualTo("backend") + assertThat(it["key"]).isEqualTo("value") + } + ) } @Test