summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2021-06-19 03:08:58 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2021-06-19 03:08:58 +0000
commit92ee1c4e91c8c1a9880af75f903b438d196fc9b6 (patch)
treecd60438a00efd01eec6198b56291371ee58e9d68
parent68d88c86e84c0bfeca8c9b3a99795e05572b9454 (diff)
parentcece3e92e86869bc477ea704176e534e76a2f46c (diff)
downloadDialer-92ee1c4e91c8c1a9880af75f903b438d196fc9b6.tar.gz
Snap for 7473808 from cece3e92e86869bc477ea704176e534e76a2f46c to sc-release
Change-Id: Ib9eb7b05e9129e24b89c79e0a67e69240481364a
-rw-r--r--src/com/android/car/dialer/ui/contact/ContactDetailsFragment.java6
-rw-r--r--testing/src/com/android/car/dialer/testing/TestViewMatchers.java67
-rw-r--r--tests/robotests/src/com/android/car/dialer/ui/contact/ContactDetailsFragmentTest.java154
-rw-r--r--tests/unittests/src/com/android/car/dialer/ui/activecall/OnGoingCallControllerBarFragmentTest.java19
-rw-r--r--tests/unittests/src/com/android/car/dialer/ui/contact/ContactDetailsFragmentTest.java197
5 files changed, 269 insertions, 174 deletions
diff --git a/src/com/android/car/dialer/ui/contact/ContactDetailsFragment.java b/src/com/android/car/dialer/ui/contact/ContactDetailsFragment.java
index bd306792..86dae334 100644
--- a/src/com/android/car/dialer/ui/contact/ContactDetailsFragment.java
+++ b/src/com/android/car/dialer/ui/contact/ContactDetailsFragment.java
@@ -86,7 +86,7 @@ public class ContactDetailsFragment extends Hilt_ContactDetailsFragment implemen
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mContact = getArguments().getParcelable(KEY_CONTACT_ENTITY);
+ mContact = getArguments() == null ? null : getArguments().getParcelable(KEY_CONTACT_ENTITY);
if (mContact == null && savedInstanceState != null) {
mContact = savedInstanceState.getParcelable(KEY_CONTACT_ENTITY);
}
@@ -118,7 +118,9 @@ public class ContactDetailsFragment extends Hilt_ContactDetailsFragment implemen
}
private void onContactChanged(Contact contact) {
- getArguments().clear();
+ if (getArguments() != null) {
+ getArguments().clear();
+ }
ToolbarController toolbar = CarUi.getToolbar(getActivity());
// Null check to have unit tests to pass.
if (toolbar == null) {
diff --git a/testing/src/com/android/car/dialer/testing/TestViewMatchers.java b/testing/src/com/android/car/dialer/testing/TestViewMatchers.java
new file mode 100644
index 00000000..770b9c5f
--- /dev/null
+++ b/testing/src/com/android/car/dialer/testing/TestViewMatchers.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2021 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.car.dialer.testing;
+
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.test.espresso.matcher.BoundedMatcher;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+
+/** View matchers created for Android instrumented tests. */
+public final class TestViewMatchers {
+
+ /** Creates a matcher that checks the {@link View#isActivated()} state. */
+ public static Matcher<View> isActivated(boolean isActivated) {
+ return new TypeSafeMatcher<View>() {
+ @Override
+ protected boolean matchesSafely(View item) {
+ return item.isActivated() == isActivated;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("View is " + (isActivated ? "activated" : "not activated"));
+ }
+ };
+ }
+
+ /** Creates a matcher for the item view at the given position of a {@link RecyclerView}. */
+ public static Matcher<View> atPosition(int position, @NonNull Matcher<View> itemMatcher) {
+ return new BoundedMatcher<View, RecyclerView>(RecyclerView.class) {
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("has item at position " + position + ": ");
+ itemMatcher.describeTo(description);
+ }
+
+ @Override
+ protected boolean matchesSafely(final RecyclerView view) {
+ RecyclerView.ViewHolder viewHolder = view.findViewHolderForAdapterPosition(
+ position);
+ if (viewHolder == null) {
+ return false;
+ }
+ return itemMatcher.matches(viewHolder.itemView);
+ }
+ };
+ }
+}
diff --git a/tests/robotests/src/com/android/car/dialer/ui/contact/ContactDetailsFragmentTest.java b/tests/robotests/src/com/android/car/dialer/ui/contact/ContactDetailsFragmentTest.java
deleted file mode 100644
index 9a9bca4c..00000000
--- a/tests/robotests/src/com/android/car/dialer/ui/contact/ContactDetailsFragmentTest.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (C) 2019 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.car.dialer.ui.contact;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.view.View;
-import android.widget.TextView;
-
-import androidx.lifecycle.MutableLiveData;
-
-import com.android.car.arch.common.FutureData;
-import com.android.car.dialer.CarDialerRobolectricTestRunner;
-import com.android.car.dialer.FragmentTestActivity;
-import com.android.car.dialer.R;
-import com.android.car.dialer.telecom.UiCallManager;
-import com.android.car.dialer.testutils.ShadowAndroidViewModelFactory;
-import com.android.car.telephony.common.Contact;
-import com.android.car.telephony.common.InMemoryPhoneBook;
-import com.android.car.telephony.common.PhoneNumber;
-import com.android.car.ui.recyclerview.CarUiRecyclerView;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.Robolectric;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-import java.util.Arrays;
-
-@Config(shadows = {ShadowAndroidViewModelFactory.class}, qualifiers = "h610dp")
-@RunWith(CarDialerRobolectricTestRunner.class)
-public class ContactDetailsFragmentTest {
- private static final String DISPLAY_NAME = "NAME";
- private static final String[] RAW_NUMBERS = {"6505550000", "6502370000"};
-
- private ContactDetailsFragment mContactDetailsFragment;
- private FragmentTestActivity mFragmentTestActivity;
- private CarUiRecyclerView mListView;
- @Mock
- private ContactDetailsViewModel mMockContactDetailsViewModel;
- @Mock
- private Contact mMockContact;
- @Mock
- private PhoneNumber mMockPhoneNumber1;
- @Mock
- private PhoneNumber mMockPhoneNumber2;
- @Mock
- private UiCallManager mMockUiCallManager;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
-
- InMemoryPhoneBook.init(RuntimeEnvironment.application);
-
- when(mMockContact.getDisplayName()).thenReturn(DISPLAY_NAME);
- when(mMockPhoneNumber1.getRawNumber()).thenReturn(RAW_NUMBERS[0]);
- when(mMockPhoneNumber2.getRawNumber()).thenReturn(RAW_NUMBERS[1]);
- when(mMockContact.getNumbers()).thenReturn(
- Arrays.asList(mMockPhoneNumber1, mMockPhoneNumber2));
-
- MutableLiveData<FutureData<Contact>> contactDetails = new MutableLiveData<>();
- contactDetails.setValue(new FutureData<>(false, mMockContact));
- ShadowAndroidViewModelFactory.add(ContactDetailsViewModel.class,
- mMockContactDetailsViewModel);
- when(mMockContactDetailsViewModel.getContactDetails(mMockContact)).thenReturn(
- contactDetails);
- }
-
- @After
- public void tearDown() {
- InMemoryPhoneBook.tearDown();
- }
-
- @Test
- public void testCreateWithContact() {
- mContactDetailsFragment = ContactDetailsFragment.newInstance(mMockContact);
-
- setUpFragment();
-
- verifyHeader();
- verifyPhoneNumber(1);
- verifyPhoneNumber(2);
- }
-
- private void setUpFragment() {
- mFragmentTestActivity = Robolectric.buildActivity(
- FragmentTestActivity.class).create().resume().get();
-
- ContactDetailsViewHolder.Factory viewHolderFactory =
- (v, phoneNumberPresenter) -> new ContactDetailsViewHolder(v, phoneNumberPresenter,
- mMockUiCallManager);
- mContactDetailsFragment.mContactDetailsAdapterFactory =
- (contact, phoneNumberPresenter) -> new ContactDetailsAdapter(
- mFragmentTestActivity, viewHolderFactory, contact, phoneNumberPresenter);
- mFragmentTestActivity.setFragment(mContactDetailsFragment);
-
- mListView = mContactDetailsFragment.getView().findViewById(R.id.list_view);
- // Set up layout for recyclerView
- mListView.layout(0, 0, 100, 1000);
- }
-
- /**
- * Verify the title of the Contact
- */
- private void verifyHeader() {
- View firstChild = mListView.findViewHolderForLayoutPosition(0).itemView;
- assertThat(((TextView) firstChild.findViewById(R.id.title)).getText().toString()).isEqualTo(
- DISPLAY_NAME);
- assertThat(firstChild.hasOnClickListeners()).isFalse();
- }
-
- /**
- * Verify the phone numbers for the Contact
- */
- private void verifyPhoneNumber(int position) {
- View child = mListView.findViewHolderForLayoutPosition(position).itemView;
- View callButton = child.findViewById(R.id.call_action_id);
-
- assertThat(((TextView) child.findViewById(R.id.title)).getText().toString()).isEqualTo(
- RAW_NUMBERS[position - 1]);
- assertThat(callButton.hasOnClickListeners()).isTrue();
-
- int invocations = Mockito.mockingDetails(mMockUiCallManager).getInvocations().size();
-
- callButton.performClick();
-
- verify(mMockUiCallManager, times(invocations + 1)).placeCall(Mockito.any());
- }
-}
diff --git a/tests/unittests/src/com/android/car/dialer/ui/activecall/OnGoingCallControllerBarFragmentTest.java b/tests/unittests/src/com/android/car/dialer/ui/activecall/OnGoingCallControllerBarFragmentTest.java
index f40ef7db..65dbd2c9 100644
--- a/tests/unittests/src/com/android/car/dialer/ui/activecall/OnGoingCallControllerBarFragmentTest.java
+++ b/tests/unittests/src/com/android/car/dialer/ui/activecall/OnGoingCallControllerBarFragmentTest.java
@@ -27,6 +27,7 @@ import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibilit
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static com.android.car.dialer.testing.TestViewActions.selfClick;
+import static com.android.car.dialer.testing.TestViewMatchers.isActivated;
import static com.google.common.truth.Truth.assertThat;
@@ -37,7 +38,6 @@ import static org.mockito.Mockito.when;
import android.telecom.Call;
import android.telecom.CallAudioState;
-import android.view.View;
import androidx.core.util.Pair;
import androidx.lifecycle.LiveData;
@@ -52,9 +52,6 @@ import com.android.car.dialer.R;
import com.android.car.dialer.testing.TestActivity;
import com.android.car.telephony.common.CallDetail;
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
-import org.hamcrest.TypeSafeMatcher;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -235,18 +232,4 @@ public class OnGoingCallControllerBarFragmentTest {
new OnGoingCallControllerBarFragment()).commit();
});
}
-
- private static Matcher<View> isActivated(boolean isActivated) {
- return new TypeSafeMatcher<View>() {
- @Override
- protected boolean matchesSafely(View item) {
- return item.isActivated() == isActivated;
- }
-
- @Override
- public void describeTo(Description description) {
- description.appendText("View is " + (isActivated ? "activated" : "not activated"));
- }
- };
- }
}
diff --git a/tests/unittests/src/com/android/car/dialer/ui/contact/ContactDetailsFragmentTest.java b/tests/unittests/src/com/android/car/dialer/ui/contact/ContactDetailsFragmentTest.java
new file mode 100644
index 00000000..a2cdde72
--- /dev/null
+++ b/tests/unittests/src/com/android/car/dialer/ui/contact/ContactDetailsFragmentTest.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2021 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.car.dialer.ui.contact;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant;
+import static androidx.test.espresso.matcher.ViewMatchers.hasSibling;
+import static androidx.test.espresso.matcher.ViewMatchers.isClickable;
+import static androidx.test.espresso.matcher.ViewMatchers.isNotClickable;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
+import static com.android.car.dialer.testing.TestViewActions.selfClick;
+import static com.android.car.dialer.testing.TestViewMatchers.atPosition;
+import static com.android.car.dialer.testing.TestViewMatchers.isActivated;
+
+import static org.hamcrest.Matchers.allOf;
+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.content.Context;
+import android.os.Bundle;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.MutableLiveData;
+import androidx.lifecycle.ViewModel;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.test.core.app.ActivityScenario;
+import androidx.test.espresso.contrib.RecyclerViewActions;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.car.arch.common.FutureData;
+import com.android.car.dialer.R;
+import com.android.car.dialer.telecom.UiCallManager;
+import com.android.car.dialer.testing.TestActivity;
+import com.android.car.telephony.common.Contact;
+import com.android.car.telephony.common.PhoneNumber;
+
+import org.hamcrest.Matcher;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Arrays;
+
+@RunWith(AndroidJUnit4.class)
+public class ContactDetailsFragmentTest {
+ private static final String DISPLAY_NAME = "NAME";
+ private static final String[] RAW_NUMBERS = {"6505550000", "6502370000"};
+
+ @Mock
+ private Contact mMockContact;
+ @Mock
+ private PhoneNumber mMockPhoneNumber1;
+ @Mock
+ private PhoneNumber mMockPhoneNumber2;
+ @Mock
+ private UiCallManager mMockUiCallManager;
+
+ // This is initialized in the TestContactDetailsFragment#getDefaultViewModelProviderFactory();
+ private ContactDetailsViewModel mViewModel;
+
+ private final FragmentManager.FragmentLifecycleCallbacks mCallbacks =
+ new FragmentManager.FragmentLifecycleCallbacks() {
+ @Override
+ public void onFragmentAttached(@NonNull FragmentManager fm, @NonNull Fragment f,
+ @NonNull Context context) {
+ // Set up the mock ContactDetailsViewModel.
+ mViewModel = new ViewModelProvider(f).get(ContactDetailsViewModel.class);
+ LiveData<FutureData<Contact>> contactDetail = new MutableLiveData<>(
+ FutureData.newLoadedData(mMockContact));
+ when(mViewModel.getContactDetails(any())).thenReturn(contactDetail);
+ }
+
+ @Override
+ public void onFragmentCreated(@NonNull FragmentManager fm, @NonNull Fragment f,
+ @Nullable Bundle savedInstanceState) {
+ if (f instanceof ContactDetailsFragment) {
+ // Set up adapter with the mock UiCallManager.
+ ContactDetailsViewHolder.Factory viewHolderFactory =
+ (v, phoneNumberPresenter) -> new ContactDetailsViewHolder(v,
+ phoneNumberPresenter, mMockUiCallManager);
+ ((ContactDetailsFragment) f).mContactDetailsAdapterFactory =
+ (contact, phoneNumberPresenter) -> new ContactDetailsAdapter(
+ f.getContext(), viewHolderFactory, contact,
+ phoneNumberPresenter);
+ fm.unregisterFragmentLifecycleCallbacks(mCallbacks);
+ }
+ }
+ };
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ when(mMockContact.getDisplayName()).thenReturn(DISPLAY_NAME);
+ when(mMockPhoneNumber1.getRawNumber()).thenReturn(RAW_NUMBERS[0]);
+ when(mMockPhoneNumber2.getRawNumber()).thenReturn(RAW_NUMBERS[1]);
+ when(mMockContact.getNumbers()).thenReturn(
+ Arrays.asList(mMockPhoneNumber1, mMockPhoneNumber2));
+
+ }
+
+ @Test
+ public void testCreateWithContact() {
+ setUpFragment();
+
+ onView(withId(R.id.list_view))
+ .perform(RecyclerViewActions.scrollToPosition(0))
+ .check(matches(atPosition(0, hasDescendant(
+ allOf(withId(R.id.title), withText(DISPLAY_NAME))))))
+ .check(matches(atPosition(0, isNotClickable())));
+
+ verifyPhoneNumber(1);
+ verifyPhoneNumber(2);
+ }
+
+ private void setUpFragment() {
+ ActivityScenario<TestActivity> activityScenario = ActivityScenario.launch(
+ TestActivity.class);
+ activityScenario.onActivity(activity -> {
+ ContactDetailsFragment fragment = new TestContactDetailsFragment();
+
+ activity.getSupportFragmentManager().registerFragmentLifecycleCallbacks(
+ mCallbacks, /* recursive= */false);
+
+ activity.getSupportFragmentManager().beginTransaction().add(
+ R.id.test_fragment_container, fragment).commit();
+ });
+ }
+
+ /**
+ * Verify the phone numbers for the Contact
+ */
+ private void verifyPhoneNumber(int position) {
+ onView(withId(R.id.list_view))
+ .perform(RecyclerViewActions.scrollToPosition(position))
+ .check(matches(atPosition(position, hasDescendant(
+ allOf(withId(R.id.title), withText(RAW_NUMBERS[position - 1]))))))
+ .check(matches(atPosition(position, hasDescendant(
+ allOf(withId(R.id.call_action_id), isClickable())))));
+
+ Matcher<View> callActionViewMatcher = allOf(
+ withId(R.id.call_action_id),
+ hasDescendant(withText(RAW_NUMBERS[position - 1])));
+ onView(callActionViewMatcher).perform(selfClick());
+ verify(mMockUiCallManager).placeCall(RAW_NUMBERS[position - 1]);
+
+ onView(allOf(
+ withId(R.id.contact_details_favorite_button), hasSibling(callActionViewMatcher)))
+ .check(matches(isActivated(false)))
+ .perform(selfClick())
+ .check(matches(isActivated(true)));
+ verify(mViewModel).addToFavorite(eq(mMockContact),
+ eq(position == 1 ? mMockPhoneNumber1 : mMockPhoneNumber2));
+ }
+
+ /** A test override that creates mock {@link ViewModel}s. */
+ public static class TestContactDetailsFragment extends ContactDetailsFragment {
+
+ @Override
+ public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
+ return new ViewModelProvider.Factory() {
+ @NonNull
+ @Override
+ public <T extends ViewModel> T create(@NonNull Class<T> aClass) {
+ return mock(aClass);
+ }
+ };
+ }
+ }
+}