From 3d5951cbf021175ce854d4267a3a701f113014a6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 14 Jun 2024 17:26:06 +0200 Subject: [PATCH] Add test on pusher registration --- appnav/build.gradle.kts | 1 + .../appnav/loggedin/LoggedInPresenterTest.kt | 310 +++++++++++++++++- .../libraries/push/test/FakePushService.kt | 3 +- .../pushproviders/test/FakePushProvider.kt | 3 +- 4 files changed, 311 insertions(+), 6 deletions(-) diff --git a/appnav/build.gradle.kts b/appnav/build.gradle.kts index 95fb4a8a08..aae3385fb3 100644 --- a/appnav/build.gradle.kts +++ b/appnav/build.gradle.kts @@ -67,6 +67,7 @@ dependencies { testImplementation(libs.test.turbine) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.push.test) + testImplementation(projects.libraries.pushproviders.test) testImplementation(projects.features.networkmonitor.test) testImplementation(projects.features.login.impl) testImplementation(projects.tests.testutils) diff --git a/appnav/src/test/kotlin/io/element/android/appnav/loggedin/LoggedInPresenterTest.kt b/appnav/src/test/kotlin/io/element/android/appnav/loggedin/LoggedInPresenterTest.kt index f57f648599..8d4248df27 100644 --- a/appnav/src/test/kotlin/io/element/android/appnav/loggedin/LoggedInPresenterTest.kt +++ b/appnav/src/test/kotlin/io/element/android/appnav/loggedin/LoggedInPresenterTest.kt @@ -24,21 +24,36 @@ 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.MatrixClient +import io.element.android.libraries.matrix.api.encryption.EncryptionService 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.SessionVerificationService import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus +import io.element.android.libraries.matrix.test.AN_EXCEPTION 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 import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService +import io.element.android.libraries.push.api.PushService import io.element.android.libraries.push.test.FakePushService +import io.element.android.libraries.pushproviders.api.Distributor +import io.element.android.libraries.pushproviders.api.PushProvider +import io.element.android.libraries.pushproviders.test.FakePushProvider +import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.consumeItemsUntilPredicate +import io.element.android.tests.testutils.lambda.any +import io.element.android.tests.testutils.lambda.lambdaRecorder +import io.element.android.tests.testutils.lambda.value +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test +@OptIn(ExperimentalCoroutinesApi::class) class LoggedInPresenterTest { @get:Rule val warmUpRule = WarmUpRule() @@ -107,17 +122,304 @@ class LoggedInPresenterTest { } } + @Test + fun `present - ensure default pusher is not registered if session is not verified`() = runTest { + val lambda = lambdaRecorder> { _, _, _ -> + Result.success(Unit) + } + val pushService = createFakePushService(registerWithLambda = lambda) + val presenter = createLoggedInPresenter(pushService = pushService) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + skipItems(1) + lambda.assertions() + .isNeverCalled() + } + } + + @Test + fun `present - ensure default pusher is registered with default provider`() = runTest { + val lambda = lambdaRecorder> { _, _, _ -> + Result.success(Unit) + } + val sessionVerificationService = FakeSessionVerificationService() + sessionVerificationService.givenVerifiedStatus(SessionVerifiedStatus.Verified) + val pushService = createFakePushService( + registerWithLambda = lambda, + ) + val presenter = createLoggedInPresenter( + pushService = pushService, + sessionVerificationService = sessionVerificationService, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + skipItems(2) + advanceUntilIdle() + lambda.assertions() + .isCalledOnce() + .with( + // MatrixClient + any(), + // PushProvider with highest priority (lower index) + value(pushService.getAvailablePushProviders()[0]), + // First distributor + value(pushService.getAvailablePushProviders()[0].getDistributors()[0]), + ) + } + } + + @Test + fun `present - ensure default pusher is registered with default provider - fail to register`() = runTest { + val lambda = lambdaRecorder> { _, _, _ -> + Result.failure(AN_EXCEPTION) + } + val sessionVerificationService = FakeSessionVerificationService() + sessionVerificationService.givenVerifiedStatus(SessionVerifiedStatus.Verified) + val pushService = createFakePushService( + registerWithLambda = lambda, + ) + val presenter = createLoggedInPresenter( + pushService = pushService, + sessionVerificationService = sessionVerificationService, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + skipItems(2) + advanceUntilIdle() + lambda.assertions() + .isCalledOnce() + .with( + // MatrixClient + any(), + // PushProvider with highest priority (lower index) + value(pushService.getAvailablePushProviders()[0]), + // First distributor + value(pushService.getAvailablePushProviders()[0].getDistributors()[0]), + ) + } + } + + @Test + fun `present - ensure current provider is registered with current distributor`() = runTest { + val lambda = lambdaRecorder> { _, _, _ -> + Result.success(Unit) + } + val sessionVerificationService = FakeSessionVerificationService() + sessionVerificationService.givenVerifiedStatus(SessionVerifiedStatus.Verified) + val distributor = Distributor("aDistributorValue1", "aDistributorName1") + val pushProvider = FakePushProvider( + index = 1, + name = "aFakePushProvider0", + isAvailable = true, + distributors = listOf( + Distributor("aDistributorValue0", "aDistributorName0"), + distributor, + ), + currentDistributor = { distributor }, + ) + val pushService = createFakePushService( + pushProvider1 = pushProvider, + currentPushProvider = { pushProvider }, + registerWithLambda = lambda, + ) + val presenter = createLoggedInPresenter( + pushService = pushService, + sessionVerificationService = sessionVerificationService, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + skipItems(2) + advanceUntilIdle() + lambda.assertions() + .isCalledOnce() + .with( + // MatrixClient + any(), + // Current push provider + value(pushProvider), + // Current distributor + value(distributor), + ) + } + } + + @Test + fun `present - if current push provider does not have current distributor, the first one is used`() = runTest { + val lambda = lambdaRecorder> { _, _, _ -> + Result.success(Unit) + } + val sessionVerificationService = FakeSessionVerificationService() + sessionVerificationService.givenVerifiedStatus(SessionVerifiedStatus.Verified) + val pushProvider = FakePushProvider( + index = 0, + name = "aFakePushProvider0", + isAvailable = true, + distributors = listOf( + Distributor("aDistributorValue0", "aDistributorName0"), + Distributor("aDistributorValue1", "aDistributorName1"), + ), + currentDistributor = { null }, + ) + val pushService = createFakePushService( + pushProvider0 = pushProvider, + currentPushProvider = { pushProvider }, + registerWithLambda = lambda, + ) + val presenter = createLoggedInPresenter( + pushService = pushService, + sessionVerificationService = sessionVerificationService, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + skipItems(2) + advanceUntilIdle() + lambda.assertions() + .isCalledOnce() + .with( + // MatrixClient + any(), + // PushProvider with highest priority (lower index) + value(pushService.getAvailablePushProviders()[0]), + // First distributor + value(pushService.getAvailablePushProviders()[0].getDistributors()[0]), + ) + } + } + + @Test + fun `present - if current push provider does not have distributors, nothing happen`() = runTest { + val lambda = lambdaRecorder> { _, _, _ -> + Result.success(Unit) + } + val sessionVerificationService = FakeSessionVerificationService() + sessionVerificationService.givenVerifiedStatus(SessionVerifiedStatus.Verified) + val pushProvider = FakePushProvider( + index = 0, + name = "aFakePushProvider0", + isAvailable = true, + distributors = emptyList(), + ) + val pushService = createFakePushService( + pushProvider0 = pushProvider, + currentPushProvider = { pushProvider }, + registerWithLambda = lambda, + ) + val presenter = createLoggedInPresenter( + pushService = pushService, + sessionVerificationService = sessionVerificationService, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + skipItems(2) + advanceUntilIdle() + lambda.assertions() + .isNeverCalled() + } + } + + @Test + fun `present - case no push provider available provider`() = runTest { + val lambda = lambdaRecorder> { _, _, _ -> + Result.success(Unit) + } + val sessionVerificationService = FakeSessionVerificationService() + sessionVerificationService.givenVerifiedStatus(SessionVerifiedStatus.Verified) + val pushService = createFakePushService( + pushProvider0 = null, + pushProvider1 = null, + registerWithLambda = lambda, + ) + val presenter = createLoggedInPresenter( + pushService = pushService, + sessionVerificationService = sessionVerificationService, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + skipItems(2) + advanceUntilIdle() + lambda.assertions() + .isNeverCalled() + } + } + + @Test + fun `present - case one push provider but no distributor available`() = runTest { + val lambda = lambdaRecorder> { _, _, _ -> + Result.success(Unit) + } + val sessionVerificationService = FakeSessionVerificationService() + sessionVerificationService.givenVerifiedStatus(SessionVerifiedStatus.Verified) + val pushService = createFakePushService( + pushProvider0 = FakePushProvider( + index = 1, + name = "aFakePushProvider1", + isAvailable = true, + distributors = emptyList(), + ), + pushProvider1 = null, + registerWithLambda = lambda, + ) + val presenter = createLoggedInPresenter( + pushService = pushService, + sessionVerificationService = sessionVerificationService, + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + skipItems(2) + advanceUntilIdle() + lambda.assertions() + .isNeverCalled() + } + } + + private fun createFakePushService( + pushProvider0: PushProvider? = FakePushProvider( + index = 0, + name = "aFakePushProvider0", + isAvailable = true, + distributors = listOf(Distributor("aDistributorValue0", "aDistributorName0")), + currentDistributor = { null }, + ), + pushProvider1: PushProvider? = FakePushProvider( + index = 1, + name = "aFakePushProvider1", + isAvailable = true, + distributors = listOf(Distributor("aDistributorValue1", "aDistributorName1")), + currentDistributor = { null }, + ), + registerWithLambda: suspend (MatrixClient, PushProvider, Distributor) -> Result = { _, _, _ -> + Result.success(Unit) + }, + currentPushProvider: () -> PushProvider? = { null }, + ): PushService { + return FakePushService( + availablePushProviders = listOfNotNull(pushProvider0, pushProvider1), + registerWithLambda = registerWithLambda, + currentPushProvider = currentPushProvider, + ) + } + private fun createLoggedInPresenter( roomListService: RoomListService = FakeRoomListService(), networkStatus: NetworkStatus = NetworkStatus.Offline, - analyticsService: FakeAnalyticsService = FakeAnalyticsService(), - encryptionService: FakeEncryptionService = FakeEncryptionService(), + analyticsService: AnalyticsService = FakeAnalyticsService(), + sessionVerificationService: SessionVerificationService = FakeSessionVerificationService(), + encryptionService: EncryptionService = FakeEncryptionService(), + pushService: PushService = FakePushService(), ): LoggedInPresenter { return LoggedInPresenter( matrixClient = FakeMatrixClient(roomListService = roomListService), networkMonitor = FakeNetworkMonitor(networkStatus), - pushService = FakePushService(), - sessionVerificationService = FakeSessionVerificationService(), + pushService = pushService, + sessionVerificationService = sessionVerificationService, analyticsService = analyticsService, encryptionService = encryptionService ) diff --git a/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/FakePushService.kt b/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/FakePushService.kt index 5e7d9e7ff1..0bf2da54ad 100644 --- a/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/FakePushService.kt +++ b/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/FakePushService.kt @@ -28,9 +28,10 @@ class FakePushService( private val registerWithLambda: suspend (MatrixClient, PushProvider, Distributor) -> Result = { _, _, _ -> Result.success(Unit) }, + private val currentPushProvider: () -> PushProvider? = { availablePushProviders.firstOrNull() }, ) : PushService { override suspend fun getCurrentPushProvider(): PushProvider? { - return registeredPushProvider ?: availablePushProviders.firstOrNull() + return registeredPushProvider ?: currentPushProvider() } override fun getAvailablePushProviders(): List { diff --git a/libraries/pushproviders/test/src/main/kotlin/io/element/android/libraries/pushproviders/test/FakePushProvider.kt b/libraries/pushproviders/test/src/main/kotlin/io/element/android/libraries/pushproviders/test/FakePushProvider.kt index 7b37d0d296..4f83cde911 100644 --- a/libraries/pushproviders/test/src/main/kotlin/io/element/android/libraries/pushproviders/test/FakePushProvider.kt +++ b/libraries/pushproviders/test/src/main/kotlin/io/element/android/libraries/pushproviders/test/FakePushProvider.kt @@ -27,6 +27,7 @@ class FakePushProvider( override val name: String = "aFakePushProvider", private val isAvailable: Boolean = true, private val distributors: List = listOf(Distributor("aDistributorValue", "aDistributorName")), + private val currentDistributor: () -> Distributor? = { distributors.firstOrNull() }, private val currentUserPushConfig: CurrentUserPushConfig? = null, private val registerWithResult: (MatrixClient, Distributor) -> Result = { _, _ -> lambdaError() }, private val unregisterWithResult: (MatrixClient) -> Result = { lambdaError() }, @@ -40,7 +41,7 @@ class FakePushProvider( } override suspend fun getCurrentDistributor(matrixClient: MatrixClient): Distributor? { - return distributors.firstOrNull() + return currentDistributor() } override suspend fun unregister(matrixClient: MatrixClient): Result {