diff --git a/app/src/test/java/com/d4rk/androidtutorials/java/notifications/managers/AppUsageNotificationsManagerTest.java b/app/src/test/java/com/d4rk/androidtutorials/java/notifications/managers/AppUsageNotificationsManagerTest.java new file mode 100644 index 00000000..f7dcfd4a --- /dev/null +++ b/app/src/test/java/com/d4rk/androidtutorials/java/notifications/managers/AppUsageNotificationsManagerTest.java @@ -0,0 +1,48 @@ +package com.d4rk.androidtutorials.java.notifications.managers; + +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.Context; + +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import java.util.concurrent.TimeUnit; + +/** + * Tests for {@link AppUsageNotificationsManager}. + */ +public class AppUsageNotificationsManagerTest { + + @Test + public void scheduleAppUsageCheck_setsRepeatingAlarmWithThreeDayInterval() { + AlarmManager alarmManager = mock(AlarmManager.class); + Context context = mock(Context.class); + when(context.getSystemService(Context.ALARM_SERVICE)).thenReturn(alarmManager); + when(context.getApplicationContext()).thenReturn(context); + + long now = System.currentTimeMillis(); + AppUsageNotificationsManager manager = new AppUsageNotificationsManager(context); + + manager.scheduleAppUsageCheck(); + + ArgumentCaptor triggerCaptor = ArgumentCaptor.forClass(Long.class); + verify(alarmManager).setRepeating( + eq(AlarmManager.RTC_WAKEUP), + triggerCaptor.capture(), + eq(TimeUnit.DAYS.toMillis(3)), + any(PendingIntent.class) + ); + + long expectedTrigger = now + TimeUnit.DAYS.toMillis(3); + assertTrue(Math.abs(triggerCaptor.getValue() - expectedTrigger) < 1000); + } +} + diff --git a/app/src/test/java/com/d4rk/androidtutorials/java/notifications/workers/AppUsageNotificationWorkerTest.java b/app/src/test/java/com/d4rk/androidtutorials/java/notifications/workers/AppUsageNotificationWorkerTest.java new file mode 100644 index 00000000..f59aff4a --- /dev/null +++ b/app/src/test/java/com/d4rk/androidtutorials/java/notifications/workers/AppUsageNotificationWorkerTest.java @@ -0,0 +1,102 @@ +package com.d4rk.androidtutorials.java.notifications.workers; + +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockConstruction; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.content.Context; +import android.content.SharedPreferences; + +import androidx.preference.PreferenceManager; +import androidx.work.WorkerParameters; + +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.MockedConstruction; +import org.mockito.MockedStatic; + +/** + * Tests for {@link AppUsageNotificationWorker}. + */ +public class AppUsageNotificationWorkerTest { + + @Test + public void doWork_lastUsedExceedsThreshold_showsNotificationAndUpdatesTimestamp() { + Context context = mock(Context.class); + when(context.getApplicationContext()).thenReturn(context); + when(context.getString(anyInt())).thenReturn(""); + NotificationManager notificationManager = mock(NotificationManager.class); + when(context.getSystemService(Context.NOTIFICATION_SERVICE)).thenReturn(notificationManager); + + SharedPreferences sharedPreferences = mock(SharedPreferences.class); + SharedPreferences.Editor editor = mock(SharedPreferences.Editor.class); + when(sharedPreferences.getLong(eq("lastUsed"), anyLong())).thenReturn(0L); + when(sharedPreferences.edit()).thenReturn(editor); + when(editor.putLong(anyString(), anyLong())).thenReturn(editor); + + try (MockedStatic prefManager = mockStatic(PreferenceManager.class); + MockedConstruction ignoredChannel = mockConstruction(NotificationChannel.class)) { + prefManager.when(() -> PreferenceManager.getDefaultSharedPreferences(context)) + .thenReturn(sharedPreferences); + + WorkerParameters workerParameters = mock(WorkerParameters.class); + AppUsageNotificationWorker worker = new AppUsageNotificationWorker(context, workerParameters); + + worker.doWork(); + } + + verify(notificationManager, times(1)).notify(eq(0), any(Notification.class)); + + ArgumentCaptor captor = ArgumentCaptor.forClass(Long.class); + verify(editor).putLong(eq("lastUsed"), captor.capture()); + verify(editor).apply(); + assertTrue(captor.getValue() > 0L); + } + + @Test + public void doWork_lastUsedWithinThreshold_noNotificationButTimestampUpdated() { + Context context = mock(Context.class); + when(context.getApplicationContext()).thenReturn(context); + when(context.getString(anyInt())).thenReturn(""); + NotificationManager notificationManager = mock(NotificationManager.class); + when(context.getSystemService(Context.NOTIFICATION_SERVICE)).thenReturn(notificationManager); + + long lastUsed = System.currentTimeMillis(); + SharedPreferences sharedPreferences = mock(SharedPreferences.class); + SharedPreferences.Editor editor = mock(SharedPreferences.Editor.class); + when(sharedPreferences.getLong(eq("lastUsed"), anyLong())).thenReturn(lastUsed); + when(sharedPreferences.edit()).thenReturn(editor); + when(editor.putLong(anyString(), anyLong())).thenReturn(editor); + + try (MockedStatic prefManager = mockStatic(PreferenceManager.class); + MockedConstruction ignoredChannel = mockConstruction(NotificationChannel.class)) { + prefManager.when(() -> PreferenceManager.getDefaultSharedPreferences(context)) + .thenReturn(sharedPreferences); + + WorkerParameters workerParameters = mock(WorkerParameters.class); + AppUsageNotificationWorker worker = new AppUsageNotificationWorker(context, workerParameters); + + worker.doWork(); + } + + verify(notificationManager, never()).notify(anyInt(), any(Notification.class)); + + ArgumentCaptor captor = ArgumentCaptor.forClass(Long.class); + verify(editor).putLong(eq("lastUsed"), captor.capture()); + verify(editor).apply(); + assertTrue(captor.getValue() >= lastUsed); + } +} +