Updated on 2026-08-14

This commit is contained in:
Tangem 2025-04-25 14:01:08 +05:00
parent 0f9ba0ce7e
commit ba9113019a
8 changed files with 148 additions and 1 deletions

View file

@ -0,0 +1,11 @@
package com.tangem.tap.data
import com.google.firebase.messaging.FirebaseMessaging
import com.tangem.utils.notifications.PushNotificationsTokenProvider
import kotlinx.coroutines.tasks.await
class FirebasePushNotificationsTokenProvider : PushNotificationsTokenProvider {
override suspend fun getToken(): String {
return FirebaseMessaging.getInstance().token.await()
}
}

View file

@ -0,0 +1,18 @@
package com.tangem.tap.di.data
import com.tangem.tap.data.FirebasePushNotificationsTokenProvider
import com.tangem.utils.notifications.PushNotificationsTokenProvider
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
internal interface PushNotificationsModule {
@Binds
@Singleton
fun bindPushNotificationsTokenProvider(impl: FirebasePushNotificationsTokenProvider): PushNotificationsTokenProvider
}

View file

@ -1,7 +1,9 @@
package com.tangem.tap.di.domain
import com.tangem.domain.notifications.GetApplicationIdUseCase
import com.tangem.domain.notifications.SendPushTokenUseCase
import com.tangem.domain.notifications.repository.NotificationsRepository
import com.tangem.utils.notifications.PushNotificationsTokenProvider
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
@ -18,4 +20,16 @@ internal object NotificationsDomainModule {
GetApplicationIdUseCase(
notificationsRepository = notificationsRepository,
)
@Provides
@Singleton
fun providesSendPushTokenUseCase(
notificationsRepository: NotificationsRepository,
getApplicationIdUseCase: GetApplicationIdUseCase,
pushNotificationsTokenProvider: PushNotificationsTokenProvider,
): SendPushTokenUseCase = SendPushTokenUseCase(
notificationsRepository = notificationsRepository,
getApplicationIdUseCase = getApplicationIdUseCase,
pushNotificationsTokenProvider = pushNotificationsTokenProvider,
)
}

View file

@ -0,0 +1,6 @@
package com.tangem.utils.notifications
interface PushNotificationsTokenProvider {
suspend fun getToken(): String
}

View file

@ -5,6 +5,7 @@ plugins {
}
dependencies {
implementation(projects.core.utils)
implementation(projects.domain.core)
implementation(projects.domain.notifications.models)

View file

@ -0,0 +1,19 @@
package com.tangem.domain.notifications
import arrow.core.Either
import com.tangem.domain.notifications.repository.NotificationsRepository
import com.tangem.utils.notifications.PushNotificationsTokenProvider
class SendPushTokenUseCase(
private val notificationsRepository: NotificationsRepository,
private val getApplicationIdUseCase: GetApplicationIdUseCase,
private val pushNotificationsTokenProvider: PushNotificationsTokenProvider,
) {
suspend operator fun invoke(): Either<Throwable, Unit> = Either.catch {
val applicationId = getApplicationIdUseCase().getOrNull()
?: error("Application ID not found")
val token = pushNotificationsTokenProvider.getToken()
notificationsRepository.sendPushToken(applicationId, token)
}
}

View file

@ -97,7 +97,6 @@ class GetApplicationIdUseCaseTest {
val results = coroutineScope {
List(PARALLEL_COUNT) {
async {
delay(100)
useCase()
}
}.awaitAll()

View file

@ -0,0 +1,79 @@
package com.tangem.domain.notifications
import arrow.core.Either
import com.google.common.truth.Truth.assertThat
import com.tangem.domain.notifications.repository.NotificationsRepository
import com.tangem.utils.notifications.PushNotificationsTokenProvider
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.mockk
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
class SendPushTokenUseCaseTest {
private lateinit var notificationsRepository: NotificationsRepository
private lateinit var getApplicationIdUseCase: GetApplicationIdUseCase
private lateinit var pushNotificationsTokenProvider: PushNotificationsTokenProvider
private lateinit var sendPushTokenUseCase: SendPushTokenUseCase
@Before
fun setup() {
notificationsRepository = mockk()
getApplicationIdUseCase = mockk()
pushNotificationsTokenProvider = mockk()
sendPushTokenUseCase = SendPushTokenUseCase(
notificationsRepository = notificationsRepository,
getApplicationIdUseCase = getApplicationIdUseCase,
pushNotificationsTokenProvider = pushNotificationsTokenProvider,
)
}
@Test
fun `GIVEN valid application ID and token WHEN invoke THEN token is sent successfully`() = runTest {
// GIVEN
val applicationId = "test-app-id"
val token = "test-token"
coEvery { getApplicationIdUseCase() } returns Either.Right(applicationId)
coEvery { pushNotificationsTokenProvider.getToken() } returns token
coEvery { notificationsRepository.sendPushToken(applicationId, token) } returns Unit
// WHEN
val result = sendPushTokenUseCase()
// THEN
assertThat(result).isEqualTo(Either.Right(Unit))
coVerify(exactly = 1) { notificationsRepository.sendPushToken(applicationId, token) }
}
@Test
fun `GIVEN application ID is not found WHEN invoke THEN throws error`() = runTest {
// GIVEN
coEvery { getApplicationIdUseCase() } returns Either.Left(Throwable("Application ID not found"))
// WHEN & THEN
val result = sendPushTokenUseCase()
assertThat(result.isLeft()).isTrue()
assertThat(result.fold({ it.message }, { null })).isEqualTo("Application ID not found")
coVerify(exactly = 0) { notificationsRepository.sendPushToken(any(), any()) }
}
@Test
fun `GIVEN repository throws error WHEN invoke THEN returns error`() = runTest {
// GIVEN
val applicationId = "test-app-id"
val token = "test-token"
val expectedError = RuntimeException("Network error")
coEvery { getApplicationIdUseCase() } returns Either.Right(applicationId)
coEvery { pushNotificationsTokenProvider.getToken() } returns token
coEvery { notificationsRepository.sendPushToken(applicationId, token) } throws expectedError
// WHEN
val result = sendPushTokenUseCase()
// THEN
assertThat(result).isEqualTo(Either.Left(expectedError))
coVerify(exactly = 1) { notificationsRepository.sendPushToken(applicationId, token) }
}
}