Skip to content

Commit

Permalink
feat(contact): prevent sending duplicate setContact requests
Browse files Browse the repository at this point in the history
SUITEDEV-36670

Co-authored-by: LordAndras <[email protected]>
Co-authored-by: matusekma <[email protected]>
  • Loading branch information
3 people committed Sep 30, 2024
1 parent a34d79d commit dd1716a
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import com.emarsys.mobileengage.session.MobileEngageSession
import com.emarsys.mobileengage.session.SessionIdHolder

import com.emarsys.testUtil.AnnotationSpec
import io.kotest.matchers.shouldBe
import org.mockito.kotlin.any
import org.mockito.kotlin.doAnswer
import org.mockito.kotlin.eq
Expand All @@ -23,6 +24,7 @@ import org.mockito.kotlin.mock
import org.mockito.kotlin.spy
import org.mockito.kotlin.times
import org.mockito.kotlin.verify
import org.mockito.kotlin.verifyNoInteractions
import org.mockito.kotlin.verifyNoMoreInteractions
import org.mockito.kotlin.whenever
import java.util.concurrent.CountDownLatch
Expand Down Expand Up @@ -128,43 +130,62 @@ class DefaultMobileEngageInternalTest : AnnotationSpec() {

mockRequestModelFactory = mock {
on { createSetContactRequest(CONTACT_FIELD_ID, null) }.thenReturn(
mockRequestModelWithNullContactFieldValue
mockRequestModelWithNullContactFieldValue
)
on { createSetContactRequest(null, null) }.thenReturn(
mockRequestModelWithNullContactFieldValueAndNullContactFieldId
mockRequestModelWithNullContactFieldValueAndNullContactFieldId
)
on { createSetContactRequest(CONTACT_FIELD_ID, CONTACT_FIELD_VALUE) }.thenReturn(
mockRequestModel
mockRequestModel
)
on { createSetPushTokenRequest(PUSH_TOKEN) }.thenReturn(mockRequestModel)
on { createCustomEventRequest(EVENT_NAME, EVENT_ATTRIBUTES) }.thenReturn(mockRequestModel)
on { createCustomEventRequest(EVENT_NAME, EVENT_ATTRIBUTES) }.thenReturn(
mockRequestModel
)
on { createTrackDeviceInfoRequest() }.thenReturn(mockRequestModel)
on { createInternalCustomEventRequest(EVENT_NAME, EVENT_ATTRIBUTES) }.thenReturn(mockRequestModel)
on { createInternalCustomEventRequest(EVENT_NAME, EVENT_ATTRIBUTES) }.thenReturn(
mockRequestModel
)
on { createRemovePushTokenRequest() }.thenReturn(mockRequestModel)
}

mockCompletionListener = mock()

mobileEngageInternal = DefaultMobileEngageInternal(
mockRequestManager,
mockRequestModelFactory,
mockRequestContext,
mockSession,
mockSessionIdHolder
mockRequestManager,
mockRequestModelFactory,
mockRequestContext,
mockSession,
mockSessionIdHolder
)
}

@Test
fun testSetContact() {
fun testSetContact_shouldCallRequestManager_whenNewSessionIsNeeded() {
whenever(mockRequestContext.contactFieldValue).thenReturn(OTHER_CONTACT_FIELD_VALUE)

mobileEngageInternal.setContact(
CONTACT_FIELD_ID,
CONTACT_FIELD_VALUE,
mockCompletionListener
CONTACT_FIELD_ID,
CONTACT_FIELD_VALUE,
mockCompletionListener
)

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

@Test
fun testSetContact_shouldNotCallRequestManager_whenSessionIsNotChanging() {
whenever(mockRequestContext.contactFieldValue).thenReturn(CONTACT_FIELD_VALUE)

mobileEngageInternal.setContact(
CONTACT_FIELD_ID,
CONTACT_FIELD_VALUE,
mockCompletionListener
)

verifyNoInteractions(mockRequestManager)
}

@Test
fun testSetAuthenticatedContact_completionListener_canBeNull() {
mobileEngageInternal.setAuthenticatedContact(CONTACT_FIELD_ID, OPEN_ID_TOKEN, null)
Expand Down Expand Up @@ -257,10 +278,15 @@ class DefaultMobileEngageInternalTest : AnnotationSpec() {
verify(mockSession).endSession(any())
verify(mobileEngageInternal).doClearContact(any())
verify(mobileEngageInternal).resetContext()
verify(mobileEngageInternal).doSetContact(isNull(), isNull(), isNull(), any<CompletionListener>())
verify(mobileEngageInternal).doSetContact(
isNull(),
isNull(),
isNull(),
any<CompletionListener>()
)
verify(mockRequestManager).submit(
eq(mockRequestModelWithNullContactFieldValueAndNullContactFieldId),
any()
eq(mockRequestModelWithNullContactFieldValueAndNullContactFieldId),
any()
)
verifyNoMoreInteractions(mobileEngageInternal)
verify(mockSession).startSession(any())
Expand All @@ -270,11 +296,28 @@ class DefaultMobileEngageInternalTest : AnnotationSpec() {
@Test
fun testClearContact_shouldEndCurrentSession() {
whenever(mockSessionIdHolder.sessionId).thenReturn("testSessionId")
whenever(mockRequestContext.hasContactIdentification()).thenReturn(true)
whenever(mockRequestContext.contactTokenStorage.get()).thenReturn("contactToken")
mobileEngageInternal.clearContact(null)

verify(mockSession).endSession(any())
}

@Test
fun testClearContact_shouldCallOnCompleted_whenContactWasAlreadyAnonymous() {
whenever(mockRequestContext.hasContactIdentification()).thenReturn(false)
whenever(mockRequestContext.contactTokenStorage.get()).thenReturn("contactToken")
whenever(mockSessionIdHolder.sessionId).thenReturn("testSessionId")

var result = false
mobileEngageInternal.clearContact {
result = true
}
result shouldBe true
verifyNoInteractions(mockSession)
verifyNoInteractions(mockRequestManager)
}

@Test
fun testClearContact_shouldNotCallEndCurrentSession_whenThereWasNoSessionInProgress() {
whenever(mockSessionIdHolder.sessionId).thenReturn(null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ class DefaultMobileEngageInternal(
completionListener: CompletionListener?
) {
val shouldRestartSession = requestContext.contactFieldValue != contactFieldValue
doSetContact(contactFieldId, contactFieldValue, completionListener = completionListener)

if (shouldRestartSession) {
doSetContact(contactFieldId, contactFieldValue, completionListener = completionListener)
if (!sessionIdHolder.sessionId.isNullOrEmpty()) {
session.endSession {
if (it != null) {
Expand Down Expand Up @@ -85,18 +85,26 @@ class DefaultMobileEngageInternal(
}

override fun clearContact(completionListener: CompletionListener?) {
if (!sessionIdHolder.sessionId.isNullOrEmpty()) {
session.endSession {
if (it != null) {
Logger.error(CrashLog(it))
if (hasContactToken() && !requestContext.hasContactIdentification()) {
completionListener?.onCompleted(null)
} else {
if (!sessionIdHolder.sessionId.isNullOrEmpty()) {
session.endSession {
if (it != null) {
Logger.error(CrashLog(it))
}
doClearContact(completionListener)
}
} else {
doClearContact(completionListener)
}
} else {
doClearContact(completionListener)
}
}

private fun hasContactToken(): Boolean {
return !requestContext.contactTokenStorage.get().isNullOrEmpty()
}

internal fun doClearContact(completionListener: CompletionListener?) {
resetContext()

Expand Down

0 comments on commit dd1716a

Please sign in to comment.