Skip to content

Commit

Permalink
feat(multi-id): implement clearContact and clearPredictOnlyContact fo…
Browse files Browse the repository at this point in the history
…r predict

SUITEDEV-35599
  • Loading branch information
matusekma committed Apr 30, 2024
1 parent d23d084 commit ab0268d
Show file tree
Hide file tree
Showing 12 changed files with 211 additions and 61 deletions.
40 changes: 11 additions & 29 deletions emarsys-sdk/src/androidTest/java/com/emarsys/EmarsysTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ class EmarsysTest : AnnotationSpec() {
private lateinit var mockPush: PushApi
private lateinit var mockPredict: PredictApi
private lateinit var mockPredictRestricted: PredictRestrictedApi
private lateinit var mockLoggingPredictRestricted: PredictRestrictedApi
private lateinit var mockMobileEngageApi: MobileEngageApi
private lateinit var mockLoggingMobileEngageApi: MobileEngageApi
private lateinit var mockLoggingPredict: PredictApi
Expand Down Expand Up @@ -207,6 +208,7 @@ class EmarsysTest : AnnotationSpec() {
mockPredict = mock()
mockLoggingPredict = mock()
mockPredictRestricted = mock()
mockLoggingPredictRestricted = mock()
mockConfig = mock()
mockConfigInternal = mock()
mockMessageInbox = mock()
Expand Down Expand Up @@ -269,7 +271,7 @@ class EmarsysTest : AnnotationSpec() {
predict = mockPredict,
loggingPredict = mockLoggingPredict,
predictRestricted = mockPredictRestricted,
loggingPredictRestricted = mockPredictRestricted,
loggingPredictRestricted = mockLoggingPredictRestricted,
config = mockConfig,
configInternal = mockConfigInternal,
eventService = mockEventServiceApi,
Expand Down Expand Up @@ -654,7 +656,7 @@ class EmarsysTest : AnnotationSpec() {
runBlockingOnCoreSdkThread()

runBlockingOnCoreSdkThread {
verify(mockPredictRestricted).setContact(CONTACT_FIELD_ID, CONTACT_FIELD_VALUE, null)
verify(mockPredictRestricted).setContact(CONTACT_FIELD_ID, CONTACT_FIELD_VALUE, completionListener)
verifyNoInteractions(mockMobileEngageApi)
}
}
Expand Down Expand Up @@ -754,19 +756,19 @@ class EmarsysTest : AnnotationSpec() {
}

@Test
fun testSetContactWithCompletionListener_delegatesToInternals_whenBothFeaturesEnabled() {
fun testSetContactWithCompletionListener_delegatesToMobileEngageOnly_whenBothFeaturesEnabled() {
setup(mobileEngageAndPredictConfig)

setContact(CONTACT_FIELD_ID, CONTACT_FIELD_VALUE, completionListener)

runBlockingOnCoreSdkThread {
verify(mockPredictRestricted).setContact(CONTACT_FIELD_ID, CONTACT_FIELD_VALUE, null)
verify(mockMobileEngageApi).setContact(
CONTACT_FIELD_ID,
CONTACT_FIELD_VALUE,
completionListener
)
}
verifyNoInteractions(mockPredictRestricted)
}

@Test
Expand All @@ -786,20 +788,19 @@ class EmarsysTest : AnnotationSpec() {
}

@Test
fun testClearContactWithCompletionListener_delegatesToPredictInternal_whenPredictIsEnabled() {
fun testClearContactWithCompletionListener_delegatesToPredictInternal_whenOnlyPredictIsEnabled() {
setup(predictConfig)

clearContact(completionListener)
runBlockingOnCoreSdkThread()

runBlockingOnCoreSdkThread {
verifyNoInteractions(mockMobileEngageApi)
verify(mockPredictRestricted).clearContact()
verify(mockPredictRestricted).clearPredictOnlyContact(completionListener)
}
}

@Test
fun testClearContactWithCompletionListener_delegatesToMobileApi_whenMobileEngageIsEnabled() {
fun testClearContactWithCompletionListener_delegatesToMobileApi_whenOnlyMobileEngageIsEnabled() {
setup(mobileEngageConfig)

clearContact(completionListener)
Expand All @@ -810,36 +811,16 @@ class EmarsysTest : AnnotationSpec() {
}
}

@Test
fun testClearContactWithCompletionListener_doNotDelegatesToPredictInternal_whenPredictIsDisabled() {
setup(mobileEngageConfig)

clearContact(completionListener)
runBlockingOnCoreSdkThread {
verifyNoInteractions(mockPredictRestricted)
}
}

@Test
fun testClearContactWithCompletionListener_doNotDelegatesToMobileEngageApi_whenMobileEngageIsDisabled() {
setup(predictConfig)

clearContact(completionListener)

verifyNoInteractions(mockMobileEngageApi)
}

@Test
fun testClearContactWithCompletionListener_delegatesToInternals_whenBothEnabled() {
setup(mobileEngageAndPredictConfig)

clearContact(completionListener)

runBlockingOnCoreSdkThread {
verify(mockMobileEngageApi).clearContact(completionListener)
verify(mockPredictRestricted).clearContact()
}

verify(mockMobileEngageApi).clearContact(completionListener)
}

@Test
Expand All @@ -851,6 +832,7 @@ class EmarsysTest : AnnotationSpec() {
verifyNoInteractions(mockPredictRestricted)
}
verify(mockLoggingMobileEngageApi).clearContact(completionListener)
verify(mockLoggingPredictRestricted).clearContact()
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ import com.emarsys.predict.PredictApi
import com.emarsys.predict.PredictInternal
import com.emarsys.predict.PredictRestrictedApi
import com.emarsys.predict.provider.PredictRequestModelBuilderProvider
import com.emarsys.predict.request.PredictMultiIdRequestModelFactory
import com.emarsys.predict.request.PredictRequestContext
import com.emarsys.push.PushApi
import com.google.android.gms.location.FusedLocationProviderClient
Expand Down Expand Up @@ -200,5 +201,6 @@ class FakeDependencyContainer(
override val jsCommandFactoryProvider: JSCommandFactoryProvider = mock(),
override val jsOnCloseListener: OnCloseListener = mock(),
override val jsOnAppEventListener: OnAppEventListener = mock(),
override val remoteMessageMapperFactory: RemoteMessageMapperFactory = mock()
override val remoteMessageMapperFactory: RemoteMessageMapperFactory = mock(),
override val predictMultiIdRequestModelFactory: PredictMultiIdRequestModelFactory = mock(),
) : EmarsysComponent
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.emarsys.predict


import com.emarsys.core.api.result.CompletionListener
import com.emarsys.di.FakeDependencyContainer
import com.emarsys.di.emarsys
import com.emarsys.di.setupEmarsysComponent
Expand Down Expand Up @@ -52,4 +53,11 @@ class PredictRestrictedTest : AnnotationSpec() {
predictRestricted.clearContact()
Mockito.verify(mockPredictInternal).clearContact()
}

@Test
fun testPredict_clearPredictOnlyContact_delegatesTo_Predict_Internal() {
val mockCompletionListener = mock<CompletionListener>()
predictRestricted.clearPredictOnlyContact(mockCompletionListener)
Mockito.verify(mockPredictInternal).clearPredictOnlyContact(mockCompletionListener)
}
}
104 changes: 81 additions & 23 deletions emarsys-sdk/src/main/java/com/emarsys/Emarsys.kt
Original file line number Diff line number Diff line change
Expand Up @@ -132,35 +132,79 @@ object Emarsys {
contactFieldValue: String,
completionListener: CompletionListener? = null
) {
if (FeatureRegistry.isFeatureEnabled(MOBILE_ENGAGE)
|| (!FeatureRegistry.isFeatureEnabled(MOBILE_ENGAGE)
&& !FeatureRegistry.isFeatureEnabled(PREDICT))
) {
EmarsysDependencyInjection.mobileEngageApi()
.proxyApi(mobileEngage().concurrentHandlerHolder)
.setContact(contactFieldId, contactFieldValue, completionListener)
} else if (FeatureRegistry.isFeatureEnabled(PREDICT)) {
EmarsysDependencyInjection.predictRestrictedApi()
.proxyApi(mobileEngage().concurrentHandlerHolder)
.setContact(contactFieldId, contactFieldValue, completionListener)
}
executeMobileEngageOrPredictOnlyLogic(
mobileEngageLogic = {
setMobileEngageContact(
contactFieldId,
contactFieldValue,
completionListener
)
},
predictOnlyLogic = {
setPredictOnlyContact(
contactFieldId,
contactFieldValue,
completionListener
)
}
)
}

private fun setMobileEngageContact(
contactFieldId: Int,
contactFieldValue: String,
completionListener: CompletionListener?
) {
EmarsysDependencyInjection.mobileEngageApi()
.proxyApi(mobileEngage().concurrentHandlerHolder)
.setContact(contactFieldId, contactFieldValue, completionListener)
}

private fun setPredictOnlyContact(
contactFieldId: Int,
contactFieldValue: String,
completionListener: CompletionListener?
) {
EmarsysDependencyInjection.predictRestrictedApi()
.proxyApi(mobileEngage().concurrentHandlerHolder)
.setContact(contactFieldId, contactFieldValue, completionListener)
}

@JvmStatic
@JvmOverloads
fun clearContact(completionListener: CompletionListener? = null) {
executeMobileEngageOrPredictOnlyLogic(
mobileEngageLogic = { clearMobileEngageContact(completionListener) },
predictOnlyLogic = { clearPredictOnlyContact(completionListener) }
)
}

private fun clearMobileEngageContact(completionListener: CompletionListener?) {
EmarsysDependencyInjection.mobileEngageApi()
.proxyApi(mobileEngage().concurrentHandlerHolder)
.clearContact(completionListener)
EmarsysDependencyInjection.predictRestrictedApi()
.proxyApi(mobileEngage().concurrentHandlerHolder)
.clearContact()
}

private fun clearPredictOnlyContact(completionListener: CompletionListener?) {
EmarsysDependencyInjection.predictRestrictedApi()
.proxyApi(mobileEngage().concurrentHandlerHolder)
.clearPredictOnlyContact(completionListener)
}

private fun executeMobileEngageOrPredictOnlyLogic(
mobileEngageLogic: () -> Unit,
predictOnlyLogic: () -> Unit
) {
if (FeatureRegistry.isFeatureEnabled(MOBILE_ENGAGE)
|| (!FeatureRegistry.isFeatureEnabled(MOBILE_ENGAGE)
&& !FeatureRegistry.isFeatureEnabled(PREDICT))
) {
EmarsysDependencyInjection.mobileEngageApi()
.proxyApi(mobileEngage().concurrentHandlerHolder)
.clearContact(completionListener)
}
if (FeatureRegistry.isFeatureEnabled(PREDICT)) {
EmarsysDependencyInjection.predictRestrictedApi()
.proxyApi(mobileEngage().concurrentHandlerHolder)
.clearContact()
mobileEngageLogic()
} else if (FeatureRegistry.isFeatureEnabled(PREDICT)) {
predictOnlyLogic()
}
}

Expand Down Expand Up @@ -233,17 +277,31 @@ object Emarsys {
}

private fun refreshRemoteConfig(applicationCode: String?) {
if (!listOf("", "null", "nil", "0").contains(applicationCode?.lowercase()) && applicationCode != null) {
if (!listOf(
"",
"null",
"nil",
"0"
).contains(applicationCode?.lowercase()) && applicationCode != null
) {
emarsys().configInternal.proxyApi(mobileEngage().concurrentHandlerHolder)
.refreshRemoteConfig {
it?.let {
val logEntry = StatusLog(Emarsys::class.java, "refreshRemoteConfig", mapOf("applicationCode" to applicationCode, "exception" to it.message))
val logEntry = StatusLog(
Emarsys::class.java,
"refreshRemoteConfig",
mapOf("applicationCode" to applicationCode, "exception" to it.message)
)
Logger.log(logEntry)
}
}
} else {
Log.w("EmarsysSdk", "Invalid applicationCode: $applicationCode")
val logEntry = StatusLog(Emarsys::class.java, "refreshRemoteConfig", mapOf("applicationCode" to applicationCode))
val logEntry = StatusLog(
Emarsys::class.java,
"refreshRemoteConfig",
mapOf("applicationCode" to applicationCode)
)
Logger.log(logEntry)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ class PredictRestricted(private val loggingInstance: Boolean = false) : PredictR
.setContact(contactFieldId, contactFieldValue, completionListener)
}

override fun clearPredictOnlyContact(completionListener: CompletionListener?) {
(if (loggingInstance) predict().loggingPredictInternal else predict().predictInternal)
.clearPredictOnlyContact(completionListener)
}

override fun clearContact() {
(if (loggingInstance) predict().loggingPredictInternal else predict().predictInternal)
.clearContact()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@ import com.emarsys.core.api.result.CompletionListener
interface PredictRestrictedApi {

fun setContact(contactFieldId: Int, contactFieldValue: String, completionListener: CompletionListener?)

fun clearPredictOnlyContact(completionListener: CompletionListener?)

fun clearContact()
}
Original file line number Diff line number Diff line change
Expand Up @@ -205,15 +205,54 @@ class DefaultPredictInternalTest : AnnotationSpec() {
}

@Test
fun testClearContact_shouldRemove_contactIdFromKeyValueStore() {
fun testClearContact_shouldRemove_visitorIdFromKeyValueStore() {
predictInternal.clearContact()

verify(mockKeyValueStore).remove("predict_contact_id")
verify(mockKeyValueStore).remove("predict_visitor_id")
}

@Test
fun testClearContact_shouldRemove_visitorIdFromKeyValueStore() {
predictInternal.clearContact()
fun testClearPredictOnlyContact_shouldCall_requestManager() {
whenever(
mockPredictMultiIdRequestModelFactory.createClearContactRequestModel()
).thenReturn(mockRequestModel)

predictInternal.clearPredictOnlyContact(mockCompletionListener)

verify(mockRequestManager).submit(mockRequestModel, mockCompletionListener)
}

@Test
fun testClearPredictOnlyContact_shouldCall_completionListener_whenExceptionIsThrown_andShouldNotRemoveVisitorId() {
val testException = IllegalArgumentException()
whenever(
mockPredictMultiIdRequestModelFactory.createClearContactRequestModel()
).thenThrow(testException)

predictInternal.clearPredictOnlyContact(mockCompletionListener)

verify(mockCompletionListener).onCompleted(testException)
verifyNoInteractions(mockRequestManager)
verifyNoInteractions(mockKeyValueStore)
}

@Test
fun testClearPredictOnlyContact_shouldNotCrash_withException_whenCompletionListenerIsNull_andShouldNotRemoveVisitorId() {
val testException = IllegalArgumentException()
whenever(
mockPredictMultiIdRequestModelFactory.createClearContactRequestModel()
).thenThrow(testException)

predictInternal.clearPredictOnlyContact(null)

verifyNoInteractions(mockRequestManager)
verifyNoInteractions(mockKeyValueStore)
verifyNoInteractions(mockCompletionListener)
}

@Test
fun testClearPredictOnlyContact_shouldRemove_visitorIdFromKeyValueStore() {
predictInternal.clearPredictOnlyContact(mockCompletionListener)

verify(mockKeyValueStore).remove("predict_visitor_id")
}
Expand Down
Loading

0 comments on commit ab0268d

Please sign in to comment.