diff --git a/code/analytics/src/main/java/com/adobe/marketing/mobile/analytics/internal/AnalyticsConstants.kt b/code/analytics/src/main/java/com/adobe/marketing/mobile/analytics/internal/AnalyticsConstants.kt index 6497657..3550e04 100644 --- a/code/analytics/src/main/java/com/adobe/marketing/mobile/analytics/internal/AnalyticsConstants.kt +++ b/code/analytics/src/main/java/com/adobe/marketing/mobile/analytics/internal/AnalyticsConstants.kt @@ -18,7 +18,7 @@ internal object AnalyticsConstants { const val EXTENSION_NAME = "com.adobe.module.analytics" const val FRIENDLY_NAME = "Analytics" - const val EXTENSION_VERSION = "3.0.0" + const val EXTENSION_VERSION = "3.0.1" const val DATASTORE_NAME = "AnalyticsDataStorage" const val DATA_QUEUE_NAME = EXTENSION_NAME const val REORDER_QUEUE_NAME = "com.adobe.module.analyticsreorderqueue" diff --git a/code/analytics/src/main/java/com/adobe/marketing/mobile/analytics/internal/AnalyticsState.kt b/code/analytics/src/main/java/com/adobe/marketing/mobile/analytics/internal/AnalyticsState.kt index 2144cd1..b790051 100644 --- a/code/analytics/src/main/java/com/adobe/marketing/mobile/analytics/internal/AnalyticsState.kt +++ b/code/analytics/src/main/java/com/adobe/marketing/mobile/analytics/internal/AnalyticsState.kt @@ -222,17 +222,17 @@ class AnalyticsState { */ private fun extractPlacesInfo(placesInfo: Map) { val placesContextData = DataReader.optTypedMap( - String::class.java, + Object::class.java, placesInfo, AnalyticsConstants.EventDataKeys.Places.CURRENT_POI, null ) ?: return - val regionId = placesContextData[AnalyticsConstants.EventDataKeys.Places.REGION_ID] + val regionId = placesContextData[AnalyticsConstants.EventDataKeys.Places.REGION_ID] as? String if (!StringUtils.isNullOrEmpty(regionId)) { defaultData[AnalyticsConstants.ContextDataKeys.REGION_ID] = regionId ?: "" } - val regionName = placesContextData[AnalyticsConstants.EventDataKeys.Places.REGION_NAME] + val regionName = placesContextData[AnalyticsConstants.EventDataKeys.Places.REGION_NAME] as? String if (!StringUtils.isNullOrEmpty(regionName)) { defaultData[AnalyticsConstants.ContextDataKeys.REGION_NAME] = regionName ?: "" diff --git a/code/analytics/src/phone/java/com/adobe/marketing/mobile/Analytics.java b/code/analytics/src/phone/java/com/adobe/marketing/mobile/Analytics.java index 15c5e6b..56840bd 100644 --- a/code/analytics/src/phone/java/com/adobe/marketing/mobile/Analytics.java +++ b/code/analytics/src/phone/java/com/adobe/marketing/mobile/Analytics.java @@ -21,7 +21,7 @@ public class Analytics { private static final String LOG_TAG = "Analytics"; - private static final String EXTENSION_VERSION = "3.0.0"; + private static final String EXTENSION_VERSION = "3.0.1"; // The constants for EventData keys private static final String ANALYTICS_ID = "aid"; private static final String GET_QUEUE_SIZE = "getqueuesize"; diff --git a/code/analytics/src/test/java/com/adobe/marketing/mobile/analytics/function/test/AnalyticsTrackPlacesTests.kt b/code/analytics/src/test/java/com/adobe/marketing/mobile/analytics/function/test/AnalyticsTrackPlacesTests.kt index f4a2001..561ae74 100644 --- a/code/analytics/src/test/java/com/adobe/marketing/mobile/analytics/function/test/AnalyticsTrackPlacesTests.kt +++ b/code/analytics/src/test/java/com/adobe/marketing/mobile/analytics/function/test/AnalyticsTrackPlacesTests.kt @@ -97,7 +97,100 @@ internal class AnalyticsTrackPlacesTests : AnalyticsFunctionalTestBase() { "a.loc.poi.id" to "myRegionId", "a.loc.poi" to "myRegionName" ) - Assert.assertTrue(expectedContextData == contextDataMap) + Assert.assertEquals(expectedContextData, contextDataMap) + Assert.assertEquals(expectedVars.size, varMap.size) + Assert.assertEquals(expectedVars, varMap) + } + + @Test(timeout = 10000) + fun `analytics hit contains current poi places data`() { + val countDownLatch = CountDownLatch(1) + var varMap: Map = emptyMap() + var contextDataMap: Map = emptyMap() + monitorNetwork { request -> + if (request.url.startsWith("https://test.com/b/ss/rsid/0/")) { + val body = URLDecoder.decode(String(request.body), "UTF-8") + varMap = extractQueryParamsFrom(body) + contextDataMap = extractContextDataFrom(body) + countDownLatch.countDown() + } + } + + val analyticsExtension = initializeAnalyticsExtensionWithPreset( + mapOf( + "analytics.server" to "test.com", + "analytics.rsids" to "rsid", + "global.privacy" to "optedin", + "experienceCloud.org" to "orgid", + "analytics.batchLimit" to 0, + "analytics.offlineEnabled" to true, + "analytics.backdatePreviousSessionInfo" to true, + "analytics.launchHitDelay" to 1 + ), + defaultIdentity() + ) + + // Test with full shared state to validate parsing/casting of types + updateMockedSharedState( + "com.adobe.module.places", + mapOf( + "currentpoi" to mapOf( + "regionid" to "99306680-a0e5-49f1-b0eb-c52c6e05ce01", + "useriswithin" to true, + "latitude" to 37.3309257, + "libraryid" to "311cbfb0-ac5e-436a-b22d-4a917426880d", + "regionname" to "Adobe 100", + "weight" to 1, + "regionmetadata" to mapOf( + "country" to "Adobe 100", + "city" to "Adobe 100", + "street" to "Adobe 100", + "state" to "Adobe 100", + "category" to "Adobe 100" + ), + "radius" to 100, + "longitude" to -121.8939791 + ) + ) + ) + + val trackEvent = Event.Builder( + "track event", + EventType.GENERIC_TRACK, + EventSource.REQUEST_CONTENT + ).setEventData( + mapOf( + "action" to "testActionName", + "contextdata" to mapOf( + "k1" to "v1", + "k2" to "v2" + ) + ) + ).build() + + analyticsExtension.handleIncomingEvent(trackEvent) + + countDownLatch.await() + val expectedVars: Map = mapOf( + "ndh" to "1", + "ce" to "UTF-8", + "cp" to "foreground", + "pev2" to "AMACTION:testActionName", + "pe" to "lnk_o", + "mid" to "mid", + "aamb" to "blob", + "aamlh" to "lochint", + "t" to TimeZoneHelper.TIMESTAMP_TIMEZONE_OFFSET, + "ts" to trackEvent.timestampInSeconds.toString() + ) + val expectedContextData: Map = mapOf( + "k1" to "v1", + "k2" to "v2", + "a.action" to "testActionName", + "a.loc.poi.id" to "99306680-a0e5-49f1-b0eb-c52c6e05ce01", + "a.loc.poi" to "Adobe 100" + ) + Assert.assertEquals(expectedContextData, contextDataMap) Assert.assertEquals(expectedVars.size, varMap.size) Assert.assertEquals(expectedVars, varMap) } @@ -184,7 +277,7 @@ internal class AnalyticsTrackPlacesTests : AnalyticsFunctionalTestBase() { "a.loc.poi.id" to "myRegionId2", "a.loc.poi" to "myRegionName2" ) - Assert.assertTrue(expectedContextData == contextDataMap) + Assert.assertEquals(expectedContextData, contextDataMap) Assert.assertEquals(expectedVars.size, varMap.size) Assert.assertEquals(expectedVars, varMap) } diff --git a/code/analytics/src/test/java/com/adobe/marketing/mobile/analytics/internal/AnalyticsStateTests.kt b/code/analytics/src/test/java/com/adobe/marketing/mobile/analytics/internal/AnalyticsStateTests.kt index 36be81e..93c4f81 100644 --- a/code/analytics/src/test/java/com/adobe/marketing/mobile/analytics/internal/AnalyticsStateTests.kt +++ b/code/analytics/src/test/java/com/adobe/marketing/mobile/analytics/internal/AnalyticsStateTests.kt @@ -159,6 +159,41 @@ class AnalyticsStateTests { ) } + @Test + fun testExtractPlacesInfo_returnsRegionNameAndID_whenStateContainsOtherTypes() { + state.update( + mapOf( + PLACES_SHARED_STATE to mapOf( + "currentpoi" to mapOf( + "regionid" to "99306680-a0e5-49f1-b0eb-c52c6e05ce01", + "useriswithin" to true, + "latitude" to 37.3309257, + "libraryid" to "311cbfb0-ac5e-436a-b22d-4a917426880d", + "regionname" to "Adobe 100", + "weight" to 1, + "regionmetadata" to mapOf( + "country" to "Adobe 100", + "city" to "Adobe 100", + "street" to "Adobe 100", + "state" to "Adobe 100", + "category" to "Adobe 100" + ), + "radius" to 100, + "longitude" to -121.8939791 + ) + ) + ) + ) + assertEquals( + "99306680-a0e5-49f1-b0eb-c52c6e05ce01", + state.defaultData[AnalyticsConstants.ContextDataKeys.REGION_ID] + ) + assertEquals( + "Adobe 100", + state.defaultData[AnalyticsConstants.ContextDataKeys.REGION_NAME] + ) + } + @Test fun testExtractPlacesInfo_returnsDefaultValues_when_empty() { state.update( @@ -183,6 +218,48 @@ class AnalyticsStateTests { assertTrue(state.defaultData.isEmpty()) } + @Test + fun testExtractPlacesInfo_returnsDefaultValuesAndDoesNotCrash_when_regionname_invalidType() { + state.update( + mapOf( + PLACES_SHARED_STATE to mapOf( + "currentpoi" to mapOf( + "regionid" to "sampleRegionId", + "regionname" to true + ) + ) + ) + ) + assertEquals( + "sampleRegionId", + state.defaultData[AnalyticsConstants.ContextDataKeys.REGION_ID] + ) + assertNull( + state.defaultData[AnalyticsConstants.ContextDataKeys.REGION_NAME] + ) + } + + @Test + fun testExtractPlacesInfo_returnsDefaultValuesAndDoesNotCrash_when_regionid_invalidType() { + state.update( + mapOf( + PLACES_SHARED_STATE to mapOf( + "currentpoi" to mapOf( + "regionid" to 123, + "regionname" to "sampleRegionName" + ) + ) + ) + ) + assertEquals( + "sampleRegionName", + state.defaultData[AnalyticsConstants.ContextDataKeys.REGION_NAME] + ) + assertNull( + state.defaultData[AnalyticsConstants.ContextDataKeys.REGION_ID] + ) + } + @Test fun testExtractPlacesInfo_shouldNotIncludeNullValues() { state.update( diff --git a/code/gradle.properties b/code/gradle.properties index 66ed9f3..84db38b 100644 --- a/code/gradle.properties +++ b/code/gradle.properties @@ -17,7 +17,7 @@ org.gradle.caching=true android.useAndroidX=true moduleName=analytics -moduleVersion=3.0.0 +moduleVersion=3.0.1 mavenRepoName=AdobeMobileAnalyticsSdk mavenRepoDescription=Android Analytics Extension for Adobe Mobile Marketing