Skip to content

Commit

Permalink
Merge pull request #1904 from Adyen/feature/analytics_track_submit_af…
Browse files Browse the repository at this point in the history
…ter_validation

Analytics - Track submit event after validation
  • Loading branch information
araratthehero authored Dec 17, 2024
2 parents 88b04a8 + a0074bb commit d32070e
Show file tree
Hide file tree
Showing 34 changed files with 381 additions and 225 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ internal class DefaultACHDirectDebitDelegate(
private val _viewFlow: MutableStateFlow<ComponentViewType?> = MutableStateFlow(ACHDirectDebitComponentViewType)
override val viewFlow: Flow<ComponentViewType?> = _viewFlow

override val submitFlow: Flow<ACHDirectDebitComponentState> = submitHandler.submitFlow
override val submitFlow: Flow<ACHDirectDebitComponentState> = getTrackedSubmitFlow()
override val uiStateFlow: Flow<PaymentComponentUIState> = submitHandler.uiStateFlow
override val uiEventFlow: Flow<PaymentComponentUIEvent> = submitHandler.uiEventFlow

Expand Down Expand Up @@ -363,10 +363,12 @@ internal class DefaultACHDirectDebitDelegate(
analyticsManager.clear(this)
}

override fun onSubmit() {
private fun getTrackedSubmitFlow() = submitHandler.submitFlow.onEach {
val event = GenericEvents.submit(paymentMethod.type.orEmpty())
analyticsManager.trackEvent(event)
}

override fun onSubmit() {
val state = _componentStateFlow.value
submitHandler.onSubmit(
state = state,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ import com.adyen.checkout.ui.core.internal.util.AddressFormUtils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
Expand All @@ -64,7 +66,10 @@ import org.junit.jupiter.params.provider.Arguments.arguments
import org.junit.jupiter.params.provider.MethodSource
import org.mockito.Mock
import org.mockito.junit.jupiter.MockitoExtension
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
import java.util.Locale

@OptIn(ExperimentalCoroutinesApi::class)
Expand Down Expand Up @@ -335,33 +340,34 @@ internal class DefaultACHDirectDebitDelegateTest(
}

@Test
fun `encryption fails, then component state should be invalid and analytics error event is tracked`() = runTest {
genericEncryptor.shouldThrowException = true
fun `encryption fails, then component state should be invalid and analytics error event is tracked`() =
runTest {
genericEncryptor.shouldThrowException = true

delegate.initialize(CoroutineScope(UnconfinedTestDispatcher()))
delegate.initialize(CoroutineScope(UnconfinedTestDispatcher()))

delegate.updateInputData {
bankLocationId = TEST_BANK_BANK_LOCATION_ID
bankAccountNumber = TEST_BANK_ACCOUNT_NUMBER
ownerName = TEST_OWNER_NAME
address = AddressInputModel(
postalCode = "34220",
street = "Street Name",
stateOrProvince = "province",
houseNumberOrName = "44",
apartmentSuite = "aparment",
city = "Istanbul",
country = "Turkey",
)
}
delegate.updateInputData {
bankLocationId = TEST_BANK_BANK_LOCATION_ID
bankAccountNumber = TEST_BANK_ACCOUNT_NUMBER
ownerName = TEST_OWNER_NAME
address = AddressInputModel(
postalCode = "34220",
street = "Street Name",
stateOrProvince = "province",
houseNumberOrName = "44",
apartmentSuite = "aparment",
city = "Istanbul",
country = "Turkey",
)
}

val componentState = delegate.componentStateFlow.first()
val componentState = delegate.componentStateFlow.first()

val expectedEvent = GenericEvents.error(TEST_PAYMENT_METHOD_TYPE, ErrorEvent.ENCRYPTION)
analyticsManager.assertLastEventEquals(expectedEvent)
val expectedEvent = GenericEvents.error(TEST_PAYMENT_METHOD_TYPE, ErrorEvent.ENCRYPTION)
analyticsManager.assertLastEventEquals(expectedEvent)

assertFalse(componentState.isValid)
}
assertFalse(componentState.isValid)
}

@Test
fun `when bankLocationId is invalid, then component state should be invalid`() = runTest {
Expand Down Expand Up @@ -655,11 +661,15 @@ internal class DefaultACHDirectDebitDelegateTest(
}

@Test
fun `when onSubmit is called, then submit event is tracked`() {
delegate.onSubmit()
fun `when submitFlow emits an event, then submit event is tracked`() = runTest {
val submitFlow = flow<ACHDirectDebitComponentState> { emit(mock()) }
whenever(submitHandler.submitFlow) doReturn submitFlow
val delegate = createAchDelegate()

val expectedEvent = GenericEvents.submit(TEST_PAYMENT_METHOD_TYPE)
analyticsManager.assertLastEventEquals(expectedEvent)
delegate.submitFlow.collectLatest {
val expectedEvent = GenericEvents.submit(TEST_PAYMENT_METHOD_TYPE)
analyticsManager.assertLastEventEquals(expectedEvent)
}
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import com.adyen.checkout.ui.core.internal.ui.SubmitHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.onEach

@Suppress("TooManyFunctions")
internal class DefaultBacsDirectDebitDelegate(
Expand All @@ -55,7 +56,7 @@ internal class DefaultBacsDirectDebitDelegate(
private val _componentStateFlow = MutableStateFlow(createComponentState())
override val componentStateFlow: Flow<BacsDirectDebitComponentState> = _componentStateFlow

override val submitFlow: Flow<BacsDirectDebitComponentState> = submitHandler.submitFlow
override val submitFlow: Flow<BacsDirectDebitComponentState> = getTrackedSubmitFlow()
override val uiStateFlow: Flow<PaymentComponentUIState> = submitHandler.uiStateFlow
override val uiEventFlow: Flow<PaymentComponentUIEvent> = submitHandler.uiEventFlow

Expand Down Expand Up @@ -122,6 +123,11 @@ internal class DefaultBacsDirectDebitDelegate(
onInputDataChanged()
}

private fun getTrackedSubmitFlow() = submitHandler.submitFlow.onEach {
val event = GenericEvents.submit(paymentMethod.type.orEmpty())
analyticsManager.trackEvent(event)
}

override fun onSubmit() {
val state = _componentStateFlow.value
when (inputData.mode) {
Expand All @@ -134,12 +140,7 @@ internal class DefaultBacsDirectDebitDelegate(
}
}

BacsDirectDebitMode.CONFIRMATION -> {
val event = GenericEvents.submit(paymentMethod.type.orEmpty())
analyticsManager.trackEvent(event)

submitHandler.onSubmit(state)
}
BacsDirectDebitMode.CONFIRMATION -> submitHandler.onSubmit(state)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import com.adyen.checkout.test.LoggingExtension
import com.adyen.checkout.ui.core.internal.ui.SubmitHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Assertions.assertEquals
Expand All @@ -49,7 +51,10 @@ import org.junit.jupiter.params.provider.Arguments.arguments
import org.junit.jupiter.params.provider.MethodSource
import org.mockito.Mock
import org.mockito.junit.jupiter.MockitoExtension
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
import java.util.Locale

@OptIn(ExperimentalCoroutinesApi::class)
Expand Down Expand Up @@ -566,23 +571,15 @@ internal class DefaultBacsDirectDebitDelegateTest(
}

@Test
fun `when onSubmit is called and component is in confirmation mode, then submit event is tracked`() {
delegate.updateInputData { mode = BacsDirectDebitMode.CONFIRMATION }

delegate.onSubmit()

val expectedEvent = GenericEvents.submit(TEST_PAYMENT_METHOD_TYPE)
analyticsManager.assertLastEventEquals(expectedEvent)
}
fun `when submitFlow emits an event, then submit event is tracked`() = runTest {
val submitFlow = flow<BacsDirectDebitComponentState> { emit(mock()) }
whenever(submitHandler.submitFlow) doReturn submitFlow
val delegate = createBacsDelegate()

@Test
fun `when onSubmit is called and component is not in confirmation mode, then submit event is not tracked`() {
delegate.updateInputData { mode = BacsDirectDebitMode.INPUT }

delegate.onSubmit()

val expectedEvent = GenericEvents.submit(TEST_PAYMENT_METHOD_TYPE)
analyticsManager.assertLastEventNotEquals(expectedEvent)
delegate.submitFlow.collectLatest {
val expectedEvent = GenericEvents.submit(TEST_PAYMENT_METHOD_TYPE)
analyticsManager.assertLastEventEquals(expectedEvent)
}
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import com.adyen.checkout.ui.core.internal.ui.SubmitHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.onEach

@Suppress("TooManyFunctions")
internal class DefaultBlikDelegate(
Expand All @@ -58,7 +59,7 @@ internal class DefaultBlikDelegate(
private val _viewFlow: MutableStateFlow<ComponentViewType?> = MutableStateFlow(BlikComponentViewType)
override val viewFlow: Flow<ComponentViewType?> = _viewFlow

override val submitFlow: Flow<BlikComponentState> = submitHandler.submitFlow
override val submitFlow: Flow<BlikComponentState> = getTrackedSubmitFlow()

override val uiStateFlow: Flow<PaymentComponentUIState> = submitHandler.uiStateFlow

Expand Down Expand Up @@ -150,10 +151,12 @@ internal class DefaultBlikDelegate(
)
}

override fun onSubmit() {
private fun getTrackedSubmitFlow() = submitHandler.submitFlow.onEach {
val event = GenericEvents.submit(paymentMethod.type.orEmpty())
analyticsManager.trackEvent(event)
}

override fun onSubmit() {
val state = _componentStateFlow.value
submitHandler.onSubmit(state)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import com.adyen.checkout.ui.core.internal.ui.SubmitHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.onEach

@Suppress("TooManyFunctions")
internal class StoredBlikDelegate(
Expand All @@ -55,7 +56,7 @@ internal class StoredBlikDelegate(
private val _viewFlow: MutableStateFlow<ComponentViewType?> = MutableStateFlow(BlikComponentViewType)
override val viewFlow: Flow<ComponentViewType?> = _viewFlow

override val submitFlow: Flow<BlikComponentState> = submitHandler.submitFlow
override val submitFlow: Flow<BlikComponentState> = getTrackedSubmitFlow()

override val uiStateFlow: Flow<PaymentComponentUIState> = submitHandler.uiStateFlow

Expand Down Expand Up @@ -104,10 +105,12 @@ internal class StoredBlikDelegate(
adyenLog(AdyenLogLevel.ERROR) { "updateInputData should not be called in StoredBlikDelegate" }
}

override fun onSubmit() {
private fun getTrackedSubmitFlow() = submitHandler.submitFlow.onEach {
val event = GenericEvents.submit(storedPaymentMethod.type.orEmpty())
analyticsManager.trackEvent(event)
}

override fun onSubmit() {
val state = _componentStateFlow.value
submitHandler.onSubmit(state)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import com.adyen.checkout.test.LoggingExtension
import com.adyen.checkout.ui.core.internal.ui.SubmitHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Assertions.assertEquals
Expand All @@ -43,7 +45,10 @@ import org.junit.jupiter.params.provider.Arguments.arguments
import org.junit.jupiter.params.provider.MethodSource
import org.mockito.Mock
import org.mockito.junit.jupiter.MockitoExtension
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
import java.util.Locale

@OptIn(ExperimentalCoroutinesApi::class)
Expand Down Expand Up @@ -264,11 +269,15 @@ internal class DefaultBlikDelegateTest(
}

@Test
fun `when onSubmit is called, then submit event is tracked`() {
delegate.onSubmit()

val expectedEvent = GenericEvents.submit(TEST_PAYMENT_METHOD_TYPE)
analyticsManager.assertLastEventEquals(expectedEvent)
fun `when submitFlow emits an event, then submit event is tracked`() = runTest {
val submitFlow = flow<BlikComponentState> { emit(mock()) }
whenever(submitHandler.submitFlow) doReturn submitFlow
val delegate = createBlikDelegate()

delegate.submitFlow.collectLatest {
val expectedEvent = GenericEvents.submit(TEST_PAYMENT_METHOD_TYPE)
analyticsManager.assertLastEventEquals(expectedEvent)
}
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import com.adyen.checkout.test.LoggingExtension
import com.adyen.checkout.ui.core.internal.ui.SubmitHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Assertions.assertFalse
Expand All @@ -37,7 +39,10 @@ import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.mockito.Mock
import org.mockito.junit.jupiter.MockitoExtension
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
import java.util.Locale

@OptIn(ExperimentalCoroutinesApi::class)
Expand Down Expand Up @@ -130,11 +135,15 @@ class StoredBlikDelegateTest(
}

@Test
fun `when onSubmit is called, then submit event is tracked`() {
delegate.onSubmit()

val expectedEvent = GenericEvents.submit(TEST_PAYMENT_METHOD_TYPE)
analyticsManager.assertLastEventEquals(expectedEvent)
fun `when submitFlow emits an event, then submit event is tracked`() = runTest {
val submitFlow = flow<BlikComponentState> { emit(mock()) }
whenever(submitHandler.submitFlow) doReturn submitFlow
val delegate = createStoredBlikDelegate()

delegate.submitFlow.collectLatest {
val expectedEvent = GenericEvents.submit(TEST_PAYMENT_METHOD_TYPE)
analyticsManager.assertLastEventEquals(expectedEvent)
}
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ internal class DefaultBoletoDelegate(
private val _viewFlow: MutableStateFlow<ComponentViewType?> = MutableStateFlow(BoletoComponentViewType)
override val viewFlow: Flow<ComponentViewType?> = _viewFlow

override val submitFlow: Flow<BoletoComponentState> = submitHandler.submitFlow
override val submitFlow: Flow<BoletoComponentState> = getTrackedSubmitFlow()
override val uiStateFlow: Flow<PaymentComponentUIState> = submitHandler.uiStateFlow
override val uiEventFlow: Flow<PaymentComponentUIEvent> = submitHandler.uiEventFlow

Expand Down Expand Up @@ -292,10 +292,12 @@ internal class DefaultBoletoDelegate(
observerRepository.removeObservers()
}

override fun onSubmit() {
private fun getTrackedSubmitFlow() = submitHandler.submitFlow.onEach {
val event = GenericEvents.submit(paymentMethod.type.orEmpty())
analyticsManager.trackEvent(event)
}

override fun onSubmit() {
submitHandler.onSubmit(_componentStateFlow.value)
}

Expand Down
Loading

0 comments on commit d32070e

Please sign in to comment.