package org.iilab.pb.alert; import android.app.AlarmManager; import android.app.Application; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.location.Location; import android.location.LocationManager; import android.os.Vibrator; import org.iilab.pb.common.AppConstants; import org.iilab.pb.common.ApplicationSettings; import org.iilab.pb.location.CurrentLocationProvider; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import org.robolectric.shadows.ShadowAlarmManager; import org.robolectric.shadows.ShadowApplication; import org.robolectric.shadows.ShadowLocationManager; import org.robolectric.shadows.ShadowVibrator; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; import static android.location.LocationManager.GPS_PROVIDER; import static android.location.LocationManager.NETWORK_PROVIDER; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; import static org.robolectric.Robolectric.shadowOf; @RunWith(RobolectricTestRunner.class) public class PanicAlertTest { private PanicAlert panicAlert; private Application context; private ShadowVibrator shadowVibrator; @Mock private ExecutorService mockExecutor; @Mock private PanicMessage mockPanicMessage; @Mock private CurrentLocationProvider mockCurrentLocationProvider; @Mock private Location mockLocation; private ShadowLocationManager shadowLocationManager; private ShadowAlarmManager shadowAlarmManager; @Mock private PackageManager mockPackageManager; @Before public void setUp() throws Exception { initMocks(this); context = Robolectric.application; setupPackageManager(); panicAlert = getPanicAlert(mockExecutor); shadowVibrator = shadowOf((Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE)); ApplicationSettings.setAlertActive(context, false); shadowLocationManager = shadowOf((LocationManager) context.getSystemService(Context.LOCATION_SERVICE)); shadowAlarmManager = shadowOf((AlarmManager) context.getSystemService(Context.ALARM_SERVICE)); shadowLocationManager.setProviderEnabled(NETWORK_PROVIDER, true); shadowLocationManager.setProviderEnabled(GPS_PROVIDER, true); } private void setupPackageManager() { ShadowApplication shadowApplication = shadowOf(Robolectric.application); shadowApplication.setPackageManager(mockPackageManager); List<ResolveInfo> activities = new ArrayList<ResolveInfo>(); activities.add(resolveInfo("com.test.package.Class1")); activities.add(resolveInfo("com.test.package.Class2")); when(mockPackageManager.queryIntentActivities(any(Intent.class), anyInt())).thenReturn(activities); } private ResolveInfo resolveInfo(String packageName) { ResolveInfo resolveInfo = new ResolveInfo(); ActivityInfo activityInfo = new ActivityInfo(); activityInfo.packageName = packageName; resolveInfo.activityInfo = activityInfo; return resolveInfo; } @Test public void shouldActiveTheAlertWithHapticFeedback() throws IllegalAccessException { panicAlert.activate(); assertEquals(500, shadowVibrator.getMilliseconds()); assertTrue(panicAlert.isActive()); verify(mockExecutor).execute(any(Runnable.class)); Intent startedIntent = shadowOf(context).peekNextStartedActivity(); assertEquals(startedIntent.getPackage(), "com.test.package.Class1"); } @Test public void shouldNotActiveAgainIfItIsAlreadyActive() throws IllegalAccessException { ApplicationSettings.setAlertActive(context, true); panicAlert.activate(); assertEquals(500, shadowVibrator.getMilliseconds()); verifyZeroInteractions(mockExecutor); } @Test public void shouldReturnActiveAlertStatus() throws Exception { ApplicationSettings.setAlertActive(context, true); // assertEquals(AlertStatus.ACTIVE, panicAlert.isActive()); assertEquals(true, panicAlert.isActive()); } @Test public void shouldReturnStandByAlertStatus() throws Exception { // assertEquals(AlertStatus.STANDBY, panicAlert.isActive()); assertEquals(false, panicAlert.isActive()); } @Test public void shouldSendTheFirstAlertOnActivation() { panicAlert = getPanicAlert(new TestExecutorService()); when(mockCurrentLocationProvider.getLocation()).thenReturn(mockLocation); panicAlert.activate(); verify(mockPanicMessage).sendAlertMessage(mockLocation); } @Test public void shouldSendAlertWithOutLocationIfLocationNotAvaiable() { panicAlert = getPanicAlert(new TestExecutorService()); when(mockCurrentLocationProvider.getLocation()).thenReturn(null); panicAlert.activate(); verify(mockPanicMessage).sendAlertMessage(null); } @Test public void shouldScheduleForContinuousAlertOnActivationAndGoToHomeScreen() { panicAlert = getPanicAlert(new TestExecutorService()); when(mockCurrentLocationProvider.getLocation()).thenReturn(mockLocation); panicAlert.activate(); Map<PendingIntent, String> requestLocationUpdates = shadowLocationManager.getRequestLocationUdpateProviderPendingIntents(); List<ShadowAlarmManager.ScheduledAlarm> scheduledAlarms = shadowAlarmManager.getScheduledAlarms(); ShadowAlarmManager.ScheduledAlarm alarm = scheduledAlarms.get(0); assertEquals(2, requestLocationUpdates.size()); assertTrue(requestLocationUpdates.values().containsAll(Arrays.asList(NETWORK_PROVIDER, GPS_PROVIDER))); assertEquals(1, scheduledAlarms.size()); assertEquals(AppConstants.DEFAULT_ALARM_INTERVAL * 1000 * 60, alarm.interval); assertEquals(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarm.type); Intent startedIntent = shadowOf(context).peekNextStartedActivity(); List<String> categories = new ArrayList<String>(startedIntent.getCategories()); assertEquals(categories.get(0), Intent.CATEGORY_HOME); assertEquals(startedIntent.getPackage(), "com.test.package.Class1"); } @Test public void shouldDeactivateTheAlert() { panicAlert = getPanicAlert(new TestExecutorService()); when(mockCurrentLocationProvider.getLocation()).thenReturn(mockLocation); panicAlert.activate(); panicAlert.deActivate(); List<ShadowAlarmManager.ScheduledAlarm> scheduledAlarms = shadowAlarmManager.getScheduledAlarms(); assertFalse(ApplicationSettings.isAlertActive(context)); assertEquals(0, scheduledAlarms.size()); } private class TestExecutorService extends ScheduledThreadPoolExecutor { public TestExecutorService() { super(1); } @Override public void execute(Runnable runnable) { runnable.run(); } } private PanicAlert getPanicAlert(final ExecutorService executorService) { return new PanicAlert(context) { ExecutorService getExecutorService() { return executorService; } PanicMessage createPanicMessage() { return mockPanicMessage; } CurrentLocationProvider getCurrentLocationProvider() { return mockCurrentLocationProvider; } }; } }