From 8a1703f537b31a4562250224d9d0093045f4dfa6 Mon Sep 17 00:00:00 2001 From: Thomson Thomas Date: Thu, 10 Sep 2026 15:01:29 -0400 Subject: [PATCH 1/3] feat(rokt): add Rokt session handoff APIs Expose Rokt session handoff for native and non-native integrations. Add setSession/getSession APIs and delegate them through the Rokt kit to the supported native SDK. #agentic --- .../kotlin/com/mparticle/rokt/RoktSession.kt | 17 ++++++ .../main/kotlin/com/mparticle/kits/Rokt.kt | 37 +++++++++++++ .../main/kotlin/com/mparticle/kits/RoktKit.kt | 47 ++++++++++++++++ .../com/mparticle/kits/RoktKitBridge.kt | 5 ++ .../kotlin/com/mparticle/kits/RoktKitTests.kt | 55 +++++++++++++++++++ .../kotlin/com/mparticle/kits/RoktTest.kt | 34 ++++++++++++ 6 files changed, 195 insertions(+) create mode 100644 android-core/src/main/kotlin/com/mparticle/rokt/RoktSession.kt diff --git a/android-core/src/main/kotlin/com/mparticle/rokt/RoktSession.kt b/android-core/src/main/kotlin/com/mparticle/rokt/RoktSession.kt new file mode 100644 index 000000000..2d273ae3d --- /dev/null +++ b/android-core/src/main/kotlin/com/mparticle/rokt/RoktSession.kt @@ -0,0 +1,17 @@ +package com.mparticle.rokt + +/** + * A Rokt session suitable for handoff between native and non-native integrations. + * + * Includes the session id plus an optional short-lived session token used to authorize offers and + * events. Mirrors Web launcher options: `sessionId` is required for handoff; `sessionToken` is + * optional (Bearer continuity when present). + * + * @param sessionId The Rokt session identifier. Must be non-empty when passed to [com.mparticle.kits.Rokt.setSession]. + * @param sessionToken Optional JWT session token used as a Bearer credential for offers and events. + * When omitted or blank, [com.mparticle.kits.Rokt.setSession] applies the session id only (same as + * Web `sessionId` without `sessionToken`). + * @param expiresAt Optional Unix epoch milliseconds when [sessionToken] expires (matches server + * `expires_at` when known). Ignored when [sessionToken] is absent. + */ +data class RoktSession @JvmOverloads constructor(val sessionId: String, val sessionToken: String? = null, val expiresAt: Long? = null) diff --git a/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/Rokt.kt b/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/Rokt.kt index 81b7e73fc..0ab6d474b 100644 --- a/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/Rokt.kt +++ b/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/Rokt.kt @@ -4,6 +4,7 @@ import android.graphics.Typeface import com.mparticle.MParticle import com.mparticle.internal.KitManager import com.mparticle.internal.Logger +import com.mparticle.rokt.RoktSession import com.rokt.roktsdk.PlacementOptions import com.rokt.roktsdk.RoktConfig import com.rokt.roktsdk.RoktEvent @@ -147,6 +148,37 @@ class Rokt internal constructor(private val mKitManager: KitManager) { } } + /** + * Set the session to use for the next execute call. + * + * Use this when you have a session from a non-native integration (e.g. WebView) + * and want the session to stay consistent across integrations. Call before the next + * selectPlacements. + * + * Matches Web launcher options: pass [RoktSession.sessionId] with optional + * [RoktSession.sessionToken]. When the token is present, offers/events can send + * `Authorization: Bearer`. When only the id is present, the id is applied without Bearer + * seeding. Empty `sessionId` (or token without id) is ignored. + * + * @param session The session id and optional JWT session token (optional expiry). + */ + fun setSession(session: RoktSession) { + if (isEnabled()) { + resolveRoktKit()?.second?.setSession(session) + } + } + + /** + * Get the current session (id + token) for use within a non-native integration e.g. WebView. + * + * @return The session, or null if disabled, no session is present, or the token has expired. + */ + fun getSession(): RoktSession? = if (isEnabled()) { + resolveRoktKit()?.second?.getSession() + } else { + null + } + /** * Set the session id to use for the next execute call. * @@ -154,9 +186,11 @@ class Rokt internal constructor(private val mKitManager: KitManager) { * e.g. WebView, and you want the session to be consistent across integrations. * * **Note:** Empty strings are ignored and will not update the session. + * Prefer [setSession] so the session token is also applied for offers and events. * * @param sessionId The session id to be set. Must be a non-empty string. */ + @Deprecated("Use setSession to set session id and session token.") fun setSessionId(sessionId: String) { MParticle.logRoktApiUsage("ROKT_SET_SESSION_ID") if (isEnabled()) { @@ -167,8 +201,11 @@ class Rokt internal constructor(private val mKitManager: KitManager) { /** * Get the session id to use within a non-native integration e.g. WebView. * + * Prefer [getSession] to also read the session token. + * * @return The session id or null if no session is present or SDK is not initialized. */ + @Deprecated("Use getSession to read session id and session token.") fun getSessionId(): String? { MParticle.logRoktApiUsage("ROKT_GET_SESSION_ID") return if (isEnabled()) { diff --git a/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktKit.kt b/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktKit.kt index 81aafe141..bc3b68c00 100644 --- a/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktKit.kt +++ b/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktKit.kt @@ -19,6 +19,7 @@ import com.mparticle.kits.KitIntegration.CommerceListener import com.mparticle.kits.KitIntegration.IdentityListener import com.mparticle.kits.KitIntegration.RoktListener import com.mparticle.rokt.RoktApiDiagnosticsForwarder +import com.mparticle.rokt.RoktSession import com.rokt.roktsdk.PlacementOptions import com.rokt.roktsdk.Rokt import com.rokt.roktsdk.Rokt.SdkFrameworkType.Android @@ -39,6 +40,7 @@ import kotlinx.coroutines.launch import java.lang.ref.WeakReference import java.math.BigDecimal import java.net.URL +import com.rokt.roktsdk.RoktSession as NativeRoktSession const val ROKT_ATTRIBUTE_SANDBOX_MODE: String = "sandbox" @@ -337,13 +339,55 @@ class RoktKit : Rokt.close() } + /** + * Set the session to use for the next execute call. + * + * Matches Web launcher options: non-empty [RoktSession.sessionId] + [RoktSession.sessionToken] + * seeds Bearer continuity via [Rokt.setSession]; id-only falls back to [Rokt.setSessionId]. + * Token without a non-empty id is ignored. Requires a Rokt Android SDK that exposes + * [Rokt.setSession] / [NativeRoktSession] (Brandon `feat/Update-To-Session-Token` and successors). + */ + override fun setSession(session: RoktSession) { + val sessionId = session.sessionId.trim() + if (sessionId.isEmpty()) { + return + } + val sessionToken = session.sessionToken?.trim().orEmpty() + if (sessionToken.isNotEmpty()) { + Rokt.setSession( + NativeRoktSession( + sessionId = sessionId, + sessionToken = sessionToken, + expiresAt = session.expiresAt, + ), + ) + } else { + Rokt.setSessionId(sessionId) + } + } + + /** + * Get the current session (id + token) for WebView / non-native handoff. + */ + override fun getSession(): RoktSession? { + val session = Rokt.getSession() ?: return null + return RoktSession( + sessionId = session.sessionId, + sessionToken = session.sessionToken, + expiresAt = session.expiresAt, + ) + } + /** * Set the session id to use for the next execute call. * This is useful for cases where you have a session id from a non-native integration, * e.g. WebView, and you want the session to be consistent across integrations. * + * Prefer [setSession] so the session token is also applied for offers and events. + * * @param sessionId The session id to be set. Must be a non-empty string. */ + @Deprecated("Use setSession to set session id and session token.") override fun setSessionId(sessionId: String) { Rokt.setSessionId(sessionId) } @@ -351,8 +395,11 @@ class RoktKit : /** * Get the session id to use within a non-native integration e.g. WebView. * + * Prefer [getSession] to also read the session token. + * * @return The session id or null if no session is present. */ + @Deprecated("Use getSession to read session id and session token.") override fun getSessionId(): String? = Rokt.getSessionId() override fun enrichAttributes(attributes: MutableMap, user: FilteredMParticleUser?) { diff --git a/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktKitBridge.kt b/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktKitBridge.kt index 7a36b0230..945381b07 100644 --- a/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktKitBridge.kt +++ b/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktKitBridge.kt @@ -1,6 +1,7 @@ package com.mparticle.kits import android.graphics.Typeface +import com.mparticle.rokt.RoktSession import com.rokt.roktsdk.PlacementOptions import com.rokt.roktsdk.RoktConfig import com.rokt.roktsdk.RoktEvent @@ -36,6 +37,10 @@ internal interface RoktKitBridge { fun close() + fun setSession(session: RoktSession) + + fun getSession(): RoktSession? + fun setSessionId(sessionId: String) fun getSessionId(): String? diff --git a/kits/rokt/rokt/src/test/kotlin/com/mparticle/kits/RoktKitTests.kt b/kits/rokt/rokt/src/test/kotlin/com/mparticle/kits/RoktKitTests.kt index 64b34db54..dc2f6d595 100644 --- a/kits/rokt/rokt/src/test/kotlin/com/mparticle/kits/RoktKitTests.kt +++ b/kits/rokt/rokt/src/test/kotlin/com/mparticle/kits/RoktKitTests.kt @@ -1499,6 +1499,61 @@ class RoktKitTests { unmockkObject(Rokt) } + @Test + fun testSetSession_delegatesToRoktSdk() { + mockkObject(Rokt) + every { Rokt.setSession(any()) } just runs + + roktKit.setSession(com.mparticle.rokt.RoktSession("sid", "jwt", 123L)) + + verify { + Rokt.setSession( + match { + it.sessionId == "sid" && it.sessionToken == "jwt" && it.expiresAt == 123L + }, + ) + } + verify(exactly = 0) { Rokt.setSessionId(any()) } + unmockkObject(Rokt) + } + + @Test + fun testSetSession_idOnlyFallsBackToSetSessionId() { + mockkObject(Rokt) + every { Rokt.setSessionId(any()) } just runs + + roktKit.setSession(com.mparticle.rokt.RoktSession("sid")) + + verify { Rokt.setSessionId("sid") } + verify(exactly = 0) { Rokt.setSession(any()) } + unmockkObject(Rokt) + } + + @Test + fun testSetSession_blankIdIsIgnored() { + mockkObject(Rokt) + + roktKit.setSession(com.mparticle.rokt.RoktSession(" ", "jwt")) + + verify(exactly = 0) { Rokt.setSession(any()) } + verify(exactly = 0) { Rokt.setSessionId(any()) } + unmockkObject(Rokt) + } + + @Test + fun testGetSession_mapsValueFromRoktSdk() { + mockkObject(Rokt) + every { Rokt.getSession() } returns com.rokt.roktsdk.RoktSession("sid", "jwt", 456L) + + val result = roktKit.getSession() + + assertEquals("sid", result?.sessionId) + assertEquals("jwt", result?.sessionToken) + assertEquals(456L, result?.expiresAt) + verify { Rokt.getSession() } + unmockkObject(Rokt) + } + @Test fun testSetSessionId_delegatesToRoktSdk() { mockkObject(Rokt) diff --git a/kits/rokt/rokt/src/test/kotlin/com/mparticle/kits/RoktTest.kt b/kits/rokt/rokt/src/test/kotlin/com/mparticle/kits/RoktTest.kt index 88af7f60c..3aac2ea33 100644 --- a/kits/rokt/rokt/src/test/kotlin/com/mparticle/kits/RoktTest.kt +++ b/kits/rokt/rokt/src/test/kotlin/com/mparticle/kits/RoktTest.kt @@ -296,6 +296,40 @@ class RoktTest { verify(roktListener, never()).selectShoppableAds(any(), any(), any(), any()) } + @Test + fun testSetSession_whenEnabled_delegatesToKitManager() { + configManager.enabled = true + val session = com.mparticle.rokt.RoktSession("sid", "jwt", 123L) + rokt.setSession(session) + verify(roktListener).setSession(session) + } + + @Test + fun testSetSession_whenDisabled_doesNotCallKitManager() { + configManager.enabled = false + val session = com.mparticle.rokt.RoktSession("sid", "jwt", 123L) + rokt.setSession(session) + verify(roktListener, never()).setSession(any()) + } + + @Test + fun testGetSession_whenEnabled_delegatesToKitManager() { + configManager.enabled = true + val expected = com.mparticle.rokt.RoktSession("sid", "jwt", 123L) + `when`(roktListener.getSession()).thenReturn(expected) + val result = rokt.getSession() + verify(roktListener).getSession() + assertEquals(expected, result) + } + + @Test + fun testGetSession_whenDisabled_returnsNull() { + configManager.enabled = false + val result = rokt.getSession() + verify(roktListener, never()).getSession() + assertNull(result) + } + @Test fun testSetSessionId_whenEnabled_delegatesToKitManager() { configManager.enabled = true From c1c3da16f5b3e8c19c6e17c1d8f4e02806b4d3b4 Mon Sep 17 00:00:00 2001 From: Jaissica Date: Wed, 19 Aug 2026 11:00:14 -0400 Subject: [PATCH 2/3] docs(rokt): drop internal branch reference from setSession kdoc --- kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktKit.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktKit.kt b/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktKit.kt index bc3b68c00..49a51d429 100644 --- a/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktKit.kt +++ b/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktKit.kt @@ -344,8 +344,8 @@ class RoktKit : * * Matches Web launcher options: non-empty [RoktSession.sessionId] + [RoktSession.sessionToken] * seeds Bearer continuity via [Rokt.setSession]; id-only falls back to [Rokt.setSessionId]. - * Token without a non-empty id is ignored. Requires a Rokt Android SDK that exposes - * [Rokt.setSession] / [NativeRoktSession] (Brandon `feat/Update-To-Session-Token` and successors). + * Token without a non-empty id is ignored. Requires a Rokt Android SDK version that exposes + * [Rokt.setSession] / [NativeRoktSession]. */ override fun setSession(session: RoktSession) { val sessionId = session.sessionId.trim() From 0a60574c8a2f7367ecaf2c05f7cc73159fea6e63 Mon Sep 17 00:00:00 2001 From: Thomson Thomas Date: Thu, 10 Sep 2026 15:20:16 -0400 Subject: [PATCH 3/3] fix(rokt): require tokens for session handoff #agentic --- .../kotlin/com/mparticle/rokt/RoktSession.kt | 14 +++----- .../mparticle/rokt/RoktSessionJavaTest.java | 21 ++++++++++++ kits/rokt/rokt/README.md | 33 +++++++++++++++++++ .../main/kotlin/com/mparticle/kits/Rokt.kt | 21 +++++++----- .../main/kotlin/com/mparticle/kits/RoktKit.kt | 28 +++++++--------- .../kotlin/com/mparticle/kits/RoktKitTests.kt | 20 ++++++++--- .../kotlin/com/mparticle/kits/RoktTest.kt | 20 +++++++++++ 7 files changed, 118 insertions(+), 39 deletions(-) create mode 100644 android-core/src/test/java/com/mparticle/rokt/RoktSessionJavaTest.java diff --git a/android-core/src/main/kotlin/com/mparticle/rokt/RoktSession.kt b/android-core/src/main/kotlin/com/mparticle/rokt/RoktSession.kt index 2d273ae3d..7276bddd0 100644 --- a/android-core/src/main/kotlin/com/mparticle/rokt/RoktSession.kt +++ b/android-core/src/main/kotlin/com/mparticle/rokt/RoktSession.kt @@ -3,15 +3,11 @@ package com.mparticle.rokt /** * A Rokt session suitable for handoff between native and non-native integrations. * - * Includes the session id plus an optional short-lived session token used to authorize offers and - * events. Mirrors Web launcher options: `sessionId` is required for handoff; `sessionToken` is - * optional (Bearer continuity when present). + * Includes the session id and short-lived session token used to authorize offers and events. * * @param sessionId The Rokt session identifier. Must be non-empty when passed to [com.mparticle.kits.Rokt.setSession]. - * @param sessionToken Optional JWT session token used as a Bearer credential for offers and events. - * When omitted or blank, [com.mparticle.kits.Rokt.setSession] applies the session id only (same as - * Web `sessionId` without `sessionToken`). - * @param expiresAt Optional Unix epoch milliseconds when [sessionToken] expires (matches server - * `expires_at` when known). Ignored when [sessionToken] is absent. + * @param sessionToken The Rokt session token. Must be non-empty when passed to [com.mparticle.kits.Rokt.setSession]. + * @param expiresAt Optional Unix epoch milliseconds when [sessionToken] expires. The underlying Rokt SDK applies its default expiry when + * this value is omitted or already in the past. */ -data class RoktSession @JvmOverloads constructor(val sessionId: String, val sessionToken: String? = null, val expiresAt: Long? = null) +data class RoktSession @JvmOverloads constructor(val sessionId: String, val sessionToken: String, val expiresAt: Long? = null) diff --git a/android-core/src/test/java/com/mparticle/rokt/RoktSessionJavaTest.java b/android-core/src/test/java/com/mparticle/rokt/RoktSessionJavaTest.java new file mode 100644 index 000000000..f2274f215 --- /dev/null +++ b/android-core/src/test/java/com/mparticle/rokt/RoktSessionJavaTest.java @@ -0,0 +1,21 @@ +package com.mparticle.rokt; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +import java.util.Arrays; +import org.junit.Test; + +public class RoktSessionJavaTest { + @Test + public void supportsRequiredTokenAndOptionalExpiryConstructors() { + RoktSession sessionWithoutExpiry = new RoktSession("session-id", "session-token"); + RoktSession sessionWithExpiry = new RoktSession("session-id", "session-token", 123L); + + assertEquals("session-token", sessionWithoutExpiry.getSessionToken()); + assertEquals(Long.valueOf(123L), sessionWithExpiry.getExpiresAt()); + assertFalse( + Arrays.stream(RoktSession.class.getConstructors()) + .anyMatch(constructor -> constructor.getParameterCount() == 1)); + } +} diff --git a/kits/rokt/rokt/README.md b/kits/rokt/rokt/README.md index 5e66f1f33..5fa6aff15 100644 --- a/kits/rokt/rokt/README.md +++ b/kits/rokt/rokt/README.md @@ -35,6 +35,39 @@ Java consumers can use the kit helper: MParticleRokt.Rokt().selectPlacements("RoktExperience", attributes); ``` +### Session handoff + +Use a token-backed session to preserve Rokt continuity when moving between native and non-native experiences. Both the session ID and token are required; expiry is optional. + +Kotlin: + +```kotlin +import com.mparticle.MParticle +import com.mparticle.kits.rokt +import com.mparticle.rokt.RoktSession + +MParticle.getInstance()?.rokt?.setSession( + RoktSession( + sessionId = sessionId, + sessionToken = sessionToken, + expiresAt = expiresAt, + ), +) + +val currentSession = MParticle.getInstance()?.rokt?.getSession() +``` + +Java: + +```java +import com.mparticle.rokt.RoktSession; + +MParticleRokt.Rokt().setSession(new RoktSession(sessionId, sessionToken, expiresAt)); +RoktSession currentSession = MParticleRokt.Rokt().getSession(); +``` + +Pass `expiresAt` as Unix epoch milliseconds when the value is available, or use the two-argument constructor to omit it. When expiry is omitted or already in the past, Rokt Android SDK 6.1.1 applies its standard 30-minute session expiry. Blank session IDs or tokens are ignored. + ### Shoppable Ads Add the optional Rokt payment extension dependency in your app, then register the extension after mParticle starts. The Rokt kit reads `stripePublishableKey` from the mParticle dashboard configuration and forwards it to the Rokt SDK during registration. diff --git a/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/Rokt.kt b/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/Rokt.kt index 0ab6d474b..736a5d101 100644 --- a/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/Rokt.kt +++ b/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/Rokt.kt @@ -155,14 +155,14 @@ class Rokt internal constructor(private val mKitManager: KitManager) { * and want the session to stay consistent across integrations. Call before the next * selectPlacements. * - * Matches Web launcher options: pass [RoktSession.sessionId] with optional - * [RoktSession.sessionToken]. When the token is present, offers/events can send - * `Authorization: Bearer`. When only the id is present, the id is applied without Bearer - * seeding. Empty `sessionId` (or token without id) is ignored. + * Both [RoktSession.sessionId] and [RoktSession.sessionToken] must be non-empty. The optional + * [RoktSession.expiresAt] value is passed to the Rokt SDK, which applies its default expiry when + * the value is omitted or already in the past. * - * @param session The session id and optional JWT session token (optional expiry). + * @param session The session id, session token, and optional expiry. */ fun setSession(session: RoktSession) { + MParticle.logRoktApiUsage("ROKT_SET_SESSION") if (isEnabled()) { resolveRoktKit()?.second?.setSession(session) } @@ -173,10 +173,13 @@ class Rokt internal constructor(private val mKitManager: KitManager) { * * @return The session, or null if disabled, no session is present, or the token has expired. */ - fun getSession(): RoktSession? = if (isEnabled()) { - resolveRoktKit()?.second?.getSession() - } else { - null + fun getSession(): RoktSession? { + MParticle.logRoktApiUsage("ROKT_GET_SESSION") + return if (isEnabled()) { + resolveRoktKit()?.second?.getSession() + } else { + null + } } /** diff --git a/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktKit.kt b/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktKit.kt index 49a51d429..686684108 100644 --- a/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktKit.kt +++ b/kits/rokt/rokt/src/main/kotlin/com/mparticle/kits/RoktKit.kt @@ -342,28 +342,22 @@ class RoktKit : /** * Set the session to use for the next execute call. * - * Matches Web launcher options: non-empty [RoktSession.sessionId] + [RoktSession.sessionToken] - * seeds Bearer continuity via [Rokt.setSession]; id-only falls back to [Rokt.setSessionId]. - * Token without a non-empty id is ignored. Requires a Rokt Android SDK version that exposes - * [Rokt.setSession] / [NativeRoktSession]. + * Non-empty [RoktSession.sessionId] and [RoktSession.sessionToken] values seed session + * continuity through [Rokt.setSession]. Blank values are ignored. */ override fun setSession(session: RoktSession) { val sessionId = session.sessionId.trim() - if (sessionId.isEmpty()) { + val sessionToken = session.sessionToken.trim() + if (sessionId.isEmpty() || sessionToken.isEmpty()) { return } - val sessionToken = session.sessionToken?.trim().orEmpty() - if (sessionToken.isNotEmpty()) { - Rokt.setSession( - NativeRoktSession( - sessionId = sessionId, - sessionToken = sessionToken, - expiresAt = session.expiresAt, - ), - ) - } else { - Rokt.setSessionId(sessionId) - } + Rokt.setSession( + NativeRoktSession( + sessionId = sessionId, + sessionToken = sessionToken, + expiresAt = session.expiresAt, + ), + ) } /** diff --git a/kits/rokt/rokt/src/test/kotlin/com/mparticle/kits/RoktKitTests.kt b/kits/rokt/rokt/src/test/kotlin/com/mparticle/kits/RoktKitTests.kt index dc2f6d595..34d5cf7ec 100644 --- a/kits/rokt/rokt/src/test/kotlin/com/mparticle/kits/RoktKitTests.kt +++ b/kits/rokt/rokt/src/test/kotlin/com/mparticle/kits/RoktKitTests.kt @@ -42,6 +42,7 @@ import org.json.JSONArray import org.json.JSONObject import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse +import org.junit.Assert.assertNull import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test @@ -1518,14 +1519,13 @@ class RoktKitTests { } @Test - fun testSetSession_idOnlyFallsBackToSetSessionId() { + fun testSetSession_blankTokenIsIgnored() { mockkObject(Rokt) - every { Rokt.setSessionId(any()) } just runs - roktKit.setSession(com.mparticle.rokt.RoktSession("sid")) + roktKit.setSession(com.mparticle.rokt.RoktSession("sid", " ")) - verify { Rokt.setSessionId("sid") } verify(exactly = 0) { Rokt.setSession(any()) } + verify(exactly = 0) { Rokt.setSessionId(any()) } unmockkObject(Rokt) } @@ -1554,6 +1554,18 @@ class RoktKitTests { unmockkObject(Rokt) } + @Test + fun testGetSession_whenNativeSessionIsAbsent_returnsNull() { + mockkObject(Rokt) + every { Rokt.getSession() } returns null + + val result = roktKit.getSession() + + assertNull(result) + verify { Rokt.getSession() } + unmockkObject(Rokt) + } + @Test fun testSetSessionId_delegatesToRoktSdk() { mockkObject(Rokt) diff --git a/kits/rokt/rokt/src/test/kotlin/com/mparticle/kits/RoktTest.kt b/kits/rokt/rokt/src/test/kotlin/com/mparticle/kits/RoktTest.kt index 3aac2ea33..6c254db14 100644 --- a/kits/rokt/rokt/src/test/kotlin/com/mparticle/kits/RoktTest.kt +++ b/kits/rokt/rokt/src/test/kotlin/com/mparticle/kits/RoktTest.kt @@ -312,6 +312,16 @@ class RoktTest { verify(roktListener, never()).setSession(any()) } + @Test + fun testSetSession_whenRoktKitMissing_doesNotCallKitManager() { + `when`(kitManager.isKitActive(MParticle.ServiceProviders.ROKT)).thenReturn(false) + val session = com.mparticle.rokt.RoktSession("sid", "jwt") + + rokt.setSession(session) + + verify(roktListener, never()).setSession(any()) + } + @Test fun testGetSession_whenEnabled_delegatesToKitManager() { configManager.enabled = true @@ -330,6 +340,16 @@ class RoktTest { assertNull(result) } + @Test + fun testGetSession_whenRoktKitMissing_returnsNull() { + `when`(kitManager.isKitActive(MParticle.ServiceProviders.ROKT)).thenReturn(false) + + val result = rokt.getSession() + + verify(roktListener, never()).getSession() + assertNull(result) + } + @Test fun testSetSessionId_whenEnabled_delegatesToKitManager() { configManager.enabled = true