-
Notifications
You must be signed in to change notification settings - Fork 63
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add API to decorate link with user/session info (close #639)
- Loading branch information
1 parent
0605fd0
commit 8fe5da9
Showing
5 changed files
with
327 additions
and
0 deletions.
There are no files selected for viewing
168 changes: 168 additions & 0 deletions
168
...-tracker/src/androidTest/java/com/snowplowanalytics/snowplow/tracker/LinkDecoratorTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
package com.snowplowanalytics.snowplow.tracker | ||
|
||
|
||
import android.net.Uri | ||
import androidx.test.ext.junit.runners.AndroidJUnit4 | ||
import androidx.test.platform.app.InstrumentationRegistry | ||
import com.snowplowanalytics.core.utils.Util.urlSafeBase64Encode | ||
import com.snowplowanalytics.snowplow.Snowplow | ||
import com.snowplowanalytics.snowplow.configuration.NetworkConfiguration | ||
import com.snowplowanalytics.snowplow.configuration.SessionConfiguration | ||
import com.snowplowanalytics.snowplow.configuration.SubjectConfiguration | ||
import com.snowplowanalytics.snowplow.configuration.TrackerConfiguration | ||
import com.snowplowanalytics.snowplow.controller.SessionController | ||
import com.snowplowanalytics.snowplow.controller.TrackerController | ||
import com.snowplowanalytics.snowplow.event.ScreenView | ||
import com.snowplowanalytics.snowplow.network.HttpMethod | ||
import com.snowplowanalytics.snowplow.util.TimeMeasure | ||
import org.junit.Assert | ||
import org.junit.Before | ||
import org.junit.Test | ||
import org.junit.runner.RunWith | ||
import java.util.concurrent.TimeUnit | ||
|
||
|
||
@RunWith(AndroidJUnit4::class) | ||
class LinkDecoratorTest { | ||
private lateinit var tracker: TrackerController | ||
private lateinit var session: SessionController | ||
private lateinit var userId: String | ||
private lateinit var appId: String | ||
private val subjectUserId = "subjectUserId" | ||
private val subjectUserIdEncoded = urlSafeBase64Encode(subjectUserId) | ||
private val testLink = Uri.parse("http://example.com") | ||
private val epoch = "\\d{13}" | ||
|
||
private fun matches(pattern: String, result: Uri) { | ||
val regex = Regex("^${pattern.replace(".", "\\.").replace("?", "\\?")}$") | ||
Assert.assertTrue( | ||
"$result\ndoes not match expected: $pattern", regex.matches(result.toString()) | ||
) | ||
} | ||
|
||
|
||
@Before | ||
fun before() { | ||
tracker = getTracker() | ||
session = tracker.session!! | ||
userId = session.userId | ||
appId = urlSafeBase64Encode(tracker.appId) | ||
} | ||
|
||
@Test | ||
fun testWithoutSession() { | ||
val tracker = getTrackerNoSession() | ||
val result = tracker.decorateLink(testLink) | ||
Assert.assertEquals(null, result) | ||
} | ||
|
||
@Test | ||
fun testDecorateUriWithExistingSpParam() { | ||
tracker.track(ScreenView("test")) | ||
|
||
val pattern = "http://example.com?_sp=$userId.$epoch.${session.sessionId}..$appId" | ||
val result = | ||
tracker.decorateLink(testLink.buildUpon().appendQueryParameter("_sp", "test").build()) | ||
|
||
matches(pattern, result!!) | ||
} | ||
|
||
@Test | ||
fun testDecorateUriWithOtherParam() { | ||
tracker.track(ScreenView("test")) | ||
|
||
val pattern = "http://example.com?a=b&_sp=$userId.$epoch.${session.sessionId}..$appId$" | ||
val result = | ||
tracker.decorateLink(testLink.buildUpon().appendQueryParameter("a", "b").build()) | ||
|
||
matches(pattern, result!!) | ||
} | ||
|
||
@Test | ||
fun testDecorateUriWithParameters() { | ||
tracker.track(ScreenView("test")) | ||
|
||
val sessionId = session.sessionId | ||
val decorate = { c: CrossDeviceParameterConfiguration -> tracker.decorateLink(testLink, c)!! } | ||
|
||
matches( | ||
"http://example.com?_sp=$userId.$epoch.$sessionId", | ||
decorate(CrossDeviceParameterConfiguration(sourceId = false)) | ||
) | ||
|
||
matches( | ||
"http://example.com?_sp=$userId.$epoch.$sessionId..$appId", | ||
decorate(CrossDeviceParameterConfiguration()) | ||
) | ||
|
||
matches( | ||
"http://example.com?_sp=$userId.$epoch.$sessionId..$appId.mob", | ||
decorate(CrossDeviceParameterConfiguration(sourcePlatform = true)) | ||
) | ||
|
||
matches( | ||
"http://example.com?_sp=$userId.$epoch.$sessionId.$subjectUserIdEncoded.$appId.mob", | ||
decorate(CrossDeviceParameterConfiguration(sourcePlatform = true, subjectUserId = true)) | ||
) | ||
|
||
matches( | ||
"http://example.com?_sp=$userId.$epoch.$sessionId...mob", | ||
decorate(CrossDeviceParameterConfiguration(sourceId = false, sourcePlatform = true)) | ||
) | ||
|
||
matches( | ||
"http://example.com?_sp=$userId.$epoch..$subjectUserIdEncoded.$appId", | ||
decorate(CrossDeviceParameterConfiguration(sessionId = false, subjectUserId = true)) | ||
) | ||
|
||
matches( | ||
"http://example.com?_sp=$userId.$epoch..$subjectUserIdEncoded.$appId", | ||
decorate(CrossDeviceParameterConfiguration(sessionId = false, subjectUserId = true)) | ||
) | ||
|
||
|
||
matches( | ||
"http://example.com?_sp=$userId.$epoch", | ||
decorate(CrossDeviceParameterConfiguration(sourceId = false, sessionId = false)) | ||
) | ||
} | ||
|
||
private fun getTracker(): TrackerController { | ||
val context = InstrumentationRegistry.getInstrumentation().targetContext | ||
|
||
val networkConfiguration = NetworkConfiguration(MockNetworkConnection(HttpMethod.POST, 200)) | ||
|
||
val trackerConfiguration = TrackerConfiguration("decoratorTest").sessionContext(true) | ||
|
||
val subjectConfig = SubjectConfiguration().userId(subjectUserId) | ||
|
||
val sessionConfiguration = SessionConfiguration( | ||
TimeMeasure(6, TimeUnit.SECONDS), | ||
TimeMeasure(30, TimeUnit.SECONDS), | ||
) | ||
|
||
return Snowplow.createTracker( | ||
context, | ||
"namespace" + Math.random(), | ||
networkConfiguration, | ||
trackerConfiguration, | ||
sessionConfiguration, | ||
subjectConfig | ||
) | ||
} | ||
|
||
private fun getTrackerNoSession(): TrackerController { | ||
val context = InstrumentationRegistry.getInstrumentation().targetContext | ||
|
||
val networkConfiguration = NetworkConfiguration(MockNetworkConnection(HttpMethod.POST, 200)) | ||
|
||
val trackerConfiguration = TrackerConfiguration("decoratorTest").sessionContext(false) | ||
|
||
return Snowplow.createTracker( | ||
context, | ||
"namespace" + Math.random(), | ||
networkConfiguration, | ||
trackerConfiguration, | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
39 changes: 39 additions & 0 deletions
39
...src/main/java/com/snowplowanalytics/snowplow/tracker/CrossDeviceParameterConfiguration.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/* | ||
* Copyright (c) 2015-2023 Snowplow Analytics Ltd. All rights reserved. | ||
* | ||
* This program is licensed to you under the Apache License Version 2.0, | ||
* and you may not use this file except in compliance with the Apache License Version 2.0. | ||
* You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the Apache License Version 2.0 is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. | ||
*/ | ||
package com.snowplowanalytics.snowplow.tracker | ||
|
||
import com.snowplowanalytics.snowplow.controller.SessionController | ||
import com.snowplowanalytics.snowplow.controller.TrackerController | ||
import com.snowplowanalytics.snowplow.controller.SubjectController | ||
|
||
/** | ||
* Configuration object for [TrackerController.decorateLink] | ||
* | ||
* Enabled properties will be included when decorating a URI using `decorateLink` | ||
*/ | ||
data class CrossDeviceParameterConfiguration( | ||
/** Whether to include the value of [SessionController.sessionId] when decorating a link (enabled by default) */ | ||
val sessionId: Boolean = true, | ||
|
||
/** Whether to include the value of [SubjectController.userId] when decorating a link */ | ||
val subjectUserId: Boolean = false, | ||
|
||
/** Whether to include the value of [TrackerController.appId] when decorating a link (enabled by default) */ | ||
val sourceId: Boolean = true, | ||
|
||
/** Whether to include the value of [TrackerController.devicePlatform] when decorating a link */ | ||
val sourcePlatform: Boolean = false, | ||
|
||
/** Optional identifier/information for cross-navigation */ | ||
val reason: String? = null | ||
) |