package com.tt.honeyDue.notifications import android.app.AlarmManager import android.content.Context import android.os.Build import androidx.test.core.app.ApplicationProvider import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner import org.robolectric.Shadows.shadowOf import org.robolectric.annotation.Config /** * Tests for [SnoozeScheduler] — verifies the AlarmManager scheduling path * used by the P4 Stream O notification Snooze action. */ @RunWith(RobolectricTestRunner::class) @Config(sdk = [Build.VERSION_CODES.TIRAMISU]) class SnoozeSchedulerTest { private lateinit var context: Context private lateinit var am: AlarmManager @Before fun setUp() { context = ApplicationProvider.getApplicationContext() am = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager // Robolectric's ShadowAlarmManager doesn't have an explicit clear, but // scheduledAlarms is filtered by live pending intents so cancel() the // world before each test. shadowOf(am).scheduledAlarms.toList().forEach { alarm -> alarm.operation?.let { am.cancel(it) } } } // ---------- 7. schedule() sets alarm 30 minutes in future ---------- @Test fun schedule_setsAlarmThirtyMinutesInFuture() { val before = System.currentTimeMillis() SnoozeScheduler.schedule( context = context, taskId = 123L, title = "t", body = "b", type = NotificationChannels.TASK_REMINDER ) val scheduled = shadowOf(am).scheduledAlarms assertEquals(1, scheduled.size) val delta = scheduled.first().triggerAtTime - before val expected = NotificationActions.SNOOZE_DELAY_MS assertTrue( "expected ~30 min trigger, got delta=$delta", delta in (expected - 2_000)..(expected + 2_000) ) } // ---------- 8. cancel() removes the pending alarm ---------- @Test fun cancel_preventsLaterDelivery() { SnoozeScheduler.schedule(context, taskId = 456L) assertEquals( "precondition: alarm scheduled", 1, shadowOf(am).scheduledAlarms.size ) SnoozeScheduler.cancel(context, taskId = 456L) // After cancel(), the PendingIntent is consumed so scheduledAlarms // shrinks back to zero (Robolectric matches by PI equality). assertEquals( "alarm should be gone after cancel()", 0, shadowOf(am).scheduledAlarms.size ) } // Bonus coverage: different task ids get independent scheduling slots. @Test fun schedule_twoDifferentTasks_yieldsTwoAlarms() { SnoozeScheduler.schedule(context, taskId = 1L) SnoozeScheduler.schedule(context, taskId = 2L) assertEquals(2, shadowOf(am).scheduledAlarms.size) } }