Code review - more tests

This commit is contained in:
Valere 2024-05-07 09:38:26 +02:00
parent a761215e31
commit 6ad40fc6e0
5 changed files with 120 additions and 4 deletions

View file

@ -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)
}
}

View file

@ -20,9 +20,13 @@ import app.cash.molecule.RecompositionMode
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
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.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.verification.SessionVerifiedStatus
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService
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(
roomListService: RoomListService = FakeRoomListService(),
networkStatus: NetworkStatus = NetworkStatus.Offline
networkStatus: NetworkStatus = NetworkStatus.Offline,
analyticsService: FakeAnalyticsService = FakeAnalyticsService(),
encryptionService: FakeEncryptionService = FakeEncryptionService(),
): LoggedInPresenter {
return LoggedInPresenter(
matrixClient = FakeMatrixClient(roomListService = roomListService),
networkMonitor = FakeNetworkMonitor(networkStatus),
pushService = FakePushService(),
sessionVerificationService = FakeSessionVerificationService(),
analyticsService = FakeAnalyticsService(),
encryptionService = FakeEncryptionService()
analyticsService = analyticsService,
encryptionService = encryptionService
)
}
}

View file

@ -77,6 +77,10 @@ class FakeSessionVerificationService : SessionVerificationService {
_sessionVerifiedStatus.value = status
}
suspend fun emitVerifiedStatus(status: SessionVerifiedStatus) {
_sessionVerifiedStatus.emit(status)
}
fun givenVerificationFlowState(state: VerificationFlowState) {
_verificationFlowState.value = state
}

View file

@ -33,6 +33,7 @@ class FakeAnalyticsService(
val capturedEvents = mutableListOf<VectorAnalyticsEvent>()
val screenEvents = mutableListOf<VectorAnalyticsScreen>()
val trackedErrors = mutableListOf<Throwable>()
val capturedUserProperties = mutableListOf<UserProperties>()
override fun getAvailableAnalyticsProviders(): Set<AnalyticsProvider> = emptySet()
@ -65,6 +66,7 @@ class FakeAnalyticsService(
}
override fun updateUserProperties(userProperties: UserProperties) {
capturedUserProperties += userProperties
}
override fun trackError(throwable: Throwable) {

View file

@ -87,7 +87,7 @@ class PosthogAnalyticsProvider @Inject constructor(
userProperties.getProperties()?.let {
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.
// For now, we have to store them, and they will be updated when the next call
// to capture will happen.