package com.tt.honeyDue.notifications import android.app.NotificationManager import android.content.Context import android.os.Build import androidx.test.core.app.ApplicationProvider import com.google.firebase.messaging.RemoteMessage import org.junit.Assert.assertEquals import org.junit.Assert.assertNotNull import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.robolectric.Robolectric import org.robolectric.RobolectricTestRunner import org.robolectric.annotation.Config /** * Tests for [FcmService] — verify channel routing and deep-link handling * when data messages arrive. */ @RunWith(RobolectricTestRunner::class) @Config(sdk = [Build.VERSION_CODES.TIRAMISU]) class FcmServiceTest { private lateinit var context: Context private lateinit var manager: NotificationManager private lateinit var service: FcmService @Before fun setUp() { context = ApplicationProvider.getApplicationContext() manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager manager.notificationChannels.forEach { manager.deleteNotificationChannel(it.id) } manager.cancelAll() service = Robolectric.setupService(FcmService::class.java) } private fun remoteMessage(id: String, data: Map): RemoteMessage { val b = RemoteMessage.Builder("test@fcm") b.setMessageId(id) data.forEach { (k, v) -> b.addData(k, v) } return b.build() } @Test fun onMessageReceived_routesTaskReminder_toCorrectChannel() { val msg = remoteMessage( id = "m-1", data = mapOf( "type" to "task_reminder", "task_id" to "7", "title" to "Reminder", "body" to "Do it" ) ) service.onMessageReceived(msg) // Channel must have been created and a notification posted on it. val channel = manager.getNotificationChannel(NotificationChannels.TASK_REMINDER) assertNotNull("task_reminder channel should be created", channel) val posted = manager.activeNotifications assertTrue("one notification should be posted", posted.isNotEmpty()) val n = posted.first() assertEquals(NotificationChannels.TASK_REMINDER, n.notification.channelId) } @Test fun onMessageReceived_routesTaskOverdue_toHighChannel() { val msg = remoteMessage( id = "m-2", data = mapOf( "type" to "task_overdue", "task_id" to "8", "title" to "Overdue", "body" to "Late" ) ) service.onMessageReceived(msg) val posted = manager.activeNotifications assertTrue(posted.isNotEmpty()) assertEquals(NotificationChannels.TASK_OVERDUE, posted.first().notification.channelId) } @Test fun onMessageReceived_routesResidenceInvite() { val msg = remoteMessage( id = "m-3", data = mapOf( "type" to "residence_invite", "residence_id" to "42", "title" to "Invite", "body" to "Join us" ) ) service.onMessageReceived(msg) val posted = manager.activeNotifications assertTrue(posted.isNotEmpty()) assertEquals(NotificationChannels.RESIDENCE_INVITE, posted.first().notification.channelId) } @Test fun onMessageReceived_routesSubscription_toLowChannel() { val msg = remoteMessage( id = "m-4", data = mapOf( "type" to "subscription", "title" to "Sub", "body" to "Changed" ) ) service.onMessageReceived(msg) val posted = manager.activeNotifications assertTrue(posted.isNotEmpty()) assertEquals(NotificationChannels.SUBSCRIPTION, posted.first().notification.channelId) } @Test fun onMessageReceived_withTaskId_sets_deep_link() { val msg = remoteMessage( id = "m-5", data = mapOf( "type" to "task_reminder", "task_id" to "123", "title" to "T", "body" to "B", "deep_link" to "honeydue://task/123" ) ) service.onMessageReceived(msg) val posted = manager.activeNotifications assertTrue(posted.isNotEmpty()) val contentIntent = posted.first().notification.contentIntent assertNotNull("content intent should be attached for deep-link tap", contentIntent) } @Test fun onMessageReceived_malformedPayload_postsNothing() { // Missing type → payload parse returns null → nothing posted. val msg = remoteMessage( id = "m-6", data = mapOf( "title" to "x", "body" to "y" ) ) service.onMessageReceived(msg) assertTrue( "no notification should be posted for malformed payload", manager.activeNotifications.isEmpty() ) } @Test fun onMessageReceived_distinctMessageIds_produceDistinctNotifications() { service.onMessageReceived( remoteMessage( "id-A", mapOf("type" to "task_reminder", "task_id" to "1", "title" to "A", "body" to "a") ) ) service.onMessageReceived( remoteMessage( "id-B", mapOf("type" to "task_reminder", "task_id" to "2", "title" to "B", "body" to "b") ) ) assertEquals(2, manager.activeNotifications.size) } }