mirror of
https://github.com/vector-im/element-android.git
synced 2024-11-16 02:05:06 +08:00
creating and passing stored user properties on post hog initialisation
- this allows information captured during the onboarding to be sent once the user has opt'd in
This commit is contained in:
parent
3236d87323
commit
d99a2f8d14
@ -43,6 +43,7 @@ class DefaultVectorAnalytics @Inject constructor(
|
||||
postHogFactory: PostHogFactory,
|
||||
analyticsConfig: AnalyticsConfig,
|
||||
private val analyticsStore: AnalyticsStore,
|
||||
private val lateInitUserPropertiesFactory: LateInitUserPropertiesFactory,
|
||||
@NamedGlobalScope private val globalScope: CoroutineScope
|
||||
) : VectorAnalytics {
|
||||
|
||||
@ -105,14 +106,14 @@ class DefaultVectorAnalytics @Inject constructor(
|
||||
.launchIn(globalScope)
|
||||
}
|
||||
|
||||
private fun identifyPostHog() {
|
||||
private suspend fun identifyPostHog() {
|
||||
val id = analyticsId ?: return
|
||||
if (id.isEmpty()) {
|
||||
Timber.tag(analyticsTag.value).d("reset")
|
||||
posthog?.reset()
|
||||
} else {
|
||||
Timber.tag(analyticsTag.value).d("identify")
|
||||
posthog?.identify(id)
|
||||
posthog?.identify(id, lateInitUserPropertiesFactory.createUserProperties()?.getProperties()?.toPostHogUserProperties(), IGNORED_OPTIONS)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,9 +20,13 @@ import com.posthog.android.Properties
|
||||
import im.vector.app.features.analytics.itf.VectorAnalyticsEvent
|
||||
import im.vector.app.features.analytics.itf.VectorAnalyticsScreen
|
||||
import im.vector.app.test.fakes.FakeAnalyticsStore
|
||||
import im.vector.app.test.fakes.FakeLateInitUserPropertiesFactory
|
||||
import im.vector.app.test.fakes.FakePostHog
|
||||
import im.vector.app.test.fakes.FakePostHogFactory
|
||||
import im.vector.app.test.fixtures.AnalyticsConfigFixture.anAnalyticsConfig
|
||||
import im.vector.app.test.fixtures.aUserProperties
|
||||
import im.vector.app.test.fixtures.aVectorAnalyticsEvent
|
||||
import im.vector.app.test.fixtures.aVectorAnalyticsScreen
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
@ -31,26 +35,23 @@ import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
private const val AN_ANALYTICS_ID = "analytics-id"
|
||||
private val A_SCREEN_EVENT = object : VectorAnalyticsScreen {
|
||||
override fun getName() = "a-screen-event-name"
|
||||
override fun getProperties() = mapOf("property-name" to "property-value")
|
||||
}
|
||||
private val AN_EVENT = object : VectorAnalyticsEvent {
|
||||
override fun getName() = "an-event-name"
|
||||
override fun getProperties() = mapOf("property-name" to "property-value")
|
||||
}
|
||||
private val A_SCREEN_EVENT = aVectorAnalyticsScreen()
|
||||
private val AN_EVENT = aVectorAnalyticsEvent()
|
||||
private val A_LATE_INIT_USER_PROPERTIES = aUserProperties()
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class DefaultVectorAnalyticsTest {
|
||||
|
||||
private val fakePostHog = FakePostHog()
|
||||
private val fakeAnalyticsStore = FakeAnalyticsStore()
|
||||
private val fakeLateInitUserPropertiesFactory = FakeLateInitUserPropertiesFactory()
|
||||
|
||||
private val defaultVectorAnalytics = DefaultVectorAnalytics(
|
||||
postHogFactory = FakePostHogFactory(fakePostHog.instance).instance,
|
||||
analyticsStore = fakeAnalyticsStore.instance,
|
||||
globalScope = CoroutineScope(Dispatchers.Unconfined),
|
||||
analyticsConfig = anAnalyticsConfig(isEnabled = true)
|
||||
analyticsConfig = anAnalyticsConfig(isEnabled = true),
|
||||
lateInitUserPropertiesFactory = fakeLateInitUserPropertiesFactory.instance
|
||||
)
|
||||
|
||||
@Before
|
||||
@ -87,14 +88,16 @@ class DefaultVectorAnalyticsTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when valid analytics id updates then identify`() = runBlockingTest {
|
||||
fun `given lateinit user properties when valid analytics id updates then identify with lateinit properties`() = runBlockingTest {
|
||||
fakeLateInitUserPropertiesFactory.givenCreatesProperties(A_LATE_INIT_USER_PROPERTIES)
|
||||
|
||||
fakeAnalyticsStore.givenAnalyticsId(AN_ANALYTICS_ID)
|
||||
|
||||
fakePostHog.verifyIdentifies(AN_ANALYTICS_ID)
|
||||
fakePostHog.verifyIdentifies(AN_ANALYTICS_ID, A_LATE_INIT_USER_PROPERTIES)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when signing out analytics id updates then resets`() = runBlockingTest {
|
||||
fun `when signing out then resets posthog`() = runBlockingTest {
|
||||
fakeAnalyticsStore.allowSettingAnalyticsIdToCallBackingFlow()
|
||||
|
||||
defaultVectorAnalytics.onSignOut()
|
||||
@ -108,9 +111,7 @@ class DefaultVectorAnalyticsTest {
|
||||
|
||||
defaultVectorAnalytics.screen(A_SCREEN_EVENT)
|
||||
|
||||
fakePostHog.verifyScreenTracked(A_SCREEN_EVENT.getName(), Properties().also {
|
||||
it.putAll(A_SCREEN_EVENT.getProperties())
|
||||
})
|
||||
fakePostHog.verifyScreenTracked(A_SCREEN_EVENT.getName(), A_SCREEN_EVENT.toPostHogProperties())
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -128,9 +129,7 @@ class DefaultVectorAnalyticsTest {
|
||||
|
||||
defaultVectorAnalytics.capture(AN_EVENT)
|
||||
|
||||
fakePostHog.verifyEventTracked(AN_EVENT.getName(), Properties().also {
|
||||
it.putAll(AN_EVENT.getProperties())
|
||||
})
|
||||
fakePostHog.verifyEventTracked(AN_EVENT.getName(), AN_EVENT.toPostHogProperties())
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -142,3 +141,15 @@ class DefaultVectorAnalyticsTest {
|
||||
fakePostHog.verifyNoEventTracking()
|
||||
}
|
||||
}
|
||||
|
||||
private fun VectorAnalyticsScreen.toPostHogProperties(): Properties? {
|
||||
return getProperties()?.let { properties ->
|
||||
Properties().also { it.putAll(properties) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun VectorAnalyticsEvent.toPostHogProperties(): Properties? {
|
||||
return getProperties()?.let { properties ->
|
||||
Properties().also { it.putAll(properties) }
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2022 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.test.fakes
|
||||
|
||||
import im.vector.app.features.analytics.impl.LateInitUserPropertiesFactory
|
||||
import im.vector.app.features.analytics.plan.UserProperties
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.mockk
|
||||
|
||||
class FakeLateInitUserPropertiesFactory {
|
||||
|
||||
val instance = mockk<LateInitUserPropertiesFactory>()
|
||||
|
||||
fun givenCreatesProperties(userProperties: UserProperties?) {
|
||||
coEvery { instance.createUserProperties() } returns userProperties
|
||||
}
|
||||
}
|
@ -19,6 +19,7 @@ package im.vector.app.test.fakes
|
||||
import android.os.Looper
|
||||
import com.posthog.android.PostHog
|
||||
import com.posthog.android.Properties
|
||||
import im.vector.app.features.analytics.plan.UserProperties
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkStatic
|
||||
@ -41,15 +42,20 @@ class FakePostHog {
|
||||
verify { instance.optOut(optedOut) }
|
||||
}
|
||||
|
||||
fun verifyIdentifies(analyticsId: String) {
|
||||
verify { instance.identify(analyticsId) }
|
||||
fun verifyIdentifies(analyticsId: String, userProperties: UserProperties?) {
|
||||
verify {
|
||||
val postHogProperties = userProperties?.getProperties()
|
||||
?.let { rawProperties -> Properties().also { it.putAll(rawProperties) } }
|
||||
?.takeIf { it.isNotEmpty() }
|
||||
instance.identify(analyticsId, postHogProperties, null)
|
||||
}
|
||||
}
|
||||
|
||||
fun verifyReset() {
|
||||
verify { instance.reset() }
|
||||
}
|
||||
|
||||
fun verifyScreenTracked(name: String, properties: Properties) {
|
||||
fun verifyScreenTracked(name: String, properties: Properties?) {
|
||||
verify { instance.screen(name, properties) }
|
||||
}
|
||||
|
||||
@ -61,7 +67,7 @@ class FakePostHog {
|
||||
}
|
||||
}
|
||||
|
||||
fun verifyEventTracked(name: String, properties: Properties) {
|
||||
fun verifyEventTracked(name: String, properties: Properties?) {
|
||||
verify { instance.capture(name, properties) }
|
||||
}
|
||||
|
||||
|
26
vector/src/test/java/im/vector/app/test/fixtures/UserPropertiesFixture.kt
vendored
Normal file
26
vector/src/test/java/im/vector/app/test/fixtures/UserPropertiesFixture.kt
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2022 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.test.fixtures
|
||||
|
||||
import im.vector.app.features.analytics.plan.UserProperties
|
||||
import im.vector.app.features.analytics.plan.UserProperties.FtueUseCaseSelection
|
||||
|
||||
fun aUserProperties(
|
||||
ftueUseCase: FtueUseCaseSelection? = FtueUseCaseSelection.Skip
|
||||
) = UserProperties(
|
||||
ftueUseCaseSelection = ftueUseCase
|
||||
)
|
36
vector/src/test/java/im/vector/app/test/fixtures/VectorAnalyticsFixture.kt
vendored
Normal file
36
vector/src/test/java/im/vector/app/test/fixtures/VectorAnalyticsFixture.kt
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2022 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.test.fixtures
|
||||
|
||||
import im.vector.app.features.analytics.itf.VectorAnalyticsEvent
|
||||
import im.vector.app.features.analytics.itf.VectorAnalyticsScreen
|
||||
|
||||
fun aVectorAnalyticsScreen(
|
||||
name: String = "a-screen-name",
|
||||
properties: Map<String, Any>? = null
|
||||
) = object : VectorAnalyticsScreen {
|
||||
override fun getName() = name
|
||||
override fun getProperties() = properties
|
||||
}
|
||||
|
||||
fun aVectorAnalyticsEvent(
|
||||
name: String = "an-event-name",
|
||||
properties: Map<String, Any>? = null
|
||||
) = object : VectorAnalyticsEvent {
|
||||
override fun getName() = name
|
||||
override fun getProperties() = properties
|
||||
}
|
Loading…
Reference in New Issue
Block a user