Code review - more tests
This commit is contained in:
parent
c430699711
commit
94bbcbf503
5 changed files with 120 additions and 4 deletions
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 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 io.element.android.appnav.loggedin
|
||||||
|
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import im.vector.app.features.analytics.plan.CryptoSessionStateChange
|
||||||
|
import im.vector.app.features.analytics.plan.UserProperties
|
||||||
|
import io.element.android.libraries.matrix.api.encryption.RecoveryState
|
||||||
|
import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
|
||||||
|
import io.element.android.tests.testutils.WarmUpRule
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class AnalyticsVerificationStateMappingTests {
|
||||||
|
@get:Rule
|
||||||
|
val warmUpRule = WarmUpRule()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Test verification Mappings`() = runTest {
|
||||||
|
assertThat(SessionVerifiedStatus.Verified.toAnalyticsUserPropertyValue())
|
||||||
|
.isEqualTo(UserProperties.VerificationState.Verified)
|
||||||
|
assertThat(SessionVerifiedStatus.NotVerified.toAnalyticsUserPropertyValue())
|
||||||
|
.isEqualTo(UserProperties.VerificationState.NotVerified)
|
||||||
|
|
||||||
|
assertThat(SessionVerifiedStatus.Verified.toAnalyticsStateChangeValue())
|
||||||
|
.isEqualTo(CryptoSessionStateChange.VerificationState.Verified)
|
||||||
|
assertThat(SessionVerifiedStatus.NotVerified.toAnalyticsStateChangeValue())
|
||||||
|
.isEqualTo(CryptoSessionStateChange.VerificationState.NotVerified)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Test recovery state Mappings`() = runTest {
|
||||||
|
assertThat(RecoveryState.UNKNOWN.toAnalyticsUserPropertyValue())
|
||||||
|
.isNull()
|
||||||
|
assertThat(RecoveryState.WAITING_FOR_SYNC.toAnalyticsUserPropertyValue())
|
||||||
|
.isNull()
|
||||||
|
assertThat(RecoveryState.INCOMPLETE.toAnalyticsUserPropertyValue())
|
||||||
|
.isEqualTo(UserProperties.RecoveryState.Incomplete)
|
||||||
|
assertThat(RecoveryState.ENABLED.toAnalyticsUserPropertyValue())
|
||||||
|
.isEqualTo(UserProperties.RecoveryState.Enabled)
|
||||||
|
assertThat(RecoveryState.DISABLED.toAnalyticsUserPropertyValue())
|
||||||
|
.isEqualTo(UserProperties.RecoveryState.Disabled)
|
||||||
|
|
||||||
|
assertThat(RecoveryState.UNKNOWN.toAnalyticsStateChangeValue())
|
||||||
|
.isNull()
|
||||||
|
assertThat(RecoveryState.WAITING_FOR_SYNC.toAnalyticsStateChangeValue())
|
||||||
|
.isNull()
|
||||||
|
assertThat(RecoveryState.INCOMPLETE.toAnalyticsStateChangeValue())
|
||||||
|
.isEqualTo(CryptoSessionStateChange.RecoveryState.Incomplete)
|
||||||
|
assertThat(RecoveryState.ENABLED.toAnalyticsStateChangeValue())
|
||||||
|
.isEqualTo(CryptoSessionStateChange.RecoveryState.Enabled)
|
||||||
|
assertThat(RecoveryState.DISABLED.toAnalyticsStateChangeValue())
|
||||||
|
.isEqualTo(CryptoSessionStateChange.RecoveryState.Disabled)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -20,9 +20,13 @@ import app.cash.molecule.RecompositionMode
|
||||||
import app.cash.molecule.moleculeFlow
|
import app.cash.molecule.moleculeFlow
|
||||||
import app.cash.turbine.test
|
import app.cash.turbine.test
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import im.vector.app.features.analytics.plan.CryptoSessionStateChange
|
||||||
|
import im.vector.app.features.analytics.plan.UserProperties
|
||||||
import io.element.android.features.networkmonitor.api.NetworkStatus
|
import io.element.android.features.networkmonitor.api.NetworkStatus
|
||||||
import io.element.android.features.networkmonitor.test.FakeNetworkMonitor
|
import io.element.android.features.networkmonitor.test.FakeNetworkMonitor
|
||||||
|
import io.element.android.libraries.matrix.api.encryption.RecoveryState
|
||||||
import io.element.android.libraries.matrix.api.roomlist.RoomListService
|
import io.element.android.libraries.matrix.api.roomlist.RoomListService
|
||||||
|
import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
|
||||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||||
import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService
|
import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService
|
||||||
import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
|
import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
|
||||||
|
|
@ -66,17 +70,53 @@ class LoggedInPresenterTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `present - report crypto status analytics`() = runTest {
|
||||||
|
val analyticsService = FakeAnalyticsService()
|
||||||
|
val verificationService = FakeSessionVerificationService()
|
||||||
|
val encryptionService = FakeEncryptionService()
|
||||||
|
val presenter = LoggedInPresenter(
|
||||||
|
matrixClient = FakeMatrixClient(encryptionService = encryptionService),
|
||||||
|
networkMonitor = FakeNetworkMonitor(NetworkStatus.Online),
|
||||||
|
pushService = FakePushService(),
|
||||||
|
sessionVerificationService = verificationService,
|
||||||
|
analyticsService = analyticsService,
|
||||||
|
encryptionService = encryptionService
|
||||||
|
)
|
||||||
|
moleculeFlow(RecompositionMode.Immediate) {
|
||||||
|
presenter.present()
|
||||||
|
}.test {
|
||||||
|
encryptionService.emitRecoveryState(RecoveryState.UNKNOWN)
|
||||||
|
encryptionService.emitRecoveryState(RecoveryState.INCOMPLETE)
|
||||||
|
verificationService.emitVerifiedStatus(SessionVerifiedStatus.Verified)
|
||||||
|
|
||||||
|
// Should only capture once (not report while checking state -like unknown-)
|
||||||
|
consumeItemsUntilPredicate {
|
||||||
|
analyticsService.capturedEvents.size == 1 &&
|
||||||
|
analyticsService.capturedEvents[0] is CryptoSessionStateChange
|
||||||
|
}
|
||||||
|
consumeItemsUntilPredicate {
|
||||||
|
analyticsService.capturedUserProperties.size == 1 &&
|
||||||
|
analyticsService.capturedUserProperties[0].recoveryState == UserProperties.RecoveryState.Incomplete &&
|
||||||
|
analyticsService.capturedUserProperties[0].verificationState == UserProperties.VerificationState.Verified
|
||||||
|
}
|
||||||
|
cancelAndConsumeRemainingEvents()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun createLoggedInPresenter(
|
private fun createLoggedInPresenter(
|
||||||
roomListService: RoomListService = FakeRoomListService(),
|
roomListService: RoomListService = FakeRoomListService(),
|
||||||
networkStatus: NetworkStatus = NetworkStatus.Offline
|
networkStatus: NetworkStatus = NetworkStatus.Offline,
|
||||||
|
analyticsService: FakeAnalyticsService = FakeAnalyticsService(),
|
||||||
|
encryptionService: FakeEncryptionService = FakeEncryptionService(),
|
||||||
): LoggedInPresenter {
|
): LoggedInPresenter {
|
||||||
return LoggedInPresenter(
|
return LoggedInPresenter(
|
||||||
matrixClient = FakeMatrixClient(roomListService = roomListService),
|
matrixClient = FakeMatrixClient(roomListService = roomListService),
|
||||||
networkMonitor = FakeNetworkMonitor(networkStatus),
|
networkMonitor = FakeNetworkMonitor(networkStatus),
|
||||||
pushService = FakePushService(),
|
pushService = FakePushService(),
|
||||||
sessionVerificationService = FakeSessionVerificationService(),
|
sessionVerificationService = FakeSessionVerificationService(),
|
||||||
analyticsService = FakeAnalyticsService(),
|
analyticsService = analyticsService,
|
||||||
encryptionService = FakeEncryptionService()
|
encryptionService = encryptionService
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,10 @@ class FakeSessionVerificationService : SessionVerificationService {
|
||||||
_sessionVerifiedStatus.value = status
|
_sessionVerifiedStatus.value = status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun emitVerifiedStatus(status: SessionVerifiedStatus) {
|
||||||
|
_sessionVerifiedStatus.emit(status)
|
||||||
|
}
|
||||||
|
|
||||||
fun givenVerificationFlowState(state: VerificationFlowState) {
|
fun givenVerificationFlowState(state: VerificationFlowState) {
|
||||||
_verificationFlowState.value = state
|
_verificationFlowState.value = state
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ class FakeAnalyticsService(
|
||||||
val capturedEvents = mutableListOf<VectorAnalyticsEvent>()
|
val capturedEvents = mutableListOf<VectorAnalyticsEvent>()
|
||||||
val screenEvents = mutableListOf<VectorAnalyticsScreen>()
|
val screenEvents = mutableListOf<VectorAnalyticsScreen>()
|
||||||
val trackedErrors = mutableListOf<Throwable>()
|
val trackedErrors = mutableListOf<Throwable>()
|
||||||
|
val capturedUserProperties = mutableListOf<UserProperties>()
|
||||||
|
|
||||||
override fun getAvailableAnalyticsProviders(): Set<AnalyticsProvider> = emptySet()
|
override fun getAvailableAnalyticsProviders(): Set<AnalyticsProvider> = emptySet()
|
||||||
|
|
||||||
|
|
@ -65,6 +66,7 @@ class FakeAnalyticsService(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateUserProperties(userProperties: UserProperties) {
|
override fun updateUserProperties(userProperties: UserProperties) {
|
||||||
|
capturedUserProperties += userProperties
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun trackError(throwable: Throwable) {
|
override fun trackError(throwable: Throwable) {
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ class PosthogAnalyticsProvider @Inject constructor(
|
||||||
userProperties.getProperties()?.let {
|
userProperties.getProperties()?.let {
|
||||||
pendingUserProperties?.putAll(it)
|
pendingUserProperties?.putAll(it)
|
||||||
}
|
}
|
||||||
// We are not currently using `identify` in EIX, if it was the case
|
// We are not currently using `identify` in EAX, if it was the case
|
||||||
// we could have called identify to update the user properties.
|
// we could have called identify to update the user properties.
|
||||||
// For now, we have to store them, and they will be updated when the next call
|
// For now, we have to store them, and they will be updated when the next call
|
||||||
// to capture will happen.
|
// to capture will happen.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue