package com.fsck.k9.notification; import android.app.Notification; import android.support.v4.app.NotificationManagerCompat; import com.fsck.k9.Account; import com.fsck.k9.K9; import com.fsck.k9.K9.NotificationHideSubject; import com.fsck.k9.K9RobolectricTestRunner; import com.fsck.k9.activity.MessageReference; import com.fsck.k9.mailstore.LocalMessage; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @RunWith(K9RobolectricTestRunner.class) public class NewMailNotificationsTest { private static final int ACCOUNT_NUMBER = 23; private Account account; private TestNewMailNotifications newMailNotifications; private NotificationManagerCompat notificationManager; private NotificationContentCreator contentCreator; private DeviceNotifications deviceNotifications; private WearNotifications wearNotifications; @Before public void setUp() throws Exception { account = createAccount(); notificationManager = createNotificationManager(); NotificationController controller = createNotificationController(notificationManager); contentCreator = createNotificationContentCreator(); deviceNotifications = createDeviceNotifications(); wearNotifications = createWearNotifications(); newMailNotifications = new TestNewMailNotifications(controller, contentCreator, deviceNotifications, wearNotifications); } @Test public void testAddNewMailNotification() throws Exception { int notificationIndex = 0; LocalMessage message = createLocalMessage(); NotificationContent content = createNotificationContent(); NotificationHolder holder = createNotificationHolder(content, notificationIndex); addToNotificationContentCreator(message, content); whenAddingContentReturn(content, AddNotificationResult.newNotification(holder)); Notification wearNotification = createNotification(); Notification summaryNotification = createNotification(); addToWearNotifications(holder, wearNotification); addToDeviceNotifications(summaryNotification); newMailNotifications.addNewMailNotification(account, message, 42); int wearNotificationId = NotificationIds.getNewMailStackedNotificationId(account, notificationIndex); int summaryNotificationId = NotificationIds.getNewMailSummaryNotificationId(account); verify(notificationManager).notify(wearNotificationId, wearNotification); verify(notificationManager).notify(summaryNotificationId, summaryNotification); } @Test public void testAddNewMailNotificationWithCancelingExistingNotification() throws Exception { int notificationIndex = 0; LocalMessage message = createLocalMessage(); NotificationContent content = createNotificationContent(); NotificationHolder holder = createNotificationHolder(content, notificationIndex); addToNotificationContentCreator(message, content); whenAddingContentReturn(content, AddNotificationResult.replaceNotification(holder)); Notification wearNotification = createNotification(); Notification summaryNotification = createNotification(); addToWearNotifications(holder, wearNotification); addToDeviceNotifications(summaryNotification); newMailNotifications.addNewMailNotification(account, message, 42); int wearNotificationId = NotificationIds.getNewMailStackedNotificationId(account, notificationIndex); int summaryNotificationId = NotificationIds.getNewMailSummaryNotificationId(account); verify(notificationManager).notify(wearNotificationId, wearNotification); verify(notificationManager).cancel(wearNotificationId); verify(notificationManager).notify(summaryNotificationId, summaryNotification); } @Test public void testAddNewMailNotificationWithPrivacyModeEnabled() throws Exception { enablePrivacyMode(); int notificationIndex = 0; LocalMessage message = createLocalMessage(); NotificationContent content = createNotificationContent(); NotificationHolder holder = createNotificationHolder(content, notificationIndex); addToNotificationContentCreator(message, content); whenAddingContentReturn(content, AddNotificationResult.newNotification(holder)); Notification wearNotification = createNotification(); addToDeviceNotifications(wearNotification); newMailNotifications.addNewMailNotification(account, message, 42); int wearNotificationId = NotificationIds.getNewMailStackedNotificationId(account, notificationIndex); int summaryNotificationId = NotificationIds.getNewMailSummaryNotificationId(account); verify(notificationManager, never()).notify(eq(wearNotificationId), any(Notification.class)); verify(notificationManager).notify(summaryNotificationId, wearNotification); } @Test public void testAddNewMailNotificationTwice() throws Exception { int notificationIndexOne = 0; int notificationIndexTwo = 1; LocalMessage messageOne = createLocalMessage(); LocalMessage messageTwo = createLocalMessage(); NotificationContent contentOne = createNotificationContent(); NotificationContent contentTwo = createNotificationContent(); NotificationHolder holderOne = createNotificationHolder(contentOne, notificationIndexOne); NotificationHolder holderTwo = createNotificationHolder(contentTwo, notificationIndexTwo); addToNotificationContentCreator(messageOne, contentOne); addToNotificationContentCreator(messageTwo, contentTwo); whenAddingContentReturn(contentOne, AddNotificationResult.newNotification(holderOne)); whenAddingContentReturn(contentTwo, AddNotificationResult.newNotification(holderTwo)); Notification wearNotificationOne = createNotification(); Notification wearNotificationTwo = createNotification(); Notification summaryNotification = createNotification(); addToWearNotifications(holderOne, wearNotificationOne); addToWearNotifications(holderTwo, wearNotificationTwo); addToDeviceNotifications(summaryNotification); newMailNotifications.addNewMailNotification(account, messageOne, 42); newMailNotifications.addNewMailNotification(account, messageTwo, 42); int wearNotificationIdOne = NotificationIds.getNewMailStackedNotificationId(account, notificationIndexOne); int wearNotificationIdTwo = NotificationIds.getNewMailStackedNotificationId(account, notificationIndexTwo); int summaryNotificationId = NotificationIds.getNewMailSummaryNotificationId(account); verify(notificationManager).notify(wearNotificationIdOne, wearNotificationOne); verify(notificationManager).notify(wearNotificationIdTwo, wearNotificationTwo); verify(notificationManager, times(2)).notify(summaryNotificationId, summaryNotification); } @Test public void testRemoveNewMailNotificationWithoutNotificationData() throws Exception { MessageReference messageReference = createMessageReference(1); newMailNotifications.removeNewMailNotification(account, messageReference); verify(notificationManager, never()).cancel(anyInt()); } @Test public void testRemoveNewMailNotificationWithUnknownMessageReference() throws Exception { enablePrivacyMode(); MessageReference messageReference = createMessageReference(1); int notificationIndex = 0; LocalMessage message = createLocalMessage(); NotificationContent content = createNotificationContent(); NotificationHolder holder = createNotificationHolder(content, notificationIndex); addToNotificationContentCreator(message, content); whenAddingContentReturn(content, AddNotificationResult.newNotification(holder)); Notification summaryNotification = createNotification(); addToDeviceNotifications(summaryNotification); newMailNotifications.addNewMailNotification(account, message, 23); whenRemovingContentReturn(messageReference, RemoveNotificationResult.unknownNotification()); newMailNotifications.removeNewMailNotification(account, messageReference); verify(notificationManager, never()).cancel(anyInt()); } @Test public void testRemoveNewMailNotification() throws Exception { enablePrivacyMode(); MessageReference messageReference = createMessageReference(1); int notificationIndex = 0; int notificationId = NotificationIds.getNewMailStackedNotificationId(account, notificationIndex); LocalMessage message = createLocalMessage(); NotificationContent content = createNotificationContent(); NotificationHolder holder = createNotificationHolder(content, notificationIndex); addToNotificationContentCreator(message, content); whenAddingContentReturn(content, AddNotificationResult.newNotification(holder)); Notification summaryNotification = createNotification(); addToDeviceNotifications(summaryNotification); newMailNotifications.addNewMailNotification(account, message, 23); whenRemovingContentReturn(messageReference, RemoveNotificationResult.cancelNotification(notificationId)); newMailNotifications.removeNewMailNotification(account, messageReference); int summaryNotificationId = NotificationIds.getNewMailSummaryNotificationId(account); verify(notificationManager).cancel(notificationId); verify(notificationManager, times(2)).notify(summaryNotificationId, summaryNotification); } @Test public void testRemoveNewMailNotificationClearingAllNotifications() throws Exception { MessageReference messageReference = createMessageReference(1); int notificationIndex = 0; int notificationId = NotificationIds.getNewMailStackedNotificationId(account, notificationIndex); LocalMessage message = createLocalMessage(); NotificationContent content = createNotificationContent(); NotificationHolder holder = createNotificationHolder(content, notificationIndex); addToNotificationContentCreator(message, content); whenAddingContentReturn(content, AddNotificationResult.newNotification(holder)); Notification summaryNotification = createNotification(); addToDeviceNotifications(summaryNotification); newMailNotifications.addNewMailNotification(account, message, 23); whenRemovingContentReturn(messageReference, RemoveNotificationResult.cancelNotification(notificationId)); when(newMailNotifications.notificationData.getNewMessagesCount()).thenReturn(0); setActiveNotificationIds(); newMailNotifications.removeNewMailNotification(account, messageReference); int summaryNotificationId = NotificationIds.getNewMailSummaryNotificationId(account); verify(notificationManager).cancel(notificationId); verify(notificationManager).cancel(summaryNotificationId); } @Test public void testRemoveNewMailNotificationWithCreateNotification() throws Exception { MessageReference messageReference = createMessageReference(1); int notificationIndex = 0; int notificationId = NotificationIds.getNewMailStackedNotificationId(account, notificationIndex); LocalMessage message = createLocalMessage(); NotificationContent contentOne = createNotificationContent(); NotificationContent contentTwo = createNotificationContent(); NotificationHolder holderOne = createNotificationHolder(contentOne, notificationIndex); NotificationHolder holderTwo = createNotificationHolder(contentTwo, notificationIndex); addToNotificationContentCreator(message, contentOne); whenAddingContentReturn(contentOne, AddNotificationResult.newNotification(holderOne)); Notification summaryNotification = createNotification(); addToDeviceNotifications(summaryNotification); Notification wearNotificationOne = createNotification(); Notification wearNotificationTwo = createNotification(); addToWearNotifications(holderOne, wearNotificationOne); addToWearNotifications(holderTwo, wearNotificationTwo); newMailNotifications.addNewMailNotification(account, message, 23); whenRemovingContentReturn(messageReference, RemoveNotificationResult.createNotification(holderTwo)); newMailNotifications.removeNewMailNotification(account, messageReference); int summaryNotificationId = NotificationIds.getNewMailSummaryNotificationId(account); verify(notificationManager).cancel(notificationId); verify(notificationManager).notify(notificationId, wearNotificationTwo); verify(notificationManager, times(2)).notify(summaryNotificationId, summaryNotification); } @Test public void testClearNewMailNotificationsWithoutNotificationData() throws Exception { newMailNotifications.clearNewMailNotifications(account); verify(notificationManager, never()).cancel(anyInt()); } @Test public void testClearNewMailNotifications() throws Exception { int notificationIndex = 0; int notificationId = NotificationIds.getNewMailStackedNotificationId(account, notificationIndex); LocalMessage message = createLocalMessage(); NotificationContent content = createNotificationContent(); NotificationHolder holder = createNotificationHolder(content, notificationIndex); addToNotificationContentCreator(message, content); setActiveNotificationIds(notificationId); whenAddingContentReturn(content, AddNotificationResult.newNotification(holder)); newMailNotifications.addNewMailNotification(account, message, 3); newMailNotifications.clearNewMailNotifications(account); verify(notificationManager).cancel(notificationId); verify(notificationManager).cancel(NotificationIds.getNewMailSummaryNotificationId(account)); } private Account createAccount() { Account account = mock(Account.class); when(account.getAccountNumber()).thenReturn(ACCOUNT_NUMBER); return account; } private LocalMessage createLocalMessage() { return mock(LocalMessage.class); } private NotificationContent createNotificationContent() { return new NotificationContent(null, null, null, null, null, false); } private NotificationHolder createNotificationHolder(NotificationContent content, int index) { int notificationId = NotificationIds.getNewMailStackedNotificationId(account, index); return new NotificationHolder(notificationId, content); } private NotificationManagerCompat createNotificationManager() { return mock(NotificationManagerCompat.class); } private NotificationController createNotificationController(NotificationManagerCompat notificationManager) { NotificationController controller = mock(NotificationController.class); when(controller.getNotificationManager()).thenReturn(notificationManager); return controller; } private NotificationContentCreator createNotificationContentCreator() { return mock(NotificationContentCreator.class); } private void addToNotificationContentCreator(LocalMessage message, NotificationContent content) { when(contentCreator.createFromMessage(account, message)).thenReturn(content); } private DeviceNotifications createDeviceNotifications() { return mock(DeviceNotifications.class); } private void addToDeviceNotifications(Notification notificationToReturn) { when(deviceNotifications.buildSummaryNotification( eq(account), eq(newMailNotifications.notificationData), anyBoolean()) ).thenReturn(notificationToReturn); } private Notification createNotification() { return mock(Notification.class); } private WearNotifications createWearNotifications() { return mock(WearNotifications.class); } private MessageReference createMessageReference(int number) { return new MessageReference("account", "folder", String.valueOf(number), null); } private void addToWearNotifications(NotificationHolder notificationHolder, Notification notificationToReturn) { when(wearNotifications.buildStackedNotification(account, notificationHolder)).thenReturn(notificationToReturn); } private void whenAddingContentReturn(NotificationContent content, AddNotificationResult result) { NotificationData notificationData = newMailNotifications.notificationData; when(notificationData.addNotificationContent(content)).thenReturn(result); int newCount = notificationData.getNewMessagesCount() + 1; when(notificationData.getNewMessagesCount()).thenReturn(newCount); } private void whenRemovingContentReturn(MessageReference messageReference, RemoveNotificationResult result) { NotificationData notificationData = newMailNotifications.notificationData; when(notificationData.removeNotificationForMessage(messageReference)).thenReturn(result); } private void setActiveNotificationIds(int... notificationIds) { NotificationData notificationData = newMailNotifications.notificationData; when(notificationData.getActiveNotificationIds()).thenReturn(notificationIds); } private void enablePrivacyMode() { K9.setNotificationHideSubject(NotificationHideSubject.ALWAYS); } static class TestNewMailNotifications extends NewMailNotifications { public final NotificationData notificationData; TestNewMailNotifications(NotificationController controller, NotificationContentCreator contentCreator, DeviceNotifications deviceNotifications, WearNotifications wearNotifications) { super(controller, contentCreator, deviceNotifications, wearNotifications); notificationData = mock(NotificationData.class); } @Override NotificationData createNotificationData(Account account, int unreadMessageCount) { return notificationData; } } }