/***************************************************************************
* Copyright 2006-2016 by Christian Ihle *
* contact@kouchat.net *
* *
* This file is part of KouChat. *
* *
* KouChat is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version. *
* *
* KouChat is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with KouChat. *
* If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
package net.usikkert.kouchat.android.notification;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
import net.usikkert.kouchat.android.R;
import net.usikkert.kouchat.android.controller.MainChatController;
import net.usikkert.kouchat.android.controller.ReceiveFileController;
import net.usikkert.kouchat.junit.ExpectedException;
import net.usikkert.kouchat.misc.User;
import net.usikkert.kouchat.net.FileReceiver;
import net.usikkert.kouchat.util.TestUtils;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.shadows.ShadowIntent;
import org.robolectric.shadows.ShadowNotification;
import org.robolectric.shadows.ShadowPendingIntent;
import android.app.Notification;
import android.app.NotificationManager;
/**
* Test of {@link NotificationService}.
*
* @author Christian Ihle
*/
@RunWith(RobolectricTestRunner.class)
public class NotificationServiceTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
private NotificationService notificationService;
private NotificationManager notificationManager;
private ArgumentCaptor<Notification> argumentCaptor;
private FileReceiver fileReceiver;
@Before
public void setUp() {
notificationService = new NotificationService(Robolectric.application);
notificationManager =
TestUtils.setFieldValueWithMock(notificationService, "notificationManager", NotificationManager.class);
argumentCaptor = ArgumentCaptor.forClass(Notification.class);
fileReceiver = new FileReceiver(new User("Niles", 1234), new File("picture.png"), 0, 12);
}
@Test
public void constructorShouldThrowExceptionIfContextIsNull() {
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Context can not be null");
new NotificationService(null);
}
@Test
public void createServiceNotificationShouldSetIconAndStartupMessage() {
final Notification notification = notificationService.createServiceNotification();
verifyThatRegularIconHasBeenSet(notification);
assertEquals("KouChat is up and running", notification.tickerText);
}
@Test
public void createServiceNotificationShouldFlagNotificationWithNoClearToAvoidSwipeToCancel() {
final Notification notification = notificationService.createServiceNotification();
assertEquals(Notification.FLAG_NO_CLEAR, notification.flags);
}
@Test
public void createServiceNotificationShouldSetNotificationTextForTheDrawer() {
final Notification notification = notificationService.createServiceNotification();
verifyThatNotificationTextIsRunning(notification);
}
@Test
public void createServiceNotificationShouldCreatePendingIntentForOpeningTheMainChat() {
final Notification notification = notificationService.createServiceNotification();
verifyThatPendingIntentOpensMainChat(notification);
}
@Test
public void createServiceNotificationShouldNotSetAnyChatActivity() {
notificationService.createServiceNotification();
assertFalse(notificationService.isMainChatActivity());
assertFalse(notificationService.isPrivateChatActivity());
}
@Test
public void notifyNewMainChatMessageShouldSetActivityIcon() {
notificationService.notifyNewMainChatMessage();
verify(notificationManager).notify(eq(1001), argumentCaptor.capture());
final Notification notification = argumentCaptor.getValue();
verifyThatActivityIconHasBeenSet(notification);
}
@Test
public void notifyNewMainChatMessageShouldFlagNotificationWithNoClearToAvoidSwipeToCancel() {
notificationService.notifyNewMainChatMessage();
verify(notificationManager).notify(eq(1001), argumentCaptor.capture());
final Notification notification = argumentCaptor.getValue();
assertEquals(Notification.FLAG_NO_CLEAR, notification.flags);
}
@Test
public void notifyNewMainChatMessageShouldSetNotificationTextForTheDrawer() {
notificationService.notifyNewMainChatMessage();
verify(notificationManager).notify(eq(1001), argumentCaptor.capture());
final Notification notification = argumentCaptor.getValue();
verifyThatNotificationTextIsNewUnreadMessages(notification);
}
@Test
public void notifyNewMainChatMessageShouldCreatePendingIntentForOpeningTheMainChat() {
notificationService.notifyNewMainChatMessage();
verify(notificationManager).notify(eq(1001), argumentCaptor.capture());
final Notification notification = argumentCaptor.getValue();
verifyThatPendingIntentOpensMainChat(notification);
}
@Test
public void notifyNewMainChatMessageShouldOnlySetMainChatActivityToTrue() {
notificationService.notifyNewMainChatMessage();
assertTrue(notificationService.isMainChatActivity());
assertFalse(notificationService.isPrivateChatActivity());
}
@Test
public void notifyNewPrivateChatMessageShouldThrowExceptionIfUserIsNull() {
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("User can not be null");
notificationService.notifyNewPrivateChatMessage(null);
}
@Test
public void notifyNewPrivateChatMessageShouldSetActivityIcon() {
notificationService.notifyNewPrivateChatMessage(new User("Test", 1234));
verify(notificationManager).notify(eq(1001), argumentCaptor.capture());
final Notification notification = argumentCaptor.getValue();
verifyThatActivityIconHasBeenSet(notification);
}
@Test
public void notifyNewPrivateChatMessageShouldFlagNotificationWithNoClearToAvoidSwipeToCancel() {
notificationService.notifyNewPrivateChatMessage(new User("Test", 1234));
verify(notificationManager).notify(eq(1001), argumentCaptor.capture());
final Notification notification = argumentCaptor.getValue();
assertEquals(Notification.FLAG_NO_CLEAR, notification.flags);
}
@Test
public void notifyNewPrivateChatMessageShouldSetNotificationTextForTheDrawer() {
notificationService.notifyNewPrivateChatMessage(new User("Test", 1234));
verify(notificationManager).notify(eq(1001), argumentCaptor.capture());
final Notification notification = argumentCaptor.getValue();
verifyThatNotificationTextIsNewUnreadMessages(notification);
}
@Test
public void notifyNewPrivateChatMessageShouldCreatePendingIntentForOpeningTheMainChat() {
notificationService.notifyNewPrivateChatMessage(new User("Test", 1234));
verify(notificationManager).notify(eq(1001), argumentCaptor.capture());
final Notification notification = argumentCaptor.getValue();
verifyThatPendingIntentOpensMainChat(notification);
}
@Test
public void notifyNewPrivateChatMessageShouldOnlySetPrivateChatActivityToTrue() {
notificationService.notifyNewPrivateChatMessage(new User("Test", 1234));
assertFalse(notificationService.isMainChatActivity());
assertTrue(notificationService.isPrivateChatActivity());
}
@Test
public void resetAllNotificationsShouldSetRegularIcon() {
notificationService.resetAllNotifications();
verify(notificationManager).notify(eq(1001), argumentCaptor.capture());
final Notification notification = argumentCaptor.getValue();
verifyThatRegularIconHasBeenSet(notification);
}
@Test
public void resetAllNotificationsShouldResetNotificationTextForTheDrawer() {
notificationService.resetAllNotifications();
verify(notificationManager).notify(eq(1001), argumentCaptor.capture());
final Notification notification = argumentCaptor.getValue();
verifyThatNotificationTextIsRunning(notification);
}
@Test
public void resetAllNotificationsShouldCreatePendingIntentForOpeningTheMainChat() {
notificationService.resetAllNotifications();
verify(notificationManager).notify(eq(1001), argumentCaptor.capture());
final Notification notification = argumentCaptor.getValue();
verifyThatPendingIntentOpensMainChat(notification);
}
@Test
public void resetAllNotificationsShouldSetMainChatActivityToFalse() {
TestUtils.setFieldValue(notificationService, "mainChatActivity", true);
assertTrue(notificationService.isMainChatActivity());
notificationService.resetAllNotifications();
assertFalse(notificationService.isMainChatActivity());
}
@Test
public void resetAllNotificationsShouldSetPrivateChatActivityToFalse() {
final User user = new User("Test", 1234);
final HashSet<User> users = new HashSet<User>();
users.add(user);
TestUtils.setFieldValue(notificationService, "privateChatActivityUsers", users);
assertTrue(notificationService.isPrivateChatActivity());
notificationService.resetAllNotifications();
assertFalse(notificationService.isPrivateChatActivity());
}
@Test
public void resetPrivateChatNotificationShouldThrowExceptionIfUserIsNull() {
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("User can not be null");
notificationService.resetPrivateChatNotification(null);
}
@Test
public void resetPrivateChatNotificationShouldSetRegularIcon() {
notificationService.resetPrivateChatNotification(new User("Test", 1234));
verify(notificationManager).notify(eq(1001), argumentCaptor.capture());
final Notification notification = argumentCaptor.getValue();
verifyThatRegularIconHasBeenSet(notification);
}
@Test
public void resetPrivateChatNotificationShouldResetNotificationTextForTheDrawer() {
notificationService.resetPrivateChatNotification(new User("Test", 1234));
verify(notificationManager).notify(eq(1001), argumentCaptor.capture());
final Notification notification = argumentCaptor.getValue();
verifyThatNotificationTextIsRunning(notification);
}
@Test
public void resetPrivateChatNotificationShouldCreatePendingIntentForOpeningTheMainChat() {
notificationService.resetPrivateChatNotification(new User("Test", 1234));
verify(notificationManager).notify(eq(1001), argumentCaptor.capture());
final Notification notification = argumentCaptor.getValue();
verifyThatPendingIntentOpensMainChat(notification);
}
@Test
public void resetPrivateChatNotificationShouldNotTouchMainChatActivity() {
TestUtils.setFieldValue(notificationService, "mainChatActivity", true);
assertTrue(notificationService.isMainChatActivity());
notificationService.resetPrivateChatNotification(new User("Test", 1234));
assertTrue(notificationService.isMainChatActivity());
}
@Test
public void resetPrivateChatNotificationShouldSetPrivateChatActivityToFalse() {
final User user = new User("Test", 1234);
final HashSet<User> users = new HashSet<User>();
users.add(user);
TestUtils.setFieldValue(notificationService, "privateChatActivityUsers", users);
assertTrue(notificationService.isPrivateChatActivity());
notificationService.resetPrivateChatNotification(user);
assertFalse(notificationService.isPrivateChatActivity());
}
@Test
public void resetPrivateChatNotificationShouldNotSendNotificationInThereIsMainChatActivity() {
TestUtils.setFieldValue(notificationService, "mainChatActivity", true);
assertTrue(notificationService.isMainChatActivity());
assertFalse(notificationService.isPrivateChatActivity());
notificationService.resetPrivateChatNotification(new User("Test", 1234));
verifyZeroInteractions(notificationManager);
TestUtils.setFieldValue(notificationService, "mainChatActivity", false);
notificationService.resetPrivateChatNotification(new User("Test", 1234));
verify(notificationManager).notify(anyInt(), any(Notification.class));
}
@Test
public void resetPrivateChatNotificationShouldNotSendNotificationIfThereIsPrivateChatActivity() {
final User user1 = new User("Test1", 1234);
final User user2 = new User("Test2", 1235);
final User user3 = new User("Test3", 1236);
final HashSet<User> users = new HashSet<User>();
users.add(user1);
users.add(user2);
users.add(user3);
TestUtils.setFieldValue(notificationService, "privateChatActivityUsers", users);
assertTrue(notificationService.isPrivateChatActivity());
assertFalse(notificationService.isMainChatActivity());
notificationService.resetPrivateChatNotification(user1);
verifyZeroInteractions(notificationManager);
assertTrue(notificationService.isPrivateChatActivity());
notificationService.resetPrivateChatNotification(user2);
verifyZeroInteractions(notificationManager);
assertTrue(notificationService.isPrivateChatActivity());
notificationService.resetPrivateChatNotification(user3);
verify(notificationManager).notify(anyInt(), any(Notification.class));
assertFalse(notificationService.isPrivateChatActivity());
}
@Test
public void resetPrivateChatNotificationShouldNotSendNotificationIfThereIsBothPrivateChatAndMainChatActivity() {
final User user1 = new User("Test1", 1234);
final User user2 = new User("Test2", 1235);
final HashSet<User> users = new HashSet<User>();
users.add(user1);
users.add(user2);
TestUtils.setFieldValue(notificationService, "privateChatActivityUsers", users);
assertTrue(notificationService.isPrivateChatActivity());
TestUtils.setFieldValue(notificationService, "mainChatActivity", true);
assertTrue(notificationService.isMainChatActivity());
notificationService.resetPrivateChatNotification(user1);
verifyZeroInteractions(notificationManager);
assertTrue(notificationService.isPrivateChatActivity());
assertTrue(notificationService.isMainChatActivity());
}
@Test
public void notifyNewFileTransferShouldThrowExceptionIfFileReceiverIsNull() {
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("FileReceiver can not be null");
notificationService.notifyNewFileTransfer(null);
}
@Test
public void notifyNewFileTransferShouldSetActivityIconAndStartupMessage() {
notificationService.notifyNewFileTransfer(fileReceiver);
verify(notificationManager).notify(eq(10012), argumentCaptor.capture());
final Notification notification = argumentCaptor.getValue();
assertEquals(R.drawable.ic_stat_notify_activity, notification.icon);
assertEquals("New file transfer request", notification.tickerText);
}
@Test
public void notifyNewFileTransferShouldSetNotificationTextForTheDrawer() {
notificationService.notifyNewFileTransfer(fileReceiver);
verify(notificationManager).notify(eq(10012), argumentCaptor.capture());
final Notification notification = argumentCaptor.getValue();
final ShadowNotification.LatestEventInfo latestEventInfo = getLatestEventInfo(notification);
assertEquals("File transfer from Niles", latestEventInfo.getContentTitle());
assertEquals("picture.png", latestEventInfo.getContentText());
}
@Test
public void notifyNewFileTransferShouldCreatePendingIntentForOpeningTheReceiveFileController() {
notificationService.notifyNewFileTransfer(fileReceiver);
verify(notificationManager).notify(eq(10012), argumentCaptor.capture());
final Notification notification = argumentCaptor.getValue();
final ShadowNotification.LatestEventInfo latestEventInfo = getLatestEventInfo(notification);
final ShadowIntent pendingIntent = getPendingIntent(latestEventInfo);
assertEquals(ReceiveFileController.class, pendingIntent.getIntentClass());
assertEquals(1234, pendingIntent.getIntExtra("userCode", -1));
assertEquals(12, pendingIntent.getIntExtra("fileTransferId", -1));
assertTrue(pendingIntent.getAction().matches("openReceiveFileDialog \\d{13}"));
}
@Test
public void notifyNewFileTransferShouldFlagNotificationWithNoClearToAvoidSwipeToCancel() {
notificationService.notifyNewFileTransfer(fileReceiver);
verify(notificationManager).notify(eq(10012), argumentCaptor.capture());
final Notification notification = argumentCaptor.getValue();
assertEquals(Notification.FLAG_NO_CLEAR, notification.flags);
}
@Test
public void notifyNewFileTransferShouldCreatePendingIntentWithUniqueRequestCodeToAvoidIntentExtrasFromBeingCached() {
notificationService.notifyNewFileTransfer(fileReceiver);
verify(notificationManager).notify(eq(10012), argumentCaptor.capture());
final Notification notification = argumentCaptor.getValue();
final ShadowNotification.LatestEventInfo latestEventInfo = getLatestEventInfo(notification);
final ShadowPendingIntent shadowPendingIntent = Robolectric.shadowOf(latestEventInfo.getContentIntent());
assertEquals(10012, shadowPendingIntent.getRequestCode());
}
@Test
public void notifyNewFileTransferShouldAddFileTransferIdToCurrentFileTransfers() {
final FileReceiver fileReceiver1 = createFileReceiver(101);
final FileReceiver fileReceiver2 = createFileReceiver(102);
final FileReceiver fileReceiver3 = createFileReceiver(103);
assertTrue(notificationService.getCurrentFileTransferIds().isEmpty());
notificationService.notifyNewFileTransfer(fileReceiver1);
verifyCurrentFileTransferIds(101);
notificationService.notifyNewFileTransfer(fileReceiver2);
verifyCurrentFileTransferIds(101, 102);
notificationService.notifyNewFileTransfer(fileReceiver3);
verifyCurrentFileTransferIds(101, 102, 103);
}
@Test
public void cancelFileTransferNotificationShouldThrowExceptionInFileReceiverIsNull() {
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("FileReceiver can not be null");
notificationService.cancelFileTransferNotification(null);
}
@Test
public void cancelFileTransferNotificationShouldCancelUsingFileReceiverId() {
notificationService.cancelFileTransferNotification(fileReceiver);
verify(notificationManager).cancel(10012);
}
@Test
public void cancelFileTransferNotificationShouldRemoveFileTransferIdFromCurrentFileTransfers() {
final FileReceiver fileReceiver1 = createFileReceiver(101);
final FileReceiver fileReceiver2 = createFileReceiver(102);
final FileReceiver fileReceiver3 = createFileReceiver(103);
assertTrue(notificationService.getCurrentFileTransferIds().isEmpty());
notificationService.notifyNewFileTransfer(fileReceiver1);
notificationService.notifyNewFileTransfer(fileReceiver2);
notificationService.notifyNewFileTransfer(fileReceiver3);
verifyCurrentFileTransferIds(101, 102, 103);
notificationService.cancelFileTransferNotification(fileReceiver2);
verifyCurrentFileTransferIds(101, 103);
notificationService.cancelFileTransferNotification(fileReceiver1);
verifyCurrentFileTransferIds(103);
notificationService.cancelFileTransferNotification(fileReceiver3);
assertTrue(notificationService.getCurrentFileTransferIds().isEmpty());
}
@Test
public void getCurrentFileTransferIdsShouldNotReturnAModifiableSet() {
expectedException.expect(UnsupportedOperationException.class);
final Set<Integer> set = notificationService.getCurrentFileTransferIds();
set.add(10);
}
private void verifyThatNotificationTextIsRunning(final Notification notification) {
final ShadowNotification.LatestEventInfo latestEventInfo = getLatestEventInfo(notification);
assertEquals("KouChat", latestEventInfo.getContentTitle());
assertEquals("Running", latestEventInfo.getContentText());
assertEquals(R.string.notification_running, notificationService.getCurrentLatestInfoTextId());
}
private void verifyThatNotificationTextIsNewUnreadMessages(final Notification notification) {
final ShadowNotification.LatestEventInfo latestEventInfo = getLatestEventInfo(notification);
assertEquals("KouChat", latestEventInfo.getContentTitle());
assertEquals("New unread messages", latestEventInfo.getContentText());
assertEquals(R.string.notification_new_message, notificationService.getCurrentLatestInfoTextId());
}
private void verifyThatPendingIntentOpensMainChat(final Notification notification) {
final ShadowNotification.LatestEventInfo latestEventInfo = getLatestEventInfo(notification);
final ShadowIntent pendingIntent = getPendingIntent(latestEventInfo);
assertEquals(MainChatController.class, pendingIntent.getIntentClass());
}
private void verifyThatRegularIconHasBeenSet(final Notification notification) {
assertEquals(R.drawable.ic_stat_notify_default, notification.icon);
assertEquals(R.drawable.ic_stat_notify_default, notificationService.getCurrentIconId());
}
private void verifyThatActivityIconHasBeenSet(final Notification notification) {
assertEquals(R.drawable.ic_stat_notify_activity, notification.icon);
assertEquals(R.drawable.ic_stat_notify_activity, notificationService.getCurrentIconId());
}
private ShadowNotification.LatestEventInfo getLatestEventInfo(final Notification notification) {
final ShadowNotification shadowNotification = Robolectric.shadowOf(notification);
return shadowNotification.getLatestEventInfo();
}
private ShadowIntent getPendingIntent(final ShadowNotification.LatestEventInfo latestEventInfo) {
final ShadowPendingIntent shadowPendingIntent = Robolectric.shadowOf(latestEventInfo.getContentIntent());
return Robolectric.shadowOf(shadowPendingIntent.getSavedIntent());
}
private FileReceiver createFileReceiver(final int fileTransferId) {
return new FileReceiver(new User("Holly", 567), new File("nothing.png"), 0, fileTransferId);
}
private void verifyCurrentFileTransferIds(final int... fileTransferIds) {
assertEquals(fileTransferIds.length, notificationService.getCurrentFileTransferIds().size());
for (final int fileTransferId : fileTransferIds) {
assertTrue(notificationService.getCurrentFileTransferIds().contains(fileTransferId));
}
}
}