Add robolectric tests for EmergencyContactsPreference.
Remove instrumentation tests they replace.
Bug: 30046624
Test: make RunEmergencyInfoRoboTests
Change-Id: I3ef549d55b573bd2132930ac1aea22c1627433c0
(cherry picked from commit ec15f8b319f9e38c064f8b521dba6c2dfa0a4117)
diff --git a/src/com/android/emergency/preferences/ContactPreference.java b/src/com/android/emergency/preferences/ContactPreference.java
index ebe1dea..7194b5e 100644
--- a/src/com/android/emergency/preferences/ContactPreference.java
+++ b/src/com/android/emergency/preferences/ContactPreference.java
@@ -54,6 +54,13 @@
private static final String TAG = "ContactPreference";
+ static final ContactFactory DEFAULT_CONTACT_FACTORY = new ContactFactory() {
+ @Override
+ public EmergencyContactManager.Contact getContact(Context context, Uri phoneUri) {
+ return EmergencyContactManager.getContact(context, phoneUri);
+ }
+ };
+
private final ContactFactory mContactFactory;
private EmergencyContactManager.Contact mContact;
@Nullable private RemoveContactPreferenceListener mRemoveContactPreferenceListener;
@@ -88,16 +95,11 @@
* the Uri.
*/
public ContactPreference(Context context, @NonNull Uri phoneUri) {
- this(context, phoneUri, new ContactFactory() {
- @Override
- public EmergencyContactManager.Contact getContact(Context context, Uri phoneUri) {
- return EmergencyContactManager.getContact(context, phoneUri);
- }
- });
+ this(context, phoneUri, DEFAULT_CONTACT_FACTORY);
}
@VisibleForTesting
- public ContactPreference(Context context, @NonNull Uri phoneUri,
+ ContactPreference(Context context, @NonNull Uri phoneUri,
@NonNull ContactFactory contactFactory) {
super(context);
mContactFactory = contactFactory;
diff --git a/src/com/android/emergency/preferences/EmergencyContactsPreference.java b/src/com/android/emergency/preferences/EmergencyContactsPreference.java
index 166e385..ff9d0ca 100644
--- a/src/com/android/emergency/preferences/EmergencyContactsPreference.java
+++ b/src/com/android/emergency/preferences/EmergencyContactsPreference.java
@@ -22,6 +22,7 @@
import android.preference.Preference;
import android.preference.PreferenceCategory;
import android.preference.PreferenceManager;
+import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.Toast;
@@ -52,13 +53,44 @@
private static final String CONTACT_SEPARATOR = "|";
private static final String QUOTE_CONTACT_SEPARATOR = Pattern.quote(CONTACT_SEPARATOR);
+ private static final ContactValidator DEFAULT_CONTACT_VALIDATOR = new ContactValidator() {
+ @Override
+ public boolean isValidEmergencyContact(Context context, Uri phoneUri) {
+ return EmergencyContactManager.isValidEmergencyContact(context, phoneUri);
+ }
+ };
+ private final ContactValidator mContactValidator;
+ private final ContactPreference.ContactFactory mContactFactory;
/** Stores the emergency contact's ContactsContract.CommonDataKinds.Phone.CONTENT_URI */
private List<Uri> mEmergencyContacts = new ArrayList<Uri>();
private boolean mEmergencyContactsSet = false;
+ /**
+ * Interface for getting a contact for a phone number Uri.
+ */
+ public interface ContactValidator {
+ /**
+ * Checks whether a given phone Uri represents a valid emergency contact.
+ *
+ * @param context The context to use.
+ * @param phoneUri The phone uri.
+ * @return whether the given phone Uri is a valid emergency contact.
+ */
+ boolean isValidEmergencyContact(Context context, Uri phoneUri);
+ }
+
public EmergencyContactsPreference(Context context, AttributeSet attrs) {
+ this(context, attrs, DEFAULT_CONTACT_VALIDATOR, ContactPreference.DEFAULT_CONTACT_FACTORY);
+ }
+
+ @VisibleForTesting
+ EmergencyContactsPreference(Context context, AttributeSet attrs,
+ @NonNull ContactValidator contactValidator,
+ @NonNull ContactPreference.ContactFactory contactFactory) {
super(context, attrs);
+ mContactValidator = contactValidator;
+ mContactFactory = contactFactory;
}
@Override
@@ -67,7 +99,8 @@
getPersistedEmergencyContacts() :
deserializeAndFilter(getKey(),
getContext(),
- (String) defaultValue));
+ (String) defaultValue,
+ mContactValidator));
}
@Override
@@ -106,7 +139,7 @@
if (mEmergencyContacts.contains(phoneUri)) {
return;
}
- if (!EmergencyContactManager.isValidEmergencyContact(getContext(), phoneUri)) {
+ if (!mContactValidator.isValidEmergencyContact(getContext(), phoneUri)) {
Toast.makeText(getContext(), getContext().getString(R.string.fail_add_contact),
Toast.LENGTH_LONG).show();
return;
@@ -128,7 +161,7 @@
if (changed || !mEmergencyContactsSet) {
mEmergencyContacts = emergencyContacts;
mEmergencyContactsSet = true;
- persistString(serialize(emergencyContacts));
+ persistEmergencyContacts(emergencyContacts);
if (changed) {
notifyChanged();
}
@@ -153,7 +186,8 @@
contactPreference = (ContactPreference) getPreference(i);
contactPreference.setPhoneUri(phoneUri);
} else {
- contactPreference = new ContactPreference(getContext(), phoneUri);
+ contactPreference =
+ new ContactPreference(getContext(), phoneUri, mContactFactory);
onBindContactView(contactPreference);
addPreference(contactPreference);
}
@@ -198,7 +232,8 @@
}
private List<Uri> getPersistedEmergencyContacts() {
- return deserializeAndFilter(getKey(), getContext(), getPersistedString(""));
+ return deserializeAndFilter(getKey(), getContext(), getPersistedString(""),
+ mContactValidator);
}
@Override
@@ -221,25 +256,8 @@
*/
public static List<Uri> deserializeAndFilter(String key, Context context,
String emergencyContactString) {
- String[] emergencyContactsArray =
- emergencyContactString.split(QUOTE_CONTACT_SEPARATOR);
- List<Uri> filteredEmergencyContacts = new ArrayList<Uri>(emergencyContactsArray.length);
- for (String emergencyContact : emergencyContactsArray) {
- Uri phoneUri = Uri.parse(emergencyContact);
- if (EmergencyContactManager.isValidEmergencyContact(context, phoneUri)) {
- filteredEmergencyContacts.add(phoneUri);
- }
- }
- // If not all contacts were added, then we need to overwrite the emergency contacts stored
- // in shared preferences. This deals with emergency contacts being deleted from contacts:
- // currently we have no way to being notified when this happens.
- if (filteredEmergencyContacts.size() != emergencyContactsArray.length) {
- String emergencyContactStrings = serialize(filteredEmergencyContacts);
- SharedPreferences sharedPreferences =
- PreferenceManager.getDefaultSharedPreferences(context);
- sharedPreferences.edit().putString(key, emergencyContactStrings).commit();
- }
- return filteredEmergencyContacts;
+ return deserializeAndFilter(key, context, emergencyContactString,
+ DEFAULT_CONTACT_VALIDATOR);
}
/** Converts the Uris to a string representation. */
@@ -255,4 +273,33 @@
}
return sb.toString();
}
+
+ @VisibleForTesting
+ void persistEmergencyContacts(List<Uri> emergencyContacts) {
+ persistString(serialize(emergencyContacts));
+ }
+
+ private static List<Uri> deserializeAndFilter(String key, Context context,
+ String emergencyContactString,
+ ContactValidator contactValidator) {
+ String[] emergencyContactsArray =
+ emergencyContactString.split(QUOTE_CONTACT_SEPARATOR);
+ List<Uri> filteredEmergencyContacts = new ArrayList<Uri>(emergencyContactsArray.length);
+ for (String emergencyContact : emergencyContactsArray) {
+ Uri phoneUri = Uri.parse(emergencyContact);
+ if (contactValidator.isValidEmergencyContact(context, phoneUri)) {
+ filteredEmergencyContacts.add(phoneUri);
+ }
+ }
+ // If not all contacts were added, then we need to overwrite the emergency contacts stored
+ // in shared preferences. This deals with emergency contacts being deleted from contacts:
+ // currently we have no way to being notified when this happens.
+ if (filteredEmergencyContacts.size() != emergencyContactsArray.length) {
+ String emergencyContactStrings = serialize(filteredEmergencyContacts);
+ SharedPreferences sharedPreferences =
+ PreferenceManager.getDefaultSharedPreferences(context);
+ sharedPreferences.edit().putString(key, emergencyContactStrings).commit();
+ }
+ return filteredEmergencyContacts;
+ }
}
diff --git a/tests/instrumentation/src/com/android/emergency/preferences/EmergencyContactsPreferenceTest.java b/tests/instrumentation/src/com/android/emergency/preferences/EmergencyContactsPreferenceTest.java
index 45bea8b..ac4b1e0 100644
--- a/tests/instrumentation/src/com/android/emergency/preferences/EmergencyContactsPreferenceTest.java
+++ b/tests/instrumentation/src/com/android/emergency/preferences/EmergencyContactsPreferenceTest.java
@@ -77,101 +77,6 @@
super.tearDown();
}
- public void testEmptyState() {
- assertThat(mEmergencyContactsPreference).isNotNull();
- assertThat(mEmergencyContactsPreference.isPersistent()).isTrue();
- assertThat(mEmergencyContactsPreference.isNotSet()).isTrue();
- assertThat(mEmergencyContactsPreference.getEmergencyContacts()).isEmpty();
- assertThat(mEmergencyContactsPreference.getPreferenceCount()).isEqualTo(0);
- }
-
- public void testAddAndRemoveEmergencyContact() throws Throwable {
- final String name = "Jane";
- final String phoneNumber = "456";
-
- final Uri phoneUri =
- ContactTestUtils.createContact(mContentResolver, name, phoneNumber);
- runTestOnUiThread(new Runnable() {
- @Override
- public void run() {
- mEmergencyContactsPreference.addNewEmergencyContact(phoneUri);
- }
- });
-
- assertThat(mEmergencyContactsPreference.getEmergencyContacts().size()).isEqualTo(1);
- assertThat(mEmergencyContactsPreference.getPreferenceCount()).isEqualTo(1);
- ContactPreference contactPreference = (ContactPreference)
- mEmergencyContactsPreference.getPreference(0);
-
- assertThat(contactPreference.getPhoneUri()).isEqualTo(phoneUri);
- assertThat(contactPreference.getTitle()).isEqualTo(name);
- assertThat((String) contactPreference.getSummary()).contains(phoneNumber);
-
- runTestOnUiThread(new Runnable() {
- @Override
- public void run() {
- mEmergencyContactsPreference.onRemoveContactPreference(
- (ContactPreference) mEmergencyContactsPreference.getPreference(0));
- }
- });
-
- assertThat(mEmergencyContactsPreference.getEmergencyContacts()).isEmpty();
- assertThat(mEmergencyContactsPreference.getPreferenceCount()).isEqualTo(0);
-
- // Clean up the inserted contact
- assertThat(ContactTestUtils.deleteContact(mContentResolver, name, phoneNumber)).isTrue();
- }
-
- public void testReloadFromPreference() throws Throwable {
- final String nameJane = "Jane";
- final String phoneNumberJane = "456";
- final Uri emergencyContactJane = ContactTestUtils
- .createContact(mContentResolver, nameJane, phoneNumberJane);
-
- final String nameJohn = "John";
- final String phoneNumberJohn = "123";
- final Uri emergencyContactJohn = ContactTestUtils
- .createContact(mContentResolver, nameJohn, phoneNumberJohn);
-
- final List<Uri> emergencyContacts = new ArrayList<>();
- emergencyContacts.add(emergencyContactJane);
- emergencyContacts.add(emergencyContactJohn);
- runTestOnUiThread(new Runnable() {
- @Override
- public void run() {
- mEmergencyContactsPreference.setEmergencyContacts(emergencyContacts);
- }
- });
-
- assertThat(mEmergencyContactsPreference.getEmergencyContacts().size()).isEqualTo(2);
- assertThat(mEmergencyContactsPreference.getPreferenceCount()).isEqualTo(2);
-
- // Delete Jane from another app (e.g. contacts)
- assertThat(ContactTestUtils
- .deleteContact(mContentResolver, nameJane, phoneNumberJane)).isTrue();
- getInstrumentation().waitForIdleSync();
-
- runTestOnUiThread(new Runnable() {
- @Override
- public void run() {
- mEmergencyContactsPreference.reloadFromPreference();
- }
- });
-
- getInstrumentation().waitForIdleSync();
-
- // Assert the only remaining contact is John
- assertThat(mEmergencyContactsPreference.getEmergencyContacts().size()).isEqualTo(1);
- assertThat(mEmergencyContactsPreference.getPreferenceCount()).isEqualTo(1);
- ContactPreference contactPreference = (ContactPreference)
- mEmergencyContactsPreference.getPreference(0);
- assertThat(contactPreference.getPhoneUri()).isEqualTo(emergencyContactJohn);
-
- // Clean up the inserted contact
- assertThat(ContactTestUtils
- .deleteContact(mContentResolver, nameJohn, phoneNumberJohn)).isTrue();
- }
-
public void testWidgetClick_positiveButton() throws Throwable {
final String name = "Jane";
final String phoneNumber = "456";
diff --git a/tests/robolectric/src/com/android/emergency/preferences/ContactPreferencesTest.java b/tests/robolectric/src/com/android/emergency/preferences/ContactPreferencesTest.java
index 81493f7..7a039e4 100644
--- a/tests/robolectric/src/com/android/emergency/preferences/ContactPreferencesTest.java
+++ b/tests/robolectric/src/com/android/emergency/preferences/ContactPreferencesTest.java
@@ -22,9 +22,7 @@
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
-import android.app.Instrumentation;
import android.content.ComponentName;
-import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentFilter;
diff --git a/tests/robolectric/src/com/android/emergency/preferences/EmergencyContactsPreferenceTest.java b/tests/robolectric/src/com/android/emergency/preferences/EmergencyContactsPreferenceTest.java
new file mode 100644
index 0000000..b13e4c3
--- /dev/null
+++ b/tests/robolectric/src/com/android/emergency/preferences/EmergencyContactsPreferenceTest.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.emergency.preferences;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.ContextWrapper;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.preference.PreferenceGroup;
+import android.preference.PreferenceManager;
+import android.preference.PreferenceScreen;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.emergency.ContactTestUtils;
+import com.android.emergency.EmergencyContactManager;
+import com.android.emergency.PreferenceKeys;
+import com.android.emergency.TestConfig;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+/** Unit tests for {@link EmergencyContactsPreference}. */
+@SmallTest
+@RunWith(RobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class EmergencyContactsPreferenceTest {
+ @Mock private PackageManager mPackageManager;
+ @Mock private PreferenceManager mPreferenceManager;
+ @Mock private SharedPreferences mSharedPreferences;
+ @Mock private EmergencyContactsPreference.ContactValidator mContactValidator;
+ @Mock private ContactPreference.ContactFactory mContactFactory;
+ private ContextWrapper mContext;
+ private EmergencyContactsPreference mPreference;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ when(mPreferenceManager.getSharedPreferences()).thenReturn(mSharedPreferences);
+
+ mContext = spy(RuntimeEnvironment.application);
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+
+ mPreference = spy(new EmergencyContactsPreference(RuntimeEnvironment.application,
+ null /* attrs */, mContactValidator, mContactFactory));
+
+ PreferenceGroup prefRoot = spy(new PreferenceScreen(mContext, null /* attrs */));
+ when(prefRoot.getPreferenceManager()).thenReturn(mPreferenceManager);
+ prefRoot.addPreference(mPreference);
+ }
+
+ @Test
+ public void testDefaultProperties() {
+ assertThat(mPreference.isPersistent()).isTrue();
+ assertThat(mPreference.isNotSet()).isTrue();
+ assertThat(mPreference.getEmergencyContacts()).isEmpty();
+ assertThat(mPreference.getPreferenceCount()).isEqualTo(0);
+ }
+
+ @Test
+ public void testAddAndRemoveEmergencyContact() throws Throwable {
+ final String name = "Jane";
+ final String phoneNumber = "456";
+
+ when(mContactValidator.isValidEmergencyContact(any(), any())).thenReturn(true);
+
+ EmergencyContactManager.Contact contact = mock(EmergencyContactManager.Contact.class);
+ when(mContactFactory.getContact(any(), any())).thenReturn(contact);
+ when(contact.getName()).thenReturn(name);
+ when(contact.getPhoneNumber()).thenReturn(phoneNumber);
+
+ Uri uri = mock(Uri.class);
+ when(contact.getPhoneUri()).thenReturn(uri);
+
+ mPreference.addNewEmergencyContact(uri);
+
+ assertThat(mPreference.getEmergencyContacts()).hasSize(1);
+ assertThat(mPreference.getPreferenceCount()).isEqualTo(1);
+ ContactPreference contactPreference = (ContactPreference) mPreference.getPreference(0);
+
+ assertThat(contactPreference.getPhoneUri()).isEqualTo(uri);
+ assertThat(contactPreference.getTitle()).isEqualTo(name);
+ assertThat((String) contactPreference.getSummary()).contains(phoneNumber);
+
+ mPreference.onRemoveContactPreference((ContactPreference) mPreference.getPreference(0));
+
+ assertThat(mPreference.getEmergencyContacts()).isEmpty();
+ assertThat(mPreference.getPreferenceCount()).isEqualTo(0);
+ }
+
+ @Test
+ public void testReloadFromPreference() throws Throwable {
+ final String nameJane = "Jane";
+ final String phoneNumberJane = "456";
+ Uri contactUriJane = Uri.parse("tel:" + phoneNumberJane);
+ EmergencyContactManager.Contact contactJane = mock(EmergencyContactManager.Contact.class);
+ when(mContactFactory.getContact(any(), eq(contactUriJane))).thenReturn(contactJane);
+ when(contactJane.getName()).thenReturn(nameJane);
+ when(contactJane.getPhoneNumber()).thenReturn(phoneNumberJane);
+ when(contactJane.getPhoneUri()).thenReturn(contactUriJane);
+
+ final String nameJohn = "John";
+ final String phoneNumberJohn = "123";
+ Uri contactUriJohn = Uri.parse("tel:" + phoneNumberJohn);
+ EmergencyContactManager.Contact contactJohn = mock(EmergencyContactManager.Contact.class);
+ when(mContactFactory.getContact(any(), eq(contactUriJohn))).thenReturn(contactJohn);
+ when(contactJohn.getName()).thenReturn(nameJohn);
+ when(contactJohn.getPhoneNumber()).thenReturn(phoneNumberJohn);
+ when(contactJohn.getPhoneUri()).thenReturn(contactUriJohn);
+
+ final List<Uri> emergencyContacts = new ArrayList<>();
+ emergencyContacts.add(contactUriJane);
+ emergencyContacts.add(contactUriJohn);
+ mPreference.setEmergencyContacts(emergencyContacts);
+
+ assertThat(mPreference.getEmergencyContacts().size()).isEqualTo(2);
+ assertThat(mPreference.getPreferenceCount()).isEqualTo(2);
+
+ // "Delete" Jane by reloading from preferences. The mock SharedPreferences still have both
+ // contacts stored, but the validator only believes John is valid.
+ mPreference.setKey(PreferenceKeys.KEY_EMERGENCY_CONTACTS);
+ when(mSharedPreferences.getString(eq(mPreference.getKey()), any()))
+ .thenReturn(mPreference.serialize(emergencyContacts));
+ when(mContactValidator.isValidEmergencyContact(any(), eq(contactUriJane)))
+ .thenReturn(false);
+ when(mContactValidator.isValidEmergencyContact(any(), eq(contactUriJohn))).thenReturn(true);
+ // Override the preference's persist behavior, to avoid EmergencyContactsPreference
+ // attempting to write to SharedPreferences. (Preference's default behavior is unmockable.)
+ doNothing().when(mPreference).persistEmergencyContacts(any());
+ mPreference.reloadFromPreference();
+
+ // Assert the only remaining contact is John
+ assertThat(mPreference.getEmergencyContacts()).hasSize(1);
+ assertThat(mPreference.getPreferenceCount()).isEqualTo(1);
+ ContactPreference contactPreference = (ContactPreference) mPreference.getPreference(0);
+ assertThat(contactPreference.getPhoneUri()).isEqualTo(contactUriJohn);
+ }
+}