NTP-47165 | Update code in FCM topic use case (#15438)
This commit is contained in:
@@ -9,6 +9,7 @@ package com.naviapp.common.di
|
||||
|
||||
import com.google.firebase.messaging.FirebaseMessaging
|
||||
import com.navi.base.BuildConfig
|
||||
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper
|
||||
import com.navi.common.network.BaseUrls
|
||||
import com.naviapp.app.NaviApplication
|
||||
import com.naviapp.app.initializers.AnrErrorHandlerInitializer
|
||||
@@ -46,6 +47,9 @@ object AppModule {
|
||||
@Singleton
|
||||
fun provideCoroutineScopeIO(): CoroutineScope = CoroutineScope(Dispatchers.IO)
|
||||
|
||||
@Provides
|
||||
fun provideFirebaseRemoteConfigHelper(): FirebaseRemoteConfigHelper = FirebaseRemoteConfigHelper
|
||||
|
||||
@Provides fun provideFirebaseMessaging(): FirebaseMessaging = FirebaseMessaging.getInstance()
|
||||
|
||||
@Provides
|
||||
|
||||
@@ -10,6 +10,7 @@ package com.naviapp.registration.usecase
|
||||
import com.google.firebase.messaging.FirebaseMessaging
|
||||
import com.google.gson.Gson
|
||||
import com.navi.analytics.utils.NaviTrackEvent
|
||||
import com.navi.base.cache.di.NaviCommonGson
|
||||
import com.navi.base.utils.isNotNullAndNotEmpty
|
||||
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper
|
||||
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper.FCM_TOPIC_LIST
|
||||
@@ -28,12 +29,17 @@ import javax.inject.Inject
|
||||
*
|
||||
* @property firebaseMessaging The FirebaseMessaging instance used for topic subscription.
|
||||
*/
|
||||
class FcmTopicUseCase @Inject constructor(private val firebaseMessaging: FirebaseMessaging) {
|
||||
class FcmTopicUseCase
|
||||
@Inject
|
||||
constructor(
|
||||
private val firebaseRemoteConfigHelper: FirebaseRemoteConfigHelper,
|
||||
private val firebaseMessaging: FirebaseMessaging,
|
||||
@NaviCommonGson private val gson: Gson,
|
||||
) {
|
||||
|
||||
/** Attaches FCM topics by fetching the topic list and subscribing to the enabled topics. */
|
||||
fun attachFcmTopics() {
|
||||
val topicList = fetchFcmTopicList() ?: return
|
||||
|
||||
topicList.list
|
||||
?.filter { it.topicName.isNotNullAndNotEmpty() }
|
||||
?.partition { it.enable }
|
||||
@@ -50,11 +56,10 @@ class FcmTopicUseCase @Inject constructor(private val firebaseMessaging: Firebas
|
||||
*/
|
||||
private fun fetchFcmTopicList(): FcmTopicList? {
|
||||
return try {
|
||||
Gson()
|
||||
.fromJson(
|
||||
FirebaseRemoteConfigHelper.getString(FCM_TOPIC_LIST),
|
||||
FcmTopicList::class.java,
|
||||
)
|
||||
gson.fromJson(
|
||||
firebaseRemoteConfigHelper.getString(FCM_TOPIC_LIST),
|
||||
FcmTopicList::class.java,
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
e.log()
|
||||
null
|
||||
@@ -69,29 +74,20 @@ class FcmTopicUseCase @Inject constructor(private val firebaseMessaging: Firebas
|
||||
private fun subscribeToTopic(topicName: String) {
|
||||
firebaseMessaging
|
||||
.subscribeToTopic(topicName)
|
||||
.addOnSuccessListener {
|
||||
NaviTrackEvent.trackEvent(FCM_SUBSCRIPTION_SUCCESS, mapOf(TOPIC to topicName))
|
||||
}
|
||||
.addOnSuccessListener { trackFcmEvent(FCM_SUBSCRIPTION_SUCCESS, topicName) }
|
||||
.addOnCompleteListener { task ->
|
||||
if (!task.isSuccessful) {
|
||||
NaviTrackEvent.trackEvent(
|
||||
trackFcmEvent(
|
||||
FCM_SUBSCRIPTION_FAILED,
|
||||
mapOf(
|
||||
TOPIC to topicName,
|
||||
ERROR to (task.exception?.message ?: UNKNOWN_ERROR),
|
||||
),
|
||||
topicName,
|
||||
task.exception?.message ?: UNKNOWN_ERROR,
|
||||
)
|
||||
}
|
||||
}
|
||||
.addOnFailureListener { exception ->
|
||||
NaviTrackEvent.trackEvent(
|
||||
FCM_SUBSCRIPTION_FAILED,
|
||||
mapOf(TOPIC to topicName, ERROR to exception.toString()),
|
||||
)
|
||||
}
|
||||
.addOnCanceledListener {
|
||||
NaviTrackEvent.trackEvent(FCM_SUBSCRIPTION_CANCELED, mapOf(TOPIC to topicName))
|
||||
trackFcmEvent(FCM_SUBSCRIPTION_FAILED, topicName, exception.toString())
|
||||
}
|
||||
.addOnCanceledListener { trackFcmEvent(FCM_SUBSCRIPTION_CANCELED, topicName) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,19 +98,24 @@ class FcmTopicUseCase @Inject constructor(private val firebaseMessaging: Firebas
|
||||
private fun unsubscribeToTopic(topicName: String) {
|
||||
firebaseMessaging
|
||||
.unsubscribeFromTopic(topicName)
|
||||
.addOnSuccessListener {
|
||||
NaviTrackEvent.trackEvent(FCM_UNSUBSCRIBE_SUCCESS, mapOf(TOPIC to topicName))
|
||||
}
|
||||
.addOnSuccessListener { trackFcmEvent(FCM_UNSUBSCRIBE_SUCCESS, topicName) }
|
||||
.addOnCompleteListener {
|
||||
if (!it.isSuccessful) {
|
||||
NaviTrackEvent.trackEvent(
|
||||
trackFcmEvent(
|
||||
FCM_UNSUBSCRIBE_FAILED,
|
||||
mapOf(TOPIC to topicName, ERROR to (it.exception?.message ?: UNKNOWN_ERROR)),
|
||||
topicName,
|
||||
it.exception?.message ?: UNKNOWN_ERROR,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun trackFcmEvent(eventName: String, topicName: String, errorMessage: String? = null) {
|
||||
val eventData = mutableMapOf(TOPIC to topicName)
|
||||
errorMessage?.let { eventData[ERROR] = it }
|
||||
NaviTrackEvent.trackEvent(eventName, eventData)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val FCM_SUBSCRIPTION_SUCCESS = "dev_fcm_subscription_success"
|
||||
private const val FCM_UNSUBSCRIBE_SUCCESS = "dev_fcm_unsubscribe_success"
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2025 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
import com.google.firebase.messaging.FirebaseMessaging
|
||||
import com.google.gson.Gson
|
||||
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper
|
||||
import com.navi.common.utils.log
|
||||
import com.naviapp.models.FcmTopicData
|
||||
import com.naviapp.models.FcmTopicList
|
||||
import com.naviapp.registration.usecase.FcmTopicUseCase
|
||||
import io.mockk.Runs
|
||||
import io.mockk.every
|
||||
import io.mockk.just
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkStatic
|
||||
import io.mockk.spyk
|
||||
import io.mockk.verify
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.junit.MockitoJUnitRunner
|
||||
|
||||
@RunWith(MockitoJUnitRunner::class)
|
||||
class FcmTopicUseCaseTest {
|
||||
|
||||
private lateinit var fcmTopicUseCase: FcmTopicUseCase
|
||||
private val firebaseRemoteConfigHelper: FirebaseRemoteConfigHelper = mockk()
|
||||
private val gson: Gson = mockk()
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
val mockFirebaseMessaging: FirebaseMessaging = mockk(relaxed = true)
|
||||
fcmTopicUseCase = FcmTopicUseCase(firebaseRemoteConfigHelper, mockFirebaseMessaging, gson)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `attachFcmTopics calls subscribeToTopic when enabled list is not empty`() {
|
||||
val topicName = "test_topic"
|
||||
val fcmTopicList = FcmTopicList(listOf(FcmTopicData(topicName, enable = true)))
|
||||
|
||||
every { firebaseRemoteConfigHelper.getString(any()) } returns "{}"
|
||||
every { gson.fromJson("{}", FcmTopicList::class.java) } returns fcmTopicList
|
||||
|
||||
val subscribeSpy = spyk(fcmTopicUseCase, recordPrivateCalls = true)
|
||||
|
||||
subscribeSpy.attachFcmTopics()
|
||||
verify(exactly = 1) { subscribeSpy["subscribeToTopic"](topicName) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `fetchFcmTopicList returns null for invalid JSON`() {
|
||||
every { firebaseRemoteConfigHelper.getString(any()) } returns "{}}"
|
||||
mockkStatic("com.navi.common.utils.LogKt")
|
||||
every { any<Exception>().log() } just Runs
|
||||
val result =
|
||||
fcmTopicUseCase::class
|
||||
.java
|
||||
.getDeclaredMethod("fetchFcmTopicList")
|
||||
.apply { isAccessible = true }
|
||||
.invoke(fcmTopicUseCase) as FcmTopicList?
|
||||
|
||||
assert(result == null)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `fetchFcmTopicList returns null for empty string`() {
|
||||
every { firebaseRemoteConfigHelper.getString(any()) } returns ""
|
||||
mockkStatic("com.navi.common.utils.LogKt")
|
||||
every { any<Exception>().log() } just Runs
|
||||
|
||||
val result =
|
||||
fcmTopicUseCase::class
|
||||
.java
|
||||
.getDeclaredMethod("fetchFcmTopicList")
|
||||
.apply { isAccessible = true }
|
||||
.invoke(fcmTopicUseCase) as FcmTopicList?
|
||||
|
||||
assert(result == null)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user