Ensure that disabling (resp. enabling) notification unregisters (resp. registers) the pusher
This commit is contained in:
@@ -36,7 +36,7 @@ import io.element.android.libraries.matrix.api.sync.SyncService
|
|||||||
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
|
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
|
||||||
import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
|
import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
|
||||||
import io.element.android.libraries.push.api.PushService
|
import io.element.android.libraries.push.api.PushService
|
||||||
import io.element.android.libraries.pushproviders.api.RegistrationFailure
|
import io.element.android.libraries.push.api.PusherRegistrationFailure
|
||||||
import io.element.android.services.analytics.api.AnalyticsService
|
import io.element.android.services.analytics.api.AnalyticsService
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
@@ -71,7 +71,17 @@ class LoggedInPresenter(
|
|||||||
when (sessionVerifiedStatus) {
|
when (sessionVerifiedStatus) {
|
||||||
SessionVerifiedStatus.Unknown -> Unit
|
SessionVerifiedStatus.Unknown -> Unit
|
||||||
SessionVerifiedStatus.Verified -> {
|
SessionVerifiedStatus.Verified -> {
|
||||||
ensurePusherIsRegistered(pusherRegistrationState)
|
Timber.tag(pusherTag.value).d("Ensure pusher is registered")
|
||||||
|
pushService.ensurePusherIsRegistered(matrixClient).fold(
|
||||||
|
onSuccess = {
|
||||||
|
Timber.tag(pusherTag.value).d("Pusher registered")
|
||||||
|
pusherRegistrationState.value = AsyncData.Success(Unit)
|
||||||
|
},
|
||||||
|
onFailure = {
|
||||||
|
Timber.tag(pusherTag.value).e(it, "Failed to register pusher")
|
||||||
|
pusherRegistrationState.value = AsyncData.Failure(it)
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
SessionVerifiedStatus.NotVerified -> {
|
SessionVerifiedStatus.NotVerified -> {
|
||||||
pusherRegistrationState.value = AsyncData.Failure(PusherRegistrationFailure.AccountNotVerified())
|
pusherRegistrationState.value = AsyncData.Failure(PusherRegistrationFailure.AccountNotVerified())
|
||||||
@@ -133,59 +143,6 @@ class LoggedInPresenter(
|
|||||||
currentSlidingSyncVersion == SlidingSyncVersion.Proxy
|
currentSlidingSyncVersion == SlidingSyncVersion.Proxy
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun ensurePusherIsRegistered(pusherRegistrationState: MutableState<AsyncData<Unit>>) {
|
|
||||||
Timber.tag(pusherTag.value).d("Ensure pusher is registered")
|
|
||||||
val currentPushProvider = pushService.getCurrentPushProvider(matrixClient.sessionId)
|
|
||||||
val result = if (currentPushProvider == null) {
|
|
||||||
Timber.tag(pusherTag.value).d("Register with the first available push provider with at least one distributor")
|
|
||||||
val pushProvider = pushService.getAvailablePushProviders()
|
|
||||||
.firstOrNull { it.getDistributors().isNotEmpty() }
|
|
||||||
// Else fallback to the first available push provider (the list should never be empty)
|
|
||||||
?: pushService.getAvailablePushProviders().firstOrNull()
|
|
||||||
?: return Unit
|
|
||||||
.also { Timber.tag(pusherTag.value).w("No push providers available") }
|
|
||||||
.also { pusherRegistrationState.value = AsyncData.Failure(PusherRegistrationFailure.NoProvidersAvailable()) }
|
|
||||||
val distributor = pushProvider.getDistributors().firstOrNull()
|
|
||||||
?: return Unit
|
|
||||||
.also { Timber.tag(pusherTag.value).w("No distributors available") }
|
|
||||||
.also {
|
|
||||||
// In this case, consider the push provider is chosen.
|
|
||||||
pushService.selectPushProvider(matrixClient.sessionId, pushProvider)
|
|
||||||
}
|
|
||||||
.also { pusherRegistrationState.value = AsyncData.Failure(PusherRegistrationFailure.NoDistributorsAvailable()) }
|
|
||||||
pushService.registerWith(matrixClient, pushProvider, distributor)
|
|
||||||
} else {
|
|
||||||
val currentPushDistributor = currentPushProvider.getCurrentDistributor(matrixClient.sessionId)
|
|
||||||
if (currentPushDistributor == null) {
|
|
||||||
Timber.tag(pusherTag.value).d("Register with the first available distributor")
|
|
||||||
val distributor = currentPushProvider.getDistributors().firstOrNull()
|
|
||||||
?: return Unit
|
|
||||||
.also { Timber.tag(pusherTag.value).w("No distributors available") }
|
|
||||||
.also { pusherRegistrationState.value = AsyncData.Failure(PusherRegistrationFailure.NoDistributorsAvailable()) }
|
|
||||||
pushService.registerWith(matrixClient, currentPushProvider, distributor)
|
|
||||||
} else {
|
|
||||||
Timber.tag(pusherTag.value).d("Re-register with the current distributor")
|
|
||||||
pushService.registerWith(matrixClient, currentPushProvider, currentPushDistributor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result.fold(
|
|
||||||
onSuccess = {
|
|
||||||
Timber.tag(pusherTag.value).d("Pusher registered")
|
|
||||||
pusherRegistrationState.value = AsyncData.Success(Unit)
|
|
||||||
},
|
|
||||||
onFailure = {
|
|
||||||
Timber.tag(pusherTag.value).e(it, "Failed to register pusher")
|
|
||||||
if (it is RegistrationFailure) {
|
|
||||||
pusherRegistrationState.value = AsyncData.Failure(
|
|
||||||
PusherRegistrationFailure.RegistrationFailure(it.clientException, it.isRegisteringAgain)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
pusherRegistrationState.value = AsyncData.Failure(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun reportCryptoStatusToAnalytics(verificationState: SessionVerifiedStatus, recoveryState: RecoveryState) {
|
private fun reportCryptoStatusToAnalytics(verificationState: SessionVerifiedStatus, recoveryState: RecoveryState) {
|
||||||
// Update first the user property, to store the current status for that posthog user
|
// Update first the user property, to store the current status for that posthog user
|
||||||
val userVerificationState = verificationState.toAnalyticsUserPropertyValue()
|
val userVerificationState = verificationState.toAnalyticsUserPropertyValue()
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ package io.element.android.appnav.loggedin
|
|||||||
|
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||||
import io.element.android.libraries.architecture.AsyncData
|
import io.element.android.libraries.architecture.AsyncData
|
||||||
|
import io.element.android.libraries.push.api.PusherRegistrationFailure
|
||||||
|
|
||||||
open class LoggedInStateProvider : PreviewParameterProvider<LoggedInState> {
|
open class LoggedInStateProvider : PreviewParameterProvider<LoggedInState> {
|
||||||
override val values: Sequence<LoggedInState>
|
override val values: Sequence<LoggedInState>
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import io.element.android.libraries.designsystem.preview.ElementPreview
|
|||||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||||
import io.element.android.libraries.designsystem.utils.OnLifecycleEvent
|
import io.element.android.libraries.designsystem.utils.OnLifecycleEvent
|
||||||
import io.element.android.libraries.matrix.api.exception.isNetworkError
|
import io.element.android.libraries.matrix.api.exception.isNetworkError
|
||||||
|
import io.element.android.libraries.push.api.PusherRegistrationFailure
|
||||||
import io.element.android.libraries.ui.strings.CommonStrings
|
import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
|
|||||||
import io.element.android.libraries.matrix.test.sync.FakeSyncService
|
import io.element.android.libraries.matrix.test.sync.FakeSyncService
|
||||||
import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService
|
import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService
|
||||||
import io.element.android.libraries.push.api.PushService
|
import io.element.android.libraries.push.api.PushService
|
||||||
|
import io.element.android.libraries.push.api.PusherRegistrationFailure
|
||||||
import io.element.android.libraries.push.test.FakePushService
|
import io.element.android.libraries.push.test.FakePushService
|
||||||
import io.element.android.libraries.pushproviders.api.Distributor
|
import io.element.android.libraries.pushproviders.api.Distributor
|
||||||
import io.element.android.libraries.pushproviders.api.PushProvider
|
import io.element.android.libraries.pushproviders.api.PushProvider
|
||||||
@@ -42,7 +43,6 @@ import io.element.android.services.analytics.api.AnalyticsService
|
|||||||
import io.element.android.services.analytics.test.FakeAnalyticsService
|
import io.element.android.services.analytics.test.FakeAnalyticsService
|
||||||
import io.element.android.tests.testutils.WarmUpRule
|
import io.element.android.tests.testutils.WarmUpRule
|
||||||
import io.element.android.tests.testutils.consumeItemsUntilPredicate
|
import io.element.android.tests.testutils.consumeItemsUntilPredicate
|
||||||
import io.element.android.tests.testutils.lambda.any
|
|
||||||
import io.element.android.tests.testutils.lambda.lambdaError
|
import io.element.android.tests.testutils.lambda.lambdaError
|
||||||
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||||
import io.element.android.tests.testutils.lambda.value
|
import io.element.android.tests.testutils.lambda.value
|
||||||
@@ -115,7 +115,9 @@ class LoggedInPresenterTest {
|
|||||||
encryptionService = encryptionService,
|
encryptionService = encryptionService,
|
||||||
),
|
),
|
||||||
syncService = FakeSyncService(initialSyncState = SyncState.Running),
|
syncService = FakeSyncService(initialSyncState = SyncState.Running),
|
||||||
pushService = FakePushService(),
|
pushService = FakePushService(
|
||||||
|
ensurePusherIsRegisteredResult = { Result.success(Unit) },
|
||||||
|
),
|
||||||
sessionVerificationService = verificationService,
|
sessionVerificationService = verificationService,
|
||||||
analyticsService = analyticsService,
|
analyticsService = analyticsService,
|
||||||
encryptionService = encryptionService,
|
encryptionService = encryptionService,
|
||||||
@@ -139,10 +141,10 @@ class LoggedInPresenterTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - ensure default pusher is not registered if session is not verified`() = runTest {
|
fun `present - ensure default pusher is not registered if session is not verified`() = runTest {
|
||||||
val lambda = lambdaRecorder<MatrixClient, PushProvider, Distributor, Result<Unit>> { _, _, _ ->
|
val lambda = lambdaRecorder<Result<Unit>> {
|
||||||
Result.success(Unit)
|
Result.success(Unit)
|
||||||
}
|
}
|
||||||
val pushService = createFakePushService(registerWithLambda = lambda)
|
val pushService = createFakePushService(ensurePusherIsRegisteredResult = lambda)
|
||||||
val verificationService = FakeSessionVerificationService(
|
val verificationService = FakeSessionVerificationService(
|
||||||
initialSessionVerifiedStatus = SessionVerifiedStatus.NotVerified
|
initialSessionVerifiedStatus = SessionVerifiedStatus.NotVerified
|
||||||
)
|
)
|
||||||
@@ -153,21 +155,18 @@ class LoggedInPresenterTest {
|
|||||||
val finalState = awaitFirstItem()
|
val finalState = awaitFirstItem()
|
||||||
assertThat(finalState.pusherRegistrationState.errorOrNull())
|
assertThat(finalState.pusherRegistrationState.errorOrNull())
|
||||||
.isInstanceOf(PusherRegistrationFailure.AccountNotVerified::class.java)
|
.isInstanceOf(PusherRegistrationFailure.AccountNotVerified::class.java)
|
||||||
lambda.assertions()
|
lambda.assertions().isNeverCalled()
|
||||||
.isNeverCalled()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - ensure default pusher is registered with default provider`() = runTest {
|
fun `present - ensure default pusher is registered with default provider`() = runTest {
|
||||||
val lambda = lambdaRecorder<MatrixClient, PushProvider, Distributor, Result<Unit>> { _, _, _ ->
|
val lambda = lambdaRecorder<Result<Unit>> { Result.success(Unit) }
|
||||||
Result.success(Unit)
|
|
||||||
}
|
|
||||||
val sessionVerificationService = FakeSessionVerificationService(
|
val sessionVerificationService = FakeSessionVerificationService(
|
||||||
initialSessionVerifiedStatus = SessionVerifiedStatus.Verified
|
initialSessionVerifiedStatus = SessionVerifiedStatus.Verified
|
||||||
)
|
)
|
||||||
val pushService = createFakePushService(
|
val pushService = createFakePushService(
|
||||||
registerWithLambda = lambda,
|
ensurePusherIsRegisteredResult = lambda,
|
||||||
)
|
)
|
||||||
createLoggedInPresenter(
|
createLoggedInPresenter(
|
||||||
pushService = pushService,
|
pushService = pushService,
|
||||||
@@ -180,27 +179,17 @@ class LoggedInPresenterTest {
|
|||||||
assertThat(finalState.pusherRegistrationState.isSuccess()).isTrue()
|
assertThat(finalState.pusherRegistrationState.isSuccess()).isTrue()
|
||||||
lambda.assertions()
|
lambda.assertions()
|
||||||
.isCalledOnce()
|
.isCalledOnce()
|
||||||
.with(
|
|
||||||
// MatrixClient
|
|
||||||
any(),
|
|
||||||
// PushProvider with highest priority (lower index)
|
|
||||||
value(pushService.getAvailablePushProviders()[0]),
|
|
||||||
// First distributor
|
|
||||||
value(pushService.getAvailablePushProviders()[0].getDistributors()[0]),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - ensure default pusher is registered with default provider - fail to register`() = runTest {
|
fun `present - ensure default pusher is registered with default provider - fail to register`() = runTest {
|
||||||
val lambda = lambdaRecorder<MatrixClient, PushProvider, Distributor, Result<Unit>> { _, _, _ ->
|
val lambda = lambdaRecorder<Result<Unit>> { Result.failure(AN_EXCEPTION) }
|
||||||
Result.failure(AN_EXCEPTION)
|
|
||||||
}
|
|
||||||
val sessionVerificationService = FakeSessionVerificationService(
|
val sessionVerificationService = FakeSessionVerificationService(
|
||||||
initialSessionVerifiedStatus = SessionVerifiedStatus.Verified
|
initialSessionVerifiedStatus = SessionVerifiedStatus.Verified
|
||||||
)
|
)
|
||||||
val pushService = createFakePushService(
|
val pushService = createFakePushService(
|
||||||
registerWithLambda = lambda,
|
ensurePusherIsRegisteredResult = lambda,
|
||||||
)
|
)
|
||||||
createLoggedInPresenter(
|
createLoggedInPresenter(
|
||||||
pushService = pushService,
|
pushService = pushService,
|
||||||
@@ -213,158 +202,36 @@ class LoggedInPresenterTest {
|
|||||||
assertThat(finalState.pusherRegistrationState.isFailure()).isTrue()
|
assertThat(finalState.pusherRegistrationState.isFailure()).isTrue()
|
||||||
lambda.assertions()
|
lambda.assertions()
|
||||||
.isCalledOnce()
|
.isCalledOnce()
|
||||||
.with(
|
// Reset the error and do not show again
|
||||||
// MatrixClient
|
finalState.eventSink(LoggedInEvents.CloseErrorDialog(doNotShowAgain = false))
|
||||||
any(),
|
val lastState = awaitItem()
|
||||||
// PushProvider with highest priority (lower index)
|
assertThat(lastState.pusherRegistrationState.isUninitialized()).isTrue()
|
||||||
value(pushService.getAvailablePushProviders()[0]),
|
assertThat(lastState.ignoreRegistrationError).isFalse()
|
||||||
// First distributor
|
|
||||||
value(pushService.getAvailablePushProviders()[0].getDistributors()[0]),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - ensure current provider is registered with current distributor`() = runTest {
|
fun `present - ensure default pusher is registered with default provider - fail to register - do not show again`() = runTest {
|
||||||
val lambda = lambdaRecorder<MatrixClient, PushProvider, Distributor, Result<Unit>> { _, _, _ ->
|
val lambda = lambdaRecorder<Result<Unit>> { Result.failure(AN_EXCEPTION) }
|
||||||
Result.success(Unit)
|
|
||||||
}
|
|
||||||
val sessionVerificationService = FakeSessionVerificationService(
|
|
||||||
initialSessionVerifiedStatus = SessionVerifiedStatus.Verified
|
|
||||||
)
|
|
||||||
val distributor = Distributor("aDistributorValue1", "aDistributorName1")
|
|
||||||
val pushProvider = FakePushProvider(
|
|
||||||
index = 0,
|
|
||||||
name = "aFakePushProvider0",
|
|
||||||
distributors = listOf(
|
|
||||||
Distributor("aDistributorValue0", "aDistributorName0"),
|
|
||||||
distributor,
|
|
||||||
),
|
|
||||||
currentDistributor = { distributor },
|
|
||||||
)
|
|
||||||
val pushService = createFakePushService(
|
|
||||||
pushProvider1 = pushProvider,
|
|
||||||
currentPushProvider = { pushProvider },
|
|
||||||
registerWithLambda = lambda,
|
|
||||||
)
|
|
||||||
createLoggedInPresenter(
|
|
||||||
pushService = pushService,
|
|
||||||
sessionVerificationService = sessionVerificationService,
|
|
||||||
matrixClient = FakeMatrixClient(
|
|
||||||
accountManagementUrlResult = { Result.success(null) },
|
|
||||||
),
|
|
||||||
).test {
|
|
||||||
val finalState = awaitFirstItem()
|
|
||||||
assertThat(finalState.pusherRegistrationState.isSuccess()).isTrue()
|
|
||||||
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<MatrixClient, PushProvider, Distributor, Result<Unit>> { _, _, _ ->
|
|
||||||
Result.success(Unit)
|
|
||||||
}
|
|
||||||
val sessionVerificationService = FakeSessionVerificationService(
|
|
||||||
initialSessionVerifiedStatus = SessionVerifiedStatus.Verified
|
|
||||||
)
|
|
||||||
val pushProvider = FakePushProvider(
|
|
||||||
index = 0,
|
|
||||||
name = "aFakePushProvider0",
|
|
||||||
distributors = listOf(
|
|
||||||
Distributor("aDistributorValue0", "aDistributorName0"),
|
|
||||||
Distributor("aDistributorValue1", "aDistributorName1"),
|
|
||||||
),
|
|
||||||
currentDistributor = { null },
|
|
||||||
)
|
|
||||||
val pushService = createFakePushService(
|
|
||||||
pushProvider0 = pushProvider,
|
|
||||||
currentPushProvider = { pushProvider },
|
|
||||||
registerWithLambda = lambda,
|
|
||||||
)
|
|
||||||
createLoggedInPresenter(
|
|
||||||
pushService = pushService,
|
|
||||||
sessionVerificationService = sessionVerificationService,
|
|
||||||
matrixClient = FakeMatrixClient(
|
|
||||||
accountManagementUrlResult = { Result.success(null) },
|
|
||||||
),
|
|
||||||
).test {
|
|
||||||
val finalState = awaitFirstItem()
|
|
||||||
assertThat(finalState.pusherRegistrationState.isSuccess()).isTrue()
|
|
||||||
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<MatrixClient, PushProvider, Distributor, Result<Unit>> { _, _, _ ->
|
|
||||||
Result.success(Unit)
|
|
||||||
}
|
|
||||||
val sessionVerificationService = FakeSessionVerificationService(
|
|
||||||
initialSessionVerifiedStatus = SessionVerifiedStatus.Verified
|
|
||||||
)
|
|
||||||
val pushProvider = FakePushProvider(
|
|
||||||
index = 0,
|
|
||||||
name = "aFakePushProvider0",
|
|
||||||
distributors = emptyList(),
|
|
||||||
)
|
|
||||||
val pushService = createFakePushService(
|
|
||||||
pushProvider0 = pushProvider,
|
|
||||||
currentPushProvider = { pushProvider },
|
|
||||||
registerWithLambda = lambda,
|
|
||||||
)
|
|
||||||
createLoggedInPresenter(
|
|
||||||
pushService = pushService,
|
|
||||||
sessionVerificationService = sessionVerificationService,
|
|
||||||
).test {
|
|
||||||
val finalState = awaitFirstItem()
|
|
||||||
assertThat(finalState.pusherRegistrationState.errorOrNull())
|
|
||||||
.isInstanceOf(PusherRegistrationFailure.NoDistributorsAvailable::class.java)
|
|
||||||
lambda.assertions()
|
|
||||||
.isNeverCalled()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `present - case no push provider available provider`() = runTest {
|
|
||||||
val lambda = lambdaRecorder<MatrixClient, PushProvider, Distributor, Result<Unit>> { _, _, _ ->
|
|
||||||
Result.success(Unit)
|
|
||||||
}
|
|
||||||
val sessionVerificationService = FakeSessionVerificationService(SessionVerifiedStatus.Verified)
|
|
||||||
val setIgnoreRegistrationErrorLambda = lambdaRecorder<SessionId, Boolean, Unit> { _, _ -> }
|
val setIgnoreRegistrationErrorLambda = lambdaRecorder<SessionId, Boolean, Unit> { _, _ -> }
|
||||||
|
val sessionVerificationService = FakeSessionVerificationService(
|
||||||
|
initialSessionVerifiedStatus = SessionVerifiedStatus.Verified
|
||||||
|
)
|
||||||
val pushService = createFakePushService(
|
val pushService = createFakePushService(
|
||||||
pushProvider0 = null,
|
ensurePusherIsRegisteredResult = lambda,
|
||||||
pushProvider1 = null,
|
|
||||||
registerWithLambda = lambda,
|
|
||||||
setIgnoreRegistrationErrorLambda = setIgnoreRegistrationErrorLambda,
|
setIgnoreRegistrationErrorLambda = setIgnoreRegistrationErrorLambda,
|
||||||
)
|
)
|
||||||
createLoggedInPresenter(
|
createLoggedInPresenter(
|
||||||
pushService = pushService,
|
pushService = pushService,
|
||||||
sessionVerificationService = sessionVerificationService,
|
sessionVerificationService = sessionVerificationService,
|
||||||
|
matrixClient = FakeMatrixClient(
|
||||||
|
accountManagementUrlResult = { Result.success(null) },
|
||||||
|
),
|
||||||
).test {
|
).test {
|
||||||
val finalState = awaitFirstItem()
|
val finalState = awaitFirstItem()
|
||||||
assertThat(finalState.pusherRegistrationState.errorOrNull())
|
assertThat(finalState.pusherRegistrationState.isFailure()).isTrue()
|
||||||
.isInstanceOf(PusherRegistrationFailure.NoProvidersAvailable::class.java)
|
|
||||||
lambda.assertions()
|
lambda.assertions()
|
||||||
.isNeverCalled()
|
.isCalledOnce()
|
||||||
// Reset the error and do not show again
|
// Reset the error and do not show again
|
||||||
finalState.eventSink(LoggedInEvents.CloseErrorDialog(doNotShowAgain = true))
|
finalState.eventSink(LoggedInEvents.CloseErrorDialog(doNotShowAgain = true))
|
||||||
skipItems(1)
|
skipItems(1)
|
||||||
@@ -382,95 +249,6 @@ class LoggedInPresenterTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `present - case one push provider but no distributor available`() = runTest {
|
|
||||||
val lambda = lambdaRecorder<MatrixClient, PushProvider, Distributor, Result<Unit>> { _, _, _ ->
|
|
||||||
Result.success(Unit)
|
|
||||||
}
|
|
||||||
val selectPushProviderLambda = lambdaRecorder<SessionId, PushProvider, Unit> { _, _ -> }
|
|
||||||
val sessionVerificationService = FakeSessionVerificationService(
|
|
||||||
initialSessionVerifiedStatus = SessionVerifiedStatus.Verified
|
|
||||||
)
|
|
||||||
val pushProvider = FakePushProvider(
|
|
||||||
index = 0,
|
|
||||||
name = "aFakePushProvider",
|
|
||||||
distributors = emptyList(),
|
|
||||||
)
|
|
||||||
val pushService = createFakePushService(
|
|
||||||
pushProvider0 = pushProvider,
|
|
||||||
pushProvider1 = null,
|
|
||||||
registerWithLambda = lambda,
|
|
||||||
selectPushProviderLambda = selectPushProviderLambda,
|
|
||||||
)
|
|
||||||
createLoggedInPresenter(
|
|
||||||
pushService = pushService,
|
|
||||||
sessionVerificationService = sessionVerificationService,
|
|
||||||
).test {
|
|
||||||
val finalState = awaitFirstItem()
|
|
||||||
assertThat(finalState.pusherRegistrationState.errorOrNull())
|
|
||||||
.isInstanceOf(PusherRegistrationFailure.NoDistributorsAvailable::class.java)
|
|
||||||
lambda.assertions()
|
|
||||||
.isNeverCalled()
|
|
||||||
selectPushProviderLambda.assertions()
|
|
||||||
.isCalledOnce()
|
|
||||||
.with(
|
|
||||||
// SessionId
|
|
||||||
value(A_SESSION_ID),
|
|
||||||
// PushProvider
|
|
||||||
value(pushProvider),
|
|
||||||
)
|
|
||||||
// Reset the error
|
|
||||||
finalState.eventSink(LoggedInEvents.CloseErrorDialog(doNotShowAgain = false))
|
|
||||||
val lastState = awaitItem()
|
|
||||||
assertThat(lastState.pusherRegistrationState.isUninitialized()).isTrue()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `present - case two push providers but first one does not have distributor - second one will be used`() = runTest {
|
|
||||||
val lambda = lambdaRecorder<MatrixClient, PushProvider, Distributor, Result<Unit>> { _, _, _ ->
|
|
||||||
Result.success(Unit)
|
|
||||||
}
|
|
||||||
val sessionVerificationService = FakeSessionVerificationService(
|
|
||||||
initialSessionVerifiedStatus = SessionVerifiedStatus.Verified
|
|
||||||
)
|
|
||||||
val pushProvider0 = FakePushProvider(
|
|
||||||
index = 0,
|
|
||||||
name = "aFakePushProvider0",
|
|
||||||
distributors = emptyList(),
|
|
||||||
)
|
|
||||||
val distributor = Distributor("aDistributorValue1", "aDistributorName1")
|
|
||||||
val pushProvider1 = FakePushProvider(
|
|
||||||
index = 1,
|
|
||||||
name = "aFakePushProvider1",
|
|
||||||
distributors = listOf(distributor),
|
|
||||||
)
|
|
||||||
val pushService = createFakePushService(
|
|
||||||
pushProvider0 = pushProvider0,
|
|
||||||
pushProvider1 = pushProvider1,
|
|
||||||
registerWithLambda = lambda,
|
|
||||||
)
|
|
||||||
createLoggedInPresenter(
|
|
||||||
pushService = pushService,
|
|
||||||
sessionVerificationService = sessionVerificationService,
|
|
||||||
matrixClient = FakeMatrixClient(
|
|
||||||
accountManagementUrlResult = { Result.success(null) },
|
|
||||||
),
|
|
||||||
).test {
|
|
||||||
val finalState = awaitFirstItem()
|
|
||||||
assertThat(finalState.pusherRegistrationState.isSuccess()).isTrue()
|
|
||||||
lambda.assertions().isCalledOnce()
|
|
||||||
.with(
|
|
||||||
// MatrixClient
|
|
||||||
any(),
|
|
||||||
// PushProvider with the distributor
|
|
||||||
value(pushProvider1),
|
|
||||||
// First distributor of second push provider
|
|
||||||
value(distributor),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createFakePushService(
|
private fun createFakePushService(
|
||||||
pushProvider0: PushProvider? = FakePushProvider(
|
pushProvider0: PushProvider? = FakePushProvider(
|
||||||
index = 0,
|
index = 0,
|
||||||
@@ -484,7 +262,7 @@ class LoggedInPresenterTest {
|
|||||||
distributors = listOf(Distributor("aDistributorValue1", "aDistributorName1")),
|
distributors = listOf(Distributor("aDistributorValue1", "aDistributorName1")),
|
||||||
currentDistributor = { null },
|
currentDistributor = { null },
|
||||||
),
|
),
|
||||||
registerWithLambda: (MatrixClient, PushProvider, Distributor) -> Result<Unit> = { _, _, _ ->
|
ensurePusherIsRegisteredResult: () -> Result<Unit> = {
|
||||||
Result.success(Unit)
|
Result.success(Unit)
|
||||||
},
|
},
|
||||||
selectPushProviderLambda: (SessionId, PushProvider) -> Unit = { _, _ -> lambdaError() },
|
selectPushProviderLambda: (SessionId, PushProvider) -> Unit = { _, _ -> lambdaError() },
|
||||||
@@ -493,7 +271,7 @@ class LoggedInPresenterTest {
|
|||||||
): PushService {
|
): PushService {
|
||||||
return FakePushService(
|
return FakePushService(
|
||||||
availablePushProviders = listOfNotNull(pushProvider0, pushProvider1),
|
availablePushProviders = listOfNotNull(pushProvider0, pushProvider1),
|
||||||
registerWithLambda = registerWithLambda,
|
ensurePusherIsRegisteredResult = ensurePusherIsRegisteredResult,
|
||||||
currentPushProvider = currentPushProvider,
|
currentPushProvider = currentPushProvider,
|
||||||
selectPushProviderLambda = selectPushProviderLambda,
|
selectPushProviderLambda = selectPushProviderLambda,
|
||||||
setIgnoreRegistrationErrorLambda = setIgnoreRegistrationErrorLambda,
|
setIgnoreRegistrationErrorLambda = setIgnoreRegistrationErrorLambda,
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import io.element.android.libraries.architecture.AsyncData
|
|||||||
import io.element.android.libraries.architecture.Presenter
|
import io.element.android.libraries.architecture.Presenter
|
||||||
import io.element.android.libraries.architecture.runUpdatingStateNoSuccess
|
import io.element.android.libraries.architecture.runUpdatingStateNoSuccess
|
||||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||||
|
import io.element.android.libraries.di.annotations.SessionCoroutineScope
|
||||||
import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState
|
import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService
|
import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService
|
||||||
@@ -51,6 +52,8 @@ class NotificationSettingsPresenter(
|
|||||||
private val pushService: PushService,
|
private val pushService: PushService,
|
||||||
private val systemNotificationsEnabledProvider: SystemNotificationsEnabledProvider,
|
private val systemNotificationsEnabledProvider: SystemNotificationsEnabledProvider,
|
||||||
private val fullScreenIntentPermissionsPresenter: Presenter<FullScreenIntentPermissionsState>,
|
private val fullScreenIntentPermissionsPresenter: Presenter<FullScreenIntentPermissionsState>,
|
||||||
|
@SessionCoroutineScope
|
||||||
|
private val sessionCoroutineScope: CoroutineScope,
|
||||||
) : Presenter<NotificationSettingsState> {
|
) : Presenter<NotificationSettingsState> {
|
||||||
@Composable
|
@Composable
|
||||||
override fun present(): NotificationSettingsState {
|
override fun present(): NotificationSettingsState {
|
||||||
@@ -141,7 +144,7 @@ class NotificationSettingsPresenter(
|
|||||||
is NotificationSettingsEvents.SetInviteForMeNotificationsEnabled -> {
|
is NotificationSettingsEvents.SetInviteForMeNotificationsEnabled -> {
|
||||||
localCoroutineScope.setInviteForMeNotificationsEnabled(event.enabled, changeNotificationSettingAction)
|
localCoroutineScope.setInviteForMeNotificationsEnabled(event.enabled, changeNotificationSettingAction)
|
||||||
}
|
}
|
||||||
is NotificationSettingsEvents.SetNotificationsEnabled -> localCoroutineScope.setNotificationsEnabled(userPushStore, event.enabled)
|
is NotificationSettingsEvents.SetNotificationsEnabled -> sessionCoroutineScope.setNotificationsEnabled(userPushStore, event.enabled)
|
||||||
NotificationSettingsEvents.ClearConfigurationMismatchError -> {
|
NotificationSettingsEvents.ClearConfigurationMismatchError -> {
|
||||||
matrixSettings.value = NotificationSettingsState.MatrixSettings.Invalid(fixFailed = false)
|
matrixSettings.value = NotificationSettingsState.MatrixSettings.Invalid(fixFailed = false)
|
||||||
}
|
}
|
||||||
@@ -262,5 +265,10 @@ class NotificationSettingsPresenter(
|
|||||||
|
|
||||||
private fun CoroutineScope.setNotificationsEnabled(userPushStore: UserPushStore, enabled: Boolean) = launch {
|
private fun CoroutineScope.setNotificationsEnabled(userPushStore: UserPushStore, enabled: Boolean) = launch {
|
||||||
userPushStore.setNotificationEnabledForDevice(enabled)
|
userPushStore.setNotificationEnabledForDevice(enabled)
|
||||||
|
if (enabled) {
|
||||||
|
pushService.ensurePusherIsRegistered(matrixClient)
|
||||||
|
} else {
|
||||||
|
pushService.getCurrentPushProvider(matrixClient.sessionId)?.unregister(matrixClient)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +8,6 @@
|
|||||||
|
|
||||||
package io.element.android.features.preferences.impl.notifications
|
package io.element.android.features.preferences.impl.notifications
|
||||||
|
|
||||||
import app.cash.molecule.RecompositionMode
|
|
||||||
import app.cash.molecule.moleculeFlow
|
|
||||||
import app.cash.turbine.test
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import io.element.android.libraries.architecture.AsyncData
|
import io.element.android.libraries.architecture.AsyncData
|
||||||
import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState
|
import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState
|
||||||
@@ -28,6 +25,9 @@ import io.element.android.libraries.pushproviders.test.FakePushProvider
|
|||||||
import io.element.android.libraries.pushstore.test.userpushstore.FakeUserPushStoreFactory
|
import io.element.android.libraries.pushstore.test.userpushstore.FakeUserPushStoreFactory
|
||||||
import io.element.android.tests.testutils.awaitLastSequentialItem
|
import io.element.android.tests.testutils.awaitLastSequentialItem
|
||||||
import io.element.android.tests.testutils.consumeItemsUntilPredicate
|
import io.element.android.tests.testutils.consumeItemsUntilPredicate
|
||||||
|
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||||
|
import io.element.android.tests.testutils.test
|
||||||
|
import kotlinx.coroutines.test.TestScope
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import kotlin.time.Duration.Companion.milliseconds
|
import kotlin.time.Duration.Companion.milliseconds
|
||||||
@@ -36,9 +36,7 @@ class NotificationSettingsPresenterTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `present - ensures initial state is correct`() = runTest {
|
fun `present - ensures initial state is correct`() = runTest {
|
||||||
val presenter = createNotificationSettingsPresenter()
|
val presenter = createNotificationSettingsPresenter()
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
presenter.test {
|
||||||
presenter.present()
|
|
||||||
}.test {
|
|
||||||
val initialState = awaitItem()
|
val initialState = awaitItem()
|
||||||
assertThat(initialState.appSettings.appNotificationsEnabled).isFalse()
|
assertThat(initialState.appSettings.appNotificationsEnabled).isFalse()
|
||||||
assertThat(initialState.appSettings.systemNotificationsEnabled).isTrue()
|
assertThat(initialState.appSettings.systemNotificationsEnabled).isTrue()
|
||||||
@@ -62,9 +60,7 @@ class NotificationSettingsPresenterTest {
|
|||||||
fun `present - default group notification mode changed`() = runTest {
|
fun `present - default group notification mode changed`() = runTest {
|
||||||
val notificationSettingsService = FakeNotificationSettingsService()
|
val notificationSettingsService = FakeNotificationSettingsService()
|
||||||
val presenter = createNotificationSettingsPresenter(notificationSettingsService)
|
val presenter = createNotificationSettingsPresenter(notificationSettingsService)
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
presenter.test {
|
||||||
presenter.present()
|
|
||||||
}.test {
|
|
||||||
notificationSettingsService.setDefaultRoomNotificationMode(isEncrypted = true, isOneToOne = false, mode = RoomNotificationMode.ALL_MESSAGES)
|
notificationSettingsService.setDefaultRoomNotificationMode(isEncrypted = true, isOneToOne = false, mode = RoomNotificationMode.ALL_MESSAGES)
|
||||||
notificationSettingsService.setDefaultRoomNotificationMode(isEncrypted = false, isOneToOne = false, mode = RoomNotificationMode.ALL_MESSAGES)
|
notificationSettingsService.setDefaultRoomNotificationMode(isEncrypted = false, isOneToOne = false, mode = RoomNotificationMode.ALL_MESSAGES)
|
||||||
val updatedState = consumeItemsUntilPredicate {
|
val updatedState = consumeItemsUntilPredicate {
|
||||||
@@ -80,9 +76,7 @@ class NotificationSettingsPresenterTest {
|
|||||||
fun `present - notification settings mismatched`() = runTest {
|
fun `present - notification settings mismatched`() = runTest {
|
||||||
val notificationSettingsService = FakeNotificationSettingsService()
|
val notificationSettingsService = FakeNotificationSettingsService()
|
||||||
val presenter = createNotificationSettingsPresenter(notificationSettingsService)
|
val presenter = createNotificationSettingsPresenter(notificationSettingsService)
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
presenter.test {
|
||||||
presenter.present()
|
|
||||||
}.test {
|
|
||||||
notificationSettingsService.setDefaultRoomNotificationMode(
|
notificationSettingsService.setDefaultRoomNotificationMode(
|
||||||
isEncrypted = true,
|
isEncrypted = true,
|
||||||
isOneToOne = false,
|
isOneToOne = false,
|
||||||
@@ -110,9 +104,7 @@ class NotificationSettingsPresenterTest {
|
|||||||
initialOneToOneDefaultMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY
|
initialOneToOneDefaultMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY
|
||||||
)
|
)
|
||||||
val presenter = createNotificationSettingsPresenter(notificationSettingsService)
|
val presenter = createNotificationSettingsPresenter(notificationSettingsService)
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
presenter.test {
|
||||||
presenter.present()
|
|
||||||
}.test {
|
|
||||||
val initialState = awaitItem()
|
val initialState = awaitItem()
|
||||||
initialState.eventSink(NotificationSettingsEvents.FixConfigurationMismatch)
|
initialState.eventSink(NotificationSettingsEvents.FixConfigurationMismatch)
|
||||||
val fixedState = consumeItemsUntilPredicate(timeout = 2000.milliseconds) {
|
val fixedState = consumeItemsUntilPredicate(timeout = 2000.milliseconds) {
|
||||||
@@ -125,10 +117,19 @@ class NotificationSettingsPresenterTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - set notifications enabled`() = runTest {
|
fun `present - set notifications enabled`() = runTest {
|
||||||
val presenter = createNotificationSettingsPresenter()
|
val unregisterWithResult = lambdaRecorder<MatrixClient, Result<Unit>> { Result.success(Unit) }
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
val ensurePusherIsRegisteredResult = lambdaRecorder<Result<Unit>> { Result.success(Unit) }
|
||||||
presenter.present()
|
val presenter = createNotificationSettingsPresenter(
|
||||||
}.test {
|
pushService = FakePushService(
|
||||||
|
currentPushProvider = {
|
||||||
|
FakePushProvider(
|
||||||
|
unregisterWithResult = unregisterWithResult,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
ensurePusherIsRegisteredResult = ensurePusherIsRegisteredResult,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
presenter.test {
|
||||||
val loadedState = consumeItemsUntilPredicate {
|
val loadedState = consumeItemsUntilPredicate {
|
||||||
it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid
|
it.matrixSettings is NotificationSettingsState.MatrixSettings.Valid
|
||||||
}.last()
|
}.last()
|
||||||
@@ -138,16 +139,21 @@ class NotificationSettingsPresenterTest {
|
|||||||
!it.appSettings.appNotificationsEnabled
|
!it.appSettings.appNotificationsEnabled
|
||||||
}.last()
|
}.last()
|
||||||
assertThat(updatedState.appSettings.appNotificationsEnabled).isFalse()
|
assertThat(updatedState.appSettings.appNotificationsEnabled).isFalse()
|
||||||
cancelAndIgnoreRemainingEvents()
|
unregisterWithResult.assertions().isCalledOnce()
|
||||||
|
// Enable notification again
|
||||||
|
loadedState.eventSink(NotificationSettingsEvents.SetNotificationsEnabled(true))
|
||||||
|
val updatedState2 = consumeItemsUntilPredicate {
|
||||||
|
it.appSettings.appNotificationsEnabled
|
||||||
|
}.last()
|
||||||
|
assertThat(updatedState2.appSettings.appNotificationsEnabled).isTrue()
|
||||||
|
ensurePusherIsRegisteredResult.assertions().isCalledOnce()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - set call notifications enabled`() = runTest {
|
fun `present - set call notifications enabled`() = runTest {
|
||||||
val presenter = createNotificationSettingsPresenter()
|
val presenter = createNotificationSettingsPresenter()
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
presenter.test {
|
||||||
presenter.present()
|
|
||||||
}.test {
|
|
||||||
val loadedState = consumeItemsUntilPredicate {
|
val loadedState = consumeItemsUntilPredicate {
|
||||||
(it.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid)?.callNotificationsEnabled == false
|
(it.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid)?.callNotificationsEnabled == false
|
||||||
}.last()
|
}.last()
|
||||||
@@ -166,9 +172,7 @@ class NotificationSettingsPresenterTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `present - set invite for me notifications enabled`() = runTest {
|
fun `present - set invite for me notifications enabled`() = runTest {
|
||||||
val presenter = createNotificationSettingsPresenter()
|
val presenter = createNotificationSettingsPresenter()
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
presenter.test {
|
||||||
presenter.present()
|
|
||||||
}.test {
|
|
||||||
val loadedState = consumeItemsUntilPredicate {
|
val loadedState = consumeItemsUntilPredicate {
|
||||||
(it.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid)?.inviteForMeNotificationsEnabled == false
|
(it.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid)?.inviteForMeNotificationsEnabled == false
|
||||||
}.last()
|
}.last()
|
||||||
@@ -187,9 +191,7 @@ class NotificationSettingsPresenterTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `present - set atRoom notifications enabled`() = runTest {
|
fun `present - set atRoom notifications enabled`() = runTest {
|
||||||
val presenter = createNotificationSettingsPresenter()
|
val presenter = createNotificationSettingsPresenter()
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
presenter.test {
|
||||||
presenter.present()
|
|
||||||
}.test {
|
|
||||||
val loadedState = consumeItemsUntilPredicate {
|
val loadedState = consumeItemsUntilPredicate {
|
||||||
(it.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid)?.atRoomNotificationsEnabled == false
|
(it.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid)?.atRoomNotificationsEnabled == false
|
||||||
}.last()
|
}.last()
|
||||||
@@ -210,9 +212,7 @@ class NotificationSettingsPresenterTest {
|
|||||||
val notificationSettingsService = FakeNotificationSettingsService()
|
val notificationSettingsService = FakeNotificationSettingsService()
|
||||||
val presenter = createNotificationSettingsPresenter(notificationSettingsService)
|
val presenter = createNotificationSettingsPresenter(notificationSettingsService)
|
||||||
notificationSettingsService.givenSetAtRoomError(AN_EXCEPTION)
|
notificationSettingsService.givenSetAtRoomError(AN_EXCEPTION)
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
presenter.test {
|
||||||
presenter.present()
|
|
||||||
}.test {
|
|
||||||
val loadedState = consumeItemsUntilPredicate {
|
val loadedState = consumeItemsUntilPredicate {
|
||||||
(it.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid)?.atRoomNotificationsEnabled == false
|
(it.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid)?.atRoomNotificationsEnabled == false
|
||||||
}.last()
|
}.last()
|
||||||
@@ -237,9 +237,7 @@ class NotificationSettingsPresenterTest {
|
|||||||
val presenter = createNotificationSettingsPresenter(
|
val presenter = createNotificationSettingsPresenter(
|
||||||
pushService = createFakePushService(),
|
pushService = createFakePushService(),
|
||||||
)
|
)
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
presenter.test {
|
||||||
presenter.present()
|
|
||||||
}.test {
|
|
||||||
val initialState = awaitLastSequentialItem()
|
val initialState = awaitLastSequentialItem()
|
||||||
assertThat(initialState.currentPushDistributor).isEqualTo(AsyncData.Success(Distributor(value = "aDistributorValue0", name = "aDistributorName0")))
|
assertThat(initialState.currentPushDistributor).isEqualTo(AsyncData.Success(Distributor(value = "aDistributorValue0", name = "aDistributorName0")))
|
||||||
assertThat(initialState.availablePushDistributors).containsExactly(
|
assertThat(initialState.availablePushDistributors).containsExactly(
|
||||||
@@ -271,9 +269,7 @@ class NotificationSettingsPresenterTest {
|
|||||||
val presenter = createNotificationSettingsPresenter(
|
val presenter = createNotificationSettingsPresenter(
|
||||||
pushService = createFakePushService(),
|
pushService = createFakePushService(),
|
||||||
)
|
)
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
presenter.test {
|
||||||
presenter.present()
|
|
||||||
}.test {
|
|
||||||
val initialState = awaitLastSequentialItem()
|
val initialState = awaitLastSequentialItem()
|
||||||
assertThat(initialState.currentPushDistributor).isEqualTo(AsyncData.Success(Distributor(value = "aDistributorValue0", name = "aDistributorName0")))
|
assertThat(initialState.currentPushDistributor).isEqualTo(AsyncData.Success(Distributor(value = "aDistributorValue0", name = "aDistributorName0")))
|
||||||
assertThat(initialState.availablePushDistributors).containsExactly(
|
assertThat(initialState.availablePushDistributors).containsExactly(
|
||||||
@@ -298,9 +294,7 @@ class NotificationSettingsPresenterTest {
|
|||||||
pushService = createFakePushService(),
|
pushService = createFakePushService(),
|
||||||
fullScreenIntentPermissionsStateLambda = fullScreenIntentPermissionsStateLambda,
|
fullScreenIntentPermissionsStateLambda = fullScreenIntentPermissionsStateLambda,
|
||||||
)
|
)
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
presenter.test {
|
||||||
presenter.present()
|
|
||||||
}.test {
|
|
||||||
val initialState = awaitLastSequentialItem()
|
val initialState = awaitLastSequentialItem()
|
||||||
assertThat(initialState.fullScreenIntentPermissionsState.permissionGranted).isFalse()
|
assertThat(initialState.fullScreenIntentPermissionsState.permissionGranted).isFalse()
|
||||||
|
|
||||||
@@ -324,11 +318,7 @@ class NotificationSettingsPresenterTest {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
presenter.test {
|
||||||
presenter.present()
|
|
||||||
}.test {
|
|
||||||
val initialState = awaitLastSequentialItem()
|
|
||||||
initialState.eventSink.invoke(NotificationSettingsEvents.ChangePushProvider)
|
|
||||||
val withDialog = awaitItem()
|
val withDialog = awaitItem()
|
||||||
assertThat(withDialog.showChangePushProviderDialog).isTrue()
|
assertThat(withDialog.showChangePushProviderDialog).isTrue()
|
||||||
withDialog.eventSink(NotificationSettingsEvents.SetPushProvider(1))
|
withDialog.eventSink(NotificationSettingsEvents.SetPushProvider(1))
|
||||||
@@ -361,7 +351,7 @@ class NotificationSettingsPresenterTest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createNotificationSettingsPresenter(
|
private fun TestScope.createNotificationSettingsPresenter(
|
||||||
notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService(),
|
notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService(),
|
||||||
pushService: PushService = FakePushService(),
|
pushService: PushService = FakePushService(),
|
||||||
fullScreenIntentPermissionsStateLambda: () -> FullScreenIntentPermissionsState = { aFullScreenIntentPermissionsState() },
|
fullScreenIntentPermissionsStateLambda: () -> FullScreenIntentPermissionsState = { aFullScreenIntentPermissionsState() },
|
||||||
@@ -374,6 +364,7 @@ class NotificationSettingsPresenterTest {
|
|||||||
pushService = pushService,
|
pushService = pushService,
|
||||||
systemNotificationsEnabledProvider = FakeSystemNotificationsEnabledProvider(),
|
systemNotificationsEnabledProvider = FakeSystemNotificationsEnabledProvider(),
|
||||||
fullScreenIntentPermissionsPresenter = { fullScreenIntentPermissionsStateLambda() },
|
fullScreenIntentPermissionsPresenter = { fullScreenIntentPermissionsStateLambda() },
|
||||||
|
sessionCoroutineScope = backgroundScope,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,15 @@ interface PushService {
|
|||||||
distributor: Distributor,
|
distributor: Distributor,
|
||||||
): Result<Unit>
|
): Result<Unit>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure that the pusher with the current push provider and distributor is registered.
|
||||||
|
* If there is no current config, the default push provider with the default distributor will be used.
|
||||||
|
* Error can be [PusherRegistrationFailure].
|
||||||
|
*/
|
||||||
|
suspend fun ensurePusherIsRegistered(
|
||||||
|
matrixClient: MatrixClient,
|
||||||
|
): Result<Unit>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store the given push provider as the current one, but do not register.
|
* Store the given push provider as the current one, but do not register.
|
||||||
* To be used when there is no distributor available.
|
* To be used when there is no distributor available.
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.appnav.loggedin
|
package io.element.android.libraries.push.api
|
||||||
|
|
||||||
import io.element.android.libraries.matrix.api.exception.ClientException
|
import io.element.android.libraries.matrix.api.exception.ClientException
|
||||||
|
|
||||||
@@ -15,8 +15,10 @@ import dev.zacsweers.metro.binding
|
|||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
import io.element.android.libraries.matrix.api.core.SessionId
|
import io.element.android.libraries.matrix.api.core.SessionId
|
||||||
import io.element.android.libraries.matrix.api.core.UserId
|
import io.element.android.libraries.matrix.api.core.UserId
|
||||||
|
import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
|
||||||
import io.element.android.libraries.push.api.GetCurrentPushProvider
|
import io.element.android.libraries.push.api.GetCurrentPushProvider
|
||||||
import io.element.android.libraries.push.api.PushService
|
import io.element.android.libraries.push.api.PushService
|
||||||
|
import io.element.android.libraries.push.api.PusherRegistrationFailure
|
||||||
import io.element.android.libraries.push.api.history.PushHistoryItem
|
import io.element.android.libraries.push.api.history.PushHistoryItem
|
||||||
import io.element.android.libraries.push.impl.push.MutableBatteryOptimizationStore
|
import io.element.android.libraries.push.impl.push.MutableBatteryOptimizationStore
|
||||||
import io.element.android.libraries.push.impl.store.PushDataStore
|
import io.element.android.libraries.push.impl.store.PushDataStore
|
||||||
@@ -24,11 +26,13 @@ import io.element.android.libraries.push.impl.test.TestPush
|
|||||||
import io.element.android.libraries.push.impl.unregistration.ServiceUnregisteredHandler
|
import io.element.android.libraries.push.impl.unregistration.ServiceUnregisteredHandler
|
||||||
import io.element.android.libraries.pushproviders.api.Distributor
|
import io.element.android.libraries.pushproviders.api.Distributor
|
||||||
import io.element.android.libraries.pushproviders.api.PushProvider
|
import io.element.android.libraries.pushproviders.api.PushProvider
|
||||||
|
import io.element.android.libraries.pushproviders.api.RegistrationFailure
|
||||||
import io.element.android.libraries.pushstore.api.UserPushStoreFactory
|
import io.element.android.libraries.pushstore.api.UserPushStoreFactory
|
||||||
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecretStore
|
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecretStore
|
||||||
import io.element.android.libraries.sessionstorage.api.observer.SessionListener
|
import io.element.android.libraries.sessionstorage.api.observer.SessionListener
|
||||||
import io.element.android.libraries.sessionstorage.api.observer.SessionObserver
|
import io.element.android.libraries.sessionstorage.api.observer.SessionObserver
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
@ContributesBinding(AppScope::class, binding = binding<PushService>())
|
@ContributesBinding(AppScope::class, binding = binding<PushService>())
|
||||||
@@ -84,6 +88,59 @@ class DefaultPushService(
|
|||||||
return pushProvider.registerWith(matrixClient, distributor)
|
return pushProvider.registerWith(matrixClient, distributor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun ensurePusherIsRegistered(matrixClient: MatrixClient): Result<Unit> {
|
||||||
|
val verificationStatus = matrixClient.sessionVerificationService.sessionVerifiedStatus.first()
|
||||||
|
if (verificationStatus != SessionVerifiedStatus.Verified) {
|
||||||
|
return Result.failure<Unit>(PusherRegistrationFailure.AccountNotVerified())
|
||||||
|
.also { Timber.w("Account is not verified") }
|
||||||
|
}
|
||||||
|
Timber.d("Ensure pusher is registered")
|
||||||
|
val currentPushProvider = getCurrentPushProvider(matrixClient.sessionId)
|
||||||
|
val result = if (currentPushProvider == null) {
|
||||||
|
Timber.d("Register with the first available push provider with at least one distributor")
|
||||||
|
val pushProvider = getAvailablePushProviders()
|
||||||
|
.firstOrNull { it.getDistributors().isNotEmpty() }
|
||||||
|
// Else fallback to the first available push provider (the list should never be empty)
|
||||||
|
?: getAvailablePushProviders().firstOrNull()
|
||||||
|
?: return Result.failure<Unit>(PusherRegistrationFailure.NoProvidersAvailable())
|
||||||
|
.also { Timber.w("No push providers available") }
|
||||||
|
val distributor = pushProvider.getDistributors().firstOrNull()
|
||||||
|
?: return Result.failure<Unit>(PusherRegistrationFailure.NoDistributorsAvailable())
|
||||||
|
.also { Timber.w("No distributors available") }
|
||||||
|
.also {
|
||||||
|
// In this case, consider the push provider is chosen.
|
||||||
|
selectPushProvider(matrixClient.sessionId, pushProvider)
|
||||||
|
}
|
||||||
|
registerWith(matrixClient, pushProvider, distributor)
|
||||||
|
} else {
|
||||||
|
val currentPushDistributor = currentPushProvider.getCurrentDistributor(matrixClient.sessionId)
|
||||||
|
if (currentPushDistributor == null) {
|
||||||
|
Timber.d("Register with the first available distributor")
|
||||||
|
val distributor = currentPushProvider.getDistributors().firstOrNull()
|
||||||
|
?: return Result.failure<Unit>(PusherRegistrationFailure.NoDistributorsAvailable())
|
||||||
|
.also { Timber.w("No distributors available") }
|
||||||
|
registerWith(matrixClient, currentPushProvider, distributor)
|
||||||
|
} else {
|
||||||
|
Timber.d("Re-register with the current distributor")
|
||||||
|
registerWith(matrixClient, currentPushProvider, currentPushDistributor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.fold(
|
||||||
|
onSuccess = {
|
||||||
|
Timber.d("Pusher registered")
|
||||||
|
Result.success(Unit)
|
||||||
|
},
|
||||||
|
onFailure = {
|
||||||
|
Timber.e(it, "Failed to register pusher")
|
||||||
|
if (it is RegistrationFailure) {
|
||||||
|
Result.failure(PusherRegistrationFailure.RegistrationFailure(it.clientException, it.isRegisteringAgain))
|
||||||
|
} else {
|
||||||
|
Result.failure(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun selectPushProvider(
|
override suspend fun selectPushProvider(
|
||||||
sessionId: SessionId,
|
sessionId: SessionId,
|
||||||
pushProvider: PushProvider,
|
pushProvider: PushProvider,
|
||||||
|
|||||||
@@ -12,12 +12,15 @@ import app.cash.turbine.test
|
|||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
import io.element.android.libraries.matrix.api.core.SessionId
|
import io.element.android.libraries.matrix.api.core.SessionId
|
||||||
|
import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
|
||||||
import io.element.android.libraries.matrix.test.AN_EVENT_ID
|
import io.element.android.libraries.matrix.test.AN_EVENT_ID
|
||||||
import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
||||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||||
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||||
|
import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService
|
||||||
import io.element.android.libraries.push.api.GetCurrentPushProvider
|
import io.element.android.libraries.push.api.GetCurrentPushProvider
|
||||||
|
import io.element.android.libraries.push.api.PusherRegistrationFailure
|
||||||
import io.element.android.libraries.push.api.history.PushHistoryItem
|
import io.element.android.libraries.push.api.history.PushHistoryItem
|
||||||
import io.element.android.libraries.push.impl.push.FakeMutableBatteryOptimizationStore
|
import io.element.android.libraries.push.impl.push.FakeMutableBatteryOptimizationStore
|
||||||
import io.element.android.libraries.push.impl.push.MutableBatteryOptimizationStore
|
import io.element.android.libraries.push.impl.push.MutableBatteryOptimizationStore
|
||||||
@@ -40,6 +43,7 @@ import io.element.android.libraries.pushstore.test.userpushstore.FakeUserPushSto
|
|||||||
import io.element.android.libraries.pushstore.test.userpushstore.clientsecret.InMemoryPushClientSecretStore
|
import io.element.android.libraries.pushstore.test.userpushstore.clientsecret.InMemoryPushClientSecretStore
|
||||||
import io.element.android.libraries.sessionstorage.api.observer.SessionObserver
|
import io.element.android.libraries.sessionstorage.api.observer.SessionObserver
|
||||||
import io.element.android.libraries.sessionstorage.test.observer.NoOpSessionObserver
|
import io.element.android.libraries.sessionstorage.test.observer.NoOpSessionObserver
|
||||||
|
import io.element.android.tests.testutils.lambda.any
|
||||||
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||||
import io.element.android.tests.testutils.lambda.value
|
import io.element.android.tests.testutils.lambda.value
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
@@ -339,6 +343,281 @@ class DefaultPushServiceTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `ensurePusher - error when account is not verified`() = runTest {
|
||||||
|
val sessionVerificationService = FakeSessionVerificationService(
|
||||||
|
initialSessionVerifiedStatus = SessionVerifiedStatus.NotVerified
|
||||||
|
)
|
||||||
|
val pushService = createDefaultPushService()
|
||||||
|
val result = pushService.ensurePusherIsRegistered(
|
||||||
|
FakeMatrixClient(
|
||||||
|
sessionVerificationService = sessionVerificationService,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assertThat(result.exceptionOrNull()!!).isInstanceOf(PusherRegistrationFailure.AccountNotVerified::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `ensurePusher - case two push providers but first one does not have distributor - second one will be used`() = runTest {
|
||||||
|
val lambda = lambdaRecorder<MatrixClient, Distributor, Result<Unit>> { _, _ ->
|
||||||
|
Result.success(Unit)
|
||||||
|
}
|
||||||
|
val sessionVerificationService = FakeSessionVerificationService(
|
||||||
|
initialSessionVerifiedStatus = SessionVerifiedStatus.Verified
|
||||||
|
)
|
||||||
|
val pushProvider0 = FakePushProvider(
|
||||||
|
index = 0,
|
||||||
|
name = "aFakePushProvider0",
|
||||||
|
distributors = emptyList(),
|
||||||
|
)
|
||||||
|
val distributor = Distributor("aDistributorValue1", "aDistributorName1")
|
||||||
|
val pushProvider1 = FakePushProvider(
|
||||||
|
index = 1,
|
||||||
|
name = "aFakePushProvider1",
|
||||||
|
distributors = listOf(distributor),
|
||||||
|
registerWithResult = lambda,
|
||||||
|
)
|
||||||
|
val pushService = createDefaultPushService(
|
||||||
|
pushProviders = setOf(
|
||||||
|
pushProvider0,
|
||||||
|
pushProvider1,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
val result = pushService.ensurePusherIsRegistered(
|
||||||
|
FakeMatrixClient(
|
||||||
|
sessionVerificationService = sessionVerificationService,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assertThat(result.isSuccess).isTrue()
|
||||||
|
lambda.assertions().isCalledOnce()
|
||||||
|
.with(
|
||||||
|
// MatrixClient
|
||||||
|
any(),
|
||||||
|
// First distributor of second push provider
|
||||||
|
value(distributor),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `ensurePusher - case one push provider but no distributor available`() = runTest {
|
||||||
|
val lambda = lambdaRecorder<MatrixClient, Distributor, Result<Unit>> { _, _ ->
|
||||||
|
Result.success(Unit)
|
||||||
|
}
|
||||||
|
val sessionVerificationService = FakeSessionVerificationService(
|
||||||
|
initialSessionVerifiedStatus = SessionVerifiedStatus.Verified
|
||||||
|
)
|
||||||
|
val pushProvider = FakePushProvider(
|
||||||
|
index = 0,
|
||||||
|
name = "aFakePushProvider",
|
||||||
|
distributors = emptyList(),
|
||||||
|
registerWithResult = lambda,
|
||||||
|
)
|
||||||
|
val pushService = createDefaultPushService(
|
||||||
|
pushProviders = setOf(pushProvider),
|
||||||
|
)
|
||||||
|
val result = pushService.ensurePusherIsRegistered(
|
||||||
|
FakeMatrixClient(
|
||||||
|
sessionVerificationService = sessionVerificationService,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assertThat(result.exceptionOrNull()).isInstanceOf(PusherRegistrationFailure.NoDistributorsAvailable::class.java)
|
||||||
|
lambda.assertions().isNeverCalled()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `ensurePusher - ensure default pusher is registered with default provider`() = runTest {
|
||||||
|
val lambda = lambdaRecorder<MatrixClient, Distributor, Result<Unit>> { _, _ ->
|
||||||
|
Result.success(Unit)
|
||||||
|
}
|
||||||
|
val sessionVerificationService = FakeSessionVerificationService(
|
||||||
|
initialSessionVerifiedStatus = SessionVerifiedStatus.Verified
|
||||||
|
)
|
||||||
|
val pushService = createDefaultPushService(
|
||||||
|
pushProviders = setOf(
|
||||||
|
FakePushProvider(
|
||||||
|
index = 0,
|
||||||
|
name = "aFakePushProvider",
|
||||||
|
distributors = listOf(Distributor("aDistributorValue0", "aDistributorName0")),
|
||||||
|
registerWithResult = lambda,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
val result = pushService.ensurePusherIsRegistered(
|
||||||
|
FakeMatrixClient(
|
||||||
|
sessionVerificationService = sessionVerificationService,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assertThat(result.isSuccess).isTrue()
|
||||||
|
lambda.assertions()
|
||||||
|
.isCalledOnce()
|
||||||
|
.with(
|
||||||
|
// MatrixClient
|
||||||
|
any(),
|
||||||
|
// First distributor
|
||||||
|
value(pushService.getAvailablePushProviders()[0].getDistributors()[0]),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `ensurePusher - ensure default pusher is registered with default provider - fail to register`() = runTest {
|
||||||
|
val lambda = lambdaRecorder<MatrixClient, Distributor, Result<Unit>> { _, _ ->
|
||||||
|
Result.failure(AN_EXCEPTION)
|
||||||
|
}
|
||||||
|
val sessionVerificationService = FakeSessionVerificationService(
|
||||||
|
initialSessionVerifiedStatus = SessionVerifiedStatus.Verified
|
||||||
|
)
|
||||||
|
val pushService = createDefaultPushService(
|
||||||
|
pushProviders = setOf(
|
||||||
|
FakePushProvider(
|
||||||
|
index = 0,
|
||||||
|
name = "aFakePushProvider",
|
||||||
|
distributors = listOf(Distributor("aDistributorValue0", "aDistributorName0")),
|
||||||
|
registerWithResult = lambda,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
val result = pushService.ensurePusherIsRegistered(
|
||||||
|
FakeMatrixClient(
|
||||||
|
sessionVerificationService = sessionVerificationService,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assertThat(result.isFailure).isTrue()
|
||||||
|
lambda.assertions()
|
||||||
|
.isCalledOnce()
|
||||||
|
.with(
|
||||||
|
// MatrixClient
|
||||||
|
any(),
|
||||||
|
// First distributor
|
||||||
|
value(pushService.getAvailablePushProviders()[0].getDistributors()[0]),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `ensurePusher - if current push provider does not have distributors, nothing happen`() = runTest {
|
||||||
|
val lambda = lambdaRecorder<MatrixClient, Distributor, Result<Unit>> { _, _ ->
|
||||||
|
Result.success(Unit)
|
||||||
|
}
|
||||||
|
val sessionVerificationService = FakeSessionVerificationService(
|
||||||
|
initialSessionVerifiedStatus = SessionVerifiedStatus.Verified
|
||||||
|
)
|
||||||
|
val pushProvider = FakePushProvider(
|
||||||
|
index = 0,
|
||||||
|
name = "aFakePushProvider0",
|
||||||
|
distributors = emptyList(),
|
||||||
|
registerWithResult = lambda,
|
||||||
|
)
|
||||||
|
val pushService = createDefaultPushService(
|
||||||
|
pushProviders = setOf(pushProvider),
|
||||||
|
getCurrentPushProvider = FakeGetCurrentPushProvider(currentPushProvider = pushProvider.name),
|
||||||
|
)
|
||||||
|
val result = pushService.ensurePusherIsRegistered(
|
||||||
|
FakeMatrixClient(
|
||||||
|
sessionVerificationService = sessionVerificationService,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assertThat(result.exceptionOrNull())
|
||||||
|
.isInstanceOf(PusherRegistrationFailure.NoDistributorsAvailable::class.java)
|
||||||
|
lambda.assertions()
|
||||||
|
.isNeverCalled()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `ensurePusher - ensure current provider is registered with current distributor`() = runTest {
|
||||||
|
val lambda = lambdaRecorder<MatrixClient, Distributor, Result<Unit>> { _, _ ->
|
||||||
|
Result.success(Unit)
|
||||||
|
}
|
||||||
|
val sessionVerificationService = FakeSessionVerificationService(
|
||||||
|
initialSessionVerifiedStatus = SessionVerifiedStatus.Verified
|
||||||
|
)
|
||||||
|
val distributor = Distributor("aDistributorValue1", "aDistributorName1")
|
||||||
|
val pushProvider = FakePushProvider(
|
||||||
|
index = 0,
|
||||||
|
name = "aFakePushProvider0",
|
||||||
|
distributors = listOf(
|
||||||
|
Distributor("aDistributorValue0", "aDistributorName0"),
|
||||||
|
distributor,
|
||||||
|
),
|
||||||
|
currentDistributor = { distributor },
|
||||||
|
registerWithResult = lambda,
|
||||||
|
)
|
||||||
|
val pushService = createDefaultPushService(
|
||||||
|
pushProviders = setOf(pushProvider),
|
||||||
|
getCurrentPushProvider = FakeGetCurrentPushProvider(currentPushProvider = pushProvider.name),
|
||||||
|
)
|
||||||
|
val result = pushService.ensurePusherIsRegistered(
|
||||||
|
FakeMatrixClient(
|
||||||
|
sessionVerificationService = sessionVerificationService,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assertThat(result.isSuccess).isTrue()
|
||||||
|
lambda.assertions()
|
||||||
|
.isCalledOnce()
|
||||||
|
.with(
|
||||||
|
// MatrixClient
|
||||||
|
any(),
|
||||||
|
// Current distributor
|
||||||
|
value(distributor),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `ensurePusher - case no push provider available provider`() = runTest {
|
||||||
|
val lambda = lambdaRecorder<MatrixClient, Distributor, Result<Unit>> { _, _ ->
|
||||||
|
Result.success(Unit)
|
||||||
|
}
|
||||||
|
val sessionVerificationService = FakeSessionVerificationService(SessionVerifiedStatus.Verified)
|
||||||
|
val pushService = createDefaultPushService(
|
||||||
|
pushProviders = emptySet(),
|
||||||
|
)
|
||||||
|
val result = pushService.ensurePusherIsRegistered(
|
||||||
|
FakeMatrixClient(
|
||||||
|
sessionVerificationService = sessionVerificationService,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assertThat(result.exceptionOrNull())
|
||||||
|
.isInstanceOf(PusherRegistrationFailure.NoProvidersAvailable::class.java)
|
||||||
|
lambda.assertions()
|
||||||
|
.isNeverCalled()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `ensurePusher - if current push provider does not have current distributor, the first one is used`() = runTest {
|
||||||
|
val lambda = lambdaRecorder<MatrixClient, Distributor, Result<Unit>> { _, _ ->
|
||||||
|
Result.success(Unit)
|
||||||
|
}
|
||||||
|
val sessionVerificationService = FakeSessionVerificationService(
|
||||||
|
initialSessionVerifiedStatus = SessionVerifiedStatus.Verified
|
||||||
|
)
|
||||||
|
val pushProvider = FakePushProvider(
|
||||||
|
index = 0,
|
||||||
|
name = "aFakePushProvider0",
|
||||||
|
distributors = listOf(
|
||||||
|
Distributor("aDistributorValue0", "aDistributorName0"),
|
||||||
|
Distributor("aDistributorValue1", "aDistributorName1"),
|
||||||
|
),
|
||||||
|
currentDistributor = { null },
|
||||||
|
registerWithResult = lambda,
|
||||||
|
)
|
||||||
|
val pushService = createDefaultPushService(
|
||||||
|
pushProviders = setOf(pushProvider),
|
||||||
|
getCurrentPushProvider = FakeGetCurrentPushProvider(currentPushProvider = pushProvider.name),
|
||||||
|
)
|
||||||
|
val result = pushService.ensurePusherIsRegistered(
|
||||||
|
FakeMatrixClient(
|
||||||
|
sessionVerificationService = sessionVerificationService,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assertThat(result.isSuccess).isTrue()
|
||||||
|
lambda.assertions()
|
||||||
|
.isCalledOnce()
|
||||||
|
.with(
|
||||||
|
// MatrixClient
|
||||||
|
any(),
|
||||||
|
// First distributor
|
||||||
|
value(pushService.getAvailablePushProviders()[0].getDistributors()[0]),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun createDefaultPushService(
|
private fun createDefaultPushService(
|
||||||
testPush: TestPush = FakeTestPush(),
|
testPush: TestPush = FakeTestPush(),
|
||||||
userPushStoreFactory: UserPushStoreFactory = FakeUserPushStoreFactory(),
|
userPushStoreFactory: UserPushStoreFactory = FakeUserPushStoreFactory(),
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ class FakePushService(
|
|||||||
private val resetPushHistoryResult: () -> Unit = { lambdaError() },
|
private val resetPushHistoryResult: () -> Unit = { lambdaError() },
|
||||||
private val resetBatteryOptimizationStateResult: () -> Unit = { lambdaError() },
|
private val resetBatteryOptimizationStateResult: () -> Unit = { lambdaError() },
|
||||||
private val onServiceUnregisteredResult: (UserId) -> Unit = { lambdaError() },
|
private val onServiceUnregisteredResult: (UserId) -> Unit = { lambdaError() },
|
||||||
|
private val ensurePusherIsRegisteredResult: () -> Result<Unit> = { lambdaError() },
|
||||||
) : PushService {
|
) : PushService {
|
||||||
override suspend fun getCurrentPushProvider(sessionId: SessionId): PushProvider? {
|
override suspend fun getCurrentPushProvider(sessionId: SessionId): PushProvider? {
|
||||||
return registeredPushProvider ?: currentPushProvider(sessionId)
|
return registeredPushProvider ?: currentPushProvider(sessionId)
|
||||||
@@ -56,6 +57,10 @@ class FakePushService(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun ensurePusherIsRegistered(matrixClient: MatrixClient): Result<Unit> {
|
||||||
|
return ensurePusherIsRegisteredResult()
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun selectPushProvider(sessionId: SessionId, pushProvider: PushProvider) {
|
override suspend fun selectPushProvider(sessionId: SessionId, pushProvider: PushProvider) {
|
||||||
selectPushProviderLambda(sessionId, pushProvider)
|
selectPushProviderLambda(sessionId, pushProvider)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user