Skip to content

Commit

Permalink
feat: Add debug button send FCM token #WPB-9476 (#3050)
Browse files Browse the repository at this point in the history
* feat: Add debug button send FCM token

* reduce returns

* fixed test

* fix datadog report

* after refactor fix

* fix test
  • Loading branch information
damian-kaczmarek authored Oct 8, 2024
1 parent 8e0f4a6 commit 75b92ab
Show file tree
Hide file tree
Showing 4 changed files with 273 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1805,6 +1805,7 @@ class UserSessionScope internal constructor(
staleEpochVerifier,
eventProcessor,
legalHoldHandler,
notificationTokenRepository,
this,
userScopedLogger,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package com.wire.kalium.logic.feature.debug

import com.wire.kalium.logger.KaliumLogger
import com.wire.kalium.logic.cache.SelfConversationIdProvider
import com.wire.kalium.logic.configuration.notification.NotificationTokenRepository
import com.wire.kalium.logic.data.asset.AssetRepository
import com.wire.kalium.logic.data.client.ClientRepository
import com.wire.kalium.logic.data.client.MLSClientProvider
Expand Down Expand Up @@ -54,6 +55,8 @@ import com.wire.kalium.logic.feature.message.StaleEpochVerifier
import com.wire.kalium.logic.feature.message.ephemeral.DeleteEphemeralMessageForSelfUserAsReceiverUseCaseImpl
import com.wire.kalium.logic.feature.message.ephemeral.DeleteEphemeralMessageForSelfUserAsSenderUseCaseImpl
import com.wire.kalium.logic.feature.message.ephemeral.EphemeralMessageDeletionHandlerImpl
import com.wire.kalium.logic.feature.notificationToken.SendFCMTokenUseCase
import com.wire.kalium.logic.feature.notificationToken.SendFCMTokenToAPIUseCaseImpl
import com.wire.kalium.logic.sync.SyncManager
import com.wire.kalium.logic.sync.incremental.EventProcessor
import com.wire.kalium.logic.sync.receiver.handler.legalhold.LegalHoldHandler
Expand Down Expand Up @@ -87,8 +90,9 @@ class DebugScope internal constructor(
private val staleEpochVerifier: StaleEpochVerifier,
private val eventProcessor: EventProcessor,
private val legalHoldHandler: LegalHoldHandler,
private val notificationTokenRepository: NotificationTokenRepository,
private val scope: CoroutineScope,
private val logger: KaliumLogger,
logger: KaliumLogger,
internal val dispatcher: KaliumDispatcher = KaliumDispatcherImpl,
) {

Expand Down Expand Up @@ -179,7 +183,12 @@ class DebugScope internal constructor(
messageSendingInterceptor,
userRepository,
staleEpochVerifier,
{ message, expirationData -> ephemeralMessageDeletionHandler.enqueueSelfDeletion(message, expirationData) },
{ message, expirationData ->
ephemeralMessageDeletionHandler.enqueueSelfDeletion(
message,
expirationData
)
},
scope
)

Expand Down Expand Up @@ -208,4 +217,11 @@ class DebugScope internal constructor(
selfUserId = userId,
kaliumLogger = logger
)

val sendFCMTokenToServer: SendFCMTokenUseCase
get() = SendFCMTokenToAPIUseCaseImpl(
currentClientIdProvider,
clientRepository,
notificationTokenRepository,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Wire
* Copyright (C) 2024 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.wire.kalium.logic.feature.notificationToken

import com.wire.kalium.logic.configuration.notification.NotificationTokenRepository
import com.wire.kalium.logic.data.client.ClientRepository
import com.wire.kalium.logic.data.id.CurrentClientIdProvider
import com.wire.kalium.logic.functional.Either
import com.wire.kalium.logic.functional.fold
import com.wire.kalium.logic.functional.getOrNull
import com.wire.kalium.logic.functional.nullableFold

/**
* Sends to the API locally stored FCM push token
*/
interface SendFCMTokenUseCase {
suspend operator fun invoke(): Either<SendFCMTokenError, Unit>
}

data class SendFCMTokenError(
val status: Reason,
val error: String? = null,
) {
enum class Reason {
CANT_GET_CLIENT_ID, CANT_GET_NOTIFICATION_TOKEN, CANT_REGISTER_TOKEN,
}
}

class SendFCMTokenToAPIUseCaseImpl internal constructor(
private val currentClientIdProvider: CurrentClientIdProvider,
private val clientRepository: ClientRepository,
private val notificationTokenRepository: NotificationTokenRepository,
) : SendFCMTokenUseCase {

override suspend fun invoke(): Either<SendFCMTokenError, Unit> {
val clientIdResult = currentClientIdProvider()
val notificationTokenResult = notificationTokenRepository.getNotificationToken()

val error: SendFCMTokenError? = clientIdResult.nullableFold(
{ SendFCMTokenError(SendFCMTokenError.Reason.CANT_GET_CLIENT_ID, it.toString()) },
{
notificationTokenResult.nullableFold(
{
SendFCMTokenError(
SendFCMTokenError.Reason.CANT_GET_NOTIFICATION_TOKEN,
it.toString()
)
},
{ null }
)
}
)

if (error != null) {
return Either.Left(error)
}

val clientId = clientIdResult.getOrNull()!!.value
val notificationToken = notificationTokenResult.getOrNull()!!

return clientRepository.registerToken(
senderId = notificationToken.applicationId,
client = clientId,
token = notificationToken.token,
transport = notificationToken.transport
).fold(
{
Either.Left(
SendFCMTokenError(
SendFCMTokenError.Reason.CANT_REGISTER_TOKEN,
it.toString()
)
)
},
{ Either.Right(Unit) }
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/*
* Wire
* Copyright (C) 2024 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.wire.kalium.logic.feature.notificationToken

import com.wire.kalium.logic.CoreFailure
import com.wire.kalium.logic.NetworkFailure
import com.wire.kalium.logic.StorageFailure
import com.wire.kalium.logic.configuration.notification.NotificationToken
import com.wire.kalium.logic.configuration.notification.NotificationTokenRepository
import com.wire.kalium.logic.data.client.ClientRepository
import com.wire.kalium.logic.data.conversation.ClientId
import com.wire.kalium.logic.data.id.CurrentClientIdProvider
import com.wire.kalium.logic.functional.Either
import com.wire.kalium.logic.functional.fold
import io.mockative.Mock
import io.mockative.any
import io.mockative.coEvery
import io.mockative.every
import io.mockative.mock
import kotlinx.coroutines.test.runTest
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.fail

class SendFCMTokenToAPIUseCaseTest {
@Test
fun whenInvokedAndSuccessfulResultInTokenRegistered() = runTest {

val useCase =
Arrangement()
.withClientId()
.withNotificationToken()
.withClientRepositoryRegisterToken()
.arrange()

val result = useCase.invoke()
assertEquals(Either.Right(Unit), result)
}

@Test
fun whenInvokedAndFailureOnClientId() = runTest {

val useCase = Arrangement()
.withClientIdFailure()
.withNotificationToken()
.arrange()

val failReason = useCase.invoke().fold(
{ it.status },
{ fail("Expected failure, but got success") }
)
assertEquals(SendFCMTokenError.Reason.CANT_GET_CLIENT_ID, failReason)

}

@Test
fun whenInvokedAndFailureOnNotificationToken() = runTest {

val useCase = Arrangement()
.withClientId()
.withNotificationTokenFailure()
.arrange()

val failReason = useCase.invoke().fold(
{ it.status },
{ fail("Expected failure, but got success") }
)
assertEquals(SendFCMTokenError.Reason.CANT_GET_NOTIFICATION_TOKEN, failReason)
}

@Test
fun whenInvokedAndFailureOnClientRepositoryRegisterToken() = runTest {

val useCase = Arrangement()
.withClientId()
.withNotificationToken()
.withClientRepositoryRegisterTokenFailure()
.arrange()

val failReason = useCase.invoke().fold(
{ it.status },
{ fail("Expected failure, but got success") }
)
assertEquals(SendFCMTokenError.Reason.CANT_REGISTER_TOKEN, failReason)
}


private class Arrangement {

@Mock
private val currentClientIdProvider: CurrentClientIdProvider =
mock(CurrentClientIdProvider::class)

@Mock
private val clientRepository: ClientRepository = mock(ClientRepository::class)

@Mock
private val notificationTokenRepository: NotificationTokenRepository =
mock(NotificationTokenRepository::class)


fun arrange(): SendFCMTokenToAPIUseCaseImpl {
return SendFCMTokenToAPIUseCaseImpl(
currentClientIdProvider, clientRepository, notificationTokenRepository
)
}

suspend fun withClientId() = apply {
coEvery {
currentClientIdProvider.invoke()
}.returns(Either.Right(ClientId("clientId")))
}

suspend fun withClientIdFailure() = apply {
coEvery {
currentClientIdProvider.invoke()
}.returns(Either.Left(CoreFailure.MissingClientRegistration))
}

fun withNotificationToken() = apply {
every {
notificationTokenRepository.getNotificationToken()
}.returns(Either.Right(NotificationToken("applicationId", "token", "transport")))
}

fun withNotificationTokenFailure() = apply {
every {
notificationTokenRepository.getNotificationToken()
}.returns(Either.Left(StorageFailure.DataNotFound))
}

suspend fun withClientRepositoryRegisterToken() = apply {
coEvery {
clientRepository.registerToken(any(), any(), any(), any())
}.returns(Either.Right(Unit))
}

suspend fun withClientRepositoryRegisterTokenFailure() = apply {
coEvery {
clientRepository.registerToken(any(), any(), any(), any())
}.returns(Either.Left(NetworkFailure.FeatureNotSupported))
}

}

}

0 comments on commit 75b92ab

Please sign in to comment.