Add a plus button to the mobile pref on Network & internet page
On the Network & internet page, we have a "Mobile network" pref that in
single-SIM mode leads to a detail page for the current SIM. In multi-SIM
mode it has more complicated behavior (leading either to details about
the current subscription if there is only one, or a list of
subscriptions if more than one).
One of the things we wanted to add was a shortcut to add another eSIM
subscription. So this CL adds a plus button control on the right of the
preference which leads to a flow to add another mobile subscription via
the eSIM manager.
Bug: 116349402
Test: make RunSettingsRoboTests
Change-Id: I38e0031e3bd603e93c45dcb4557750e7bc1b8b5a
diff --git a/res/layout/preference_widget_add.xml b/res/layout/preference_widget_add.xml
new file mode 100644
index 0000000..6e33a4d
--- /dev/null
+++ b/res/layout/preference_widget_add.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+ -->
+
+<ImageView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/add_preference_widget"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:paddingStart="?android:attr/listPreferredItemPaddingEnd"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:background="?android:attr/selectableItemBackground"
+ android:scaleType="center"
+ android:src="@drawable/ic_add_24dp"
+ android:contentDescription="@string/add" />
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 36fba35..29cdffa 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -658,6 +658,8 @@
<string name="apply">Apply</string>
<!-- Button label for generic share action [CHAR LIMIT=20] -->
<string name="share">Share</string>
+ <!-- Button label for generic add action [CHAR LIMIT=20] -->
+ <string name="add">Add</string>
<!-- Title of the Settings activity shown within the application itself. -->
<string name="settings_label">Settings</string>
diff --git a/res/xml/mobile_network_list.xml b/res/xml/mobile_network_list.xml
index 81704e5..5bffa2f 100644
--- a/res/xml/mobile_network_list.xml
+++ b/res/xml/mobile_network_list.xml
@@ -23,6 +23,8 @@
android:key="add_more"
android:title="@string/mobile_network_list_add_more"
android:icon="@drawable/ic_menu_add"
- android:order="100" />
+ android:order="100" >
+ <intent android:action="android.telephony.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION" />
+ </Preference>
</PreferenceScreen>
diff --git a/res/xml/network_and_internet_v2.xml b/res/xml/network_and_internet_v2.xml
index 83499d7..fd29c41 100644
--- a/res/xml/network_and_internet_v2.xml
+++ b/res/xml/network_and_internet_v2.xml
@@ -39,7 +39,7 @@
android:targetClass="Settings$WifiSettingsActivity" />
</com.android.settings.widget.MasterSwitchPreference>
- <com.android.settingslib.RestrictedPreference
+ <com.android.settings.widget.AddPreference
android:key="mobile_network_list"
android:title="@string/network_settings_title"
android:summary="@string/summary_placeholder"
diff --git a/src/com/android/settings/network/MobileNetworkSummaryController.java b/src/com/android/settings/network/MobileNetworkSummaryController.java
index cc15676..fff1fea 100644
--- a/src/com/android/settings/network/MobileNetworkSummaryController.java
+++ b/src/com/android/settings/network/MobileNetworkSummaryController.java
@@ -16,6 +16,8 @@
package com.android.settings.network;
+import static android.telephony.TelephonyManager.MultiSimVariants.UNKNOWN;
+
import static androidx.lifecycle.Lifecycle.Event.ON_PAUSE;
import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
@@ -23,6 +25,15 @@
import android.content.Intent;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.telephony.euicc.EuiccManager;
+
+import com.android.settings.R;
+import com.android.settings.network.telephony.MobileNetworkActivity;
+import com.android.settings.widget.AddPreference;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import java.util.List;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
@@ -30,12 +41,6 @@
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
-import com.android.settings.R;
-import com.android.settings.network.telephony.MobileNetworkActivity;
-import com.android.settingslib.core.AbstractPreferenceController;
-
-import java.util.List;
-
public class MobileNetworkSummaryController extends AbstractPreferenceController implements
SubscriptionsChangeListener.SubscriptionsChangeListenerClient, LifecycleObserver {
private static final String TAG = "MobileNetSummaryCtlr";
@@ -44,7 +49,8 @@
private SubscriptionManager mSubscriptionManager;
private SubscriptionsChangeListener mChangeListener;
- private PreferenceScreen mScreen;
+ private TelephonyManager mTelephonyMgr;
+ private AddPreference mPreference;
/**
* This controls the summary text and click behavior of the "Mobile network" item on the
@@ -64,6 +70,7 @@
public MobileNetworkSummaryController(Context context, Lifecycle lifecycle) {
super(context);
mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
+ mTelephonyMgr = mContext.getSystemService(TelephonyManager.class);
mChangeListener = new SubscriptionsChangeListener(context, this);
lifecycle.addObserver(this);
}
@@ -82,7 +89,7 @@
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
- mScreen = screen;
+ mPreference = screen.findPreference(getPreferenceKey());
}
@Override
@@ -100,29 +107,51 @@
}
}
- private void update() {
- if (mScreen != null) {
- final Preference preference = mScreen.findPreference(getPreferenceKey());
- refreshSummary(preference);
- final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(
- mSubscriptionManager);
+ private void startAddSimFlow() {
+ final Intent intent = new Intent(EuiccManager.ACTION_PROVISION_EMBEDDED_SUBSCRIPTION);
+ mContext.startActivity(intent);
+ }
- preference.setOnPreferenceClickListener(null);
- preference.setFragment(null);
- if (subs.size() == 0) {
- preference.setOnPreferenceClickListener((Preference pref) -> {
- // TODO(asargent) - need to get correct intent to fire here
- return true;
- });
- } else if (subs.size() == 1) {
- preference.setOnPreferenceClickListener((Preference pref) -> {
- final Intent intent = new Intent(mContext, MobileNetworkActivity.class);
- mContext.startActivity(intent);
- return true;
- });
+ private boolean shouldEnableAddButton() {
+ // The add button should only show up if the device is in multi-sim mode.
+ return mTelephonyMgr.getMultiSimConfiguration() != UNKNOWN;
+ }
+
+ private void update() {
+ if (mPreference == null) {
+ return;
+ }
+ final boolean enableAddButton = shouldEnableAddButton();
+ refreshSummary(mPreference);
+ if (!enableAddButton) {
+ mPreference.setOnAddClickListener(null);
+ } else {
+ mPreference.setOnAddClickListener(p -> {
+ startAddSimFlow();
+ });
+ }
+ final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(
+ mSubscriptionManager);
+ mPreference.setOnPreferenceClickListener(null);
+ mPreference.setFragment(null);
+ mPreference.setEnabled(true);
+ if (subs.isEmpty()) {
+ if (enableAddButton) {
+ mPreference.setEnabled(false);
} else {
- preference.setFragment(MobileNetworkListFragment.class.getCanonicalName());
+ mPreference.setOnPreferenceClickListener((Preference pref) -> {
+ startAddSimFlow();
+ return true;
+ });
}
+ } else if (subs.size() == 1) {
+ mPreference.setOnPreferenceClickListener((Preference pref) -> {
+ final Intent intent = new Intent(mContext, MobileNetworkActivity.class);
+ mContext.startActivity(intent);
+ return true;
+ });
+ } else {
+ mPreference.setFragment(MobileNetworkListFragment.class.getCanonicalName());
}
}
@@ -142,6 +171,7 @@
@Override
public void onSubscriptionsChanged() {
+ refreshSummary(mPreference);
update();
}
}
diff --git a/src/com/android/settings/widget/AddPreference.java b/src/com/android/settings/widget/AddPreference.java
new file mode 100644
index 0000000..ce36ab3
--- /dev/null
+++ b/src/com/android/settings/widget/AddPreference.java
@@ -0,0 +1,85 @@
+/*
+ * 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.settings.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+
+import com.android.settings.R;
+import com.android.settingslib.RestrictedPreference;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.PreferenceViewHolder;
+
+/**
+ * A preference with a plus button on the side representing an "add" action. The plus button will
+ * only be visible when a non-null click listener is registered.
+ */
+public class AddPreference extends RestrictedPreference implements View.OnClickListener {
+
+ private OnAddClickListener mListener;
+ private View mWidgetFrame;
+
+ public AddPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @VisibleForTesting
+ int getAddWidgetResId() {
+ return R.id.add_preference_widget;
+ }
+
+ /** Sets a listener for clicks on the plus button. Passing null will cause the button to be
+ * hidden. */
+ public void setOnAddClickListener(OnAddClickListener listener) {
+ mListener = listener;
+ if (mWidgetFrame != null) {
+ mWidgetFrame.setVisibility(shouldHideSecondTarget() ? View.GONE : View.VISIBLE);
+ }
+ }
+
+ @Override
+ protected int getSecondTargetResId() {
+ return R.layout.preference_widget_add;
+ }
+
+ @Override
+ protected boolean shouldHideSecondTarget() {
+ return mListener == null;
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+ mWidgetFrame = holder.findViewById(android.R.id.widget_frame);
+ final View addWidget = holder.findViewById(getAddWidgetResId());
+ addWidget.setEnabled(true);
+ addWidget.setOnClickListener(this);
+ }
+
+ @Override
+ public void onClick(View view) {
+ if (view.getId() == getAddWidgetResId() && mListener != null) {
+ mListener.onAddClick(this);
+ }
+ }
+
+ public interface OnAddClickListener {
+ void onAddClick(AddPreference p);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/network/MobileNetworkSummaryControllerTest.java b/tests/robotests/src/com/android/settings/network/MobileNetworkSummaryControllerTest.java
index f0c012d..6a1abd1 100644
--- a/tests/robotests/src/com/android/settings/network/MobileNetworkSummaryControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/MobileNetworkSummaryControllerTest.java
@@ -16,10 +16,16 @@
package com.android.settings.network;
+import static android.telephony.TelephonyManager.MultiSimVariants.DSDS;
+import static android.telephony.TelephonyManager.MultiSimVariants.UNKNOWN;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.ArgumentMatchers.notNull;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -28,8 +34,11 @@
import android.content.Context;
import android.content.Intent;
import android.telephony.SubscriptionInfo;
+import android.telephony.TelephonyManager;
+import android.telephony.euicc.EuiccManager;
import com.android.settings.network.telephony.MobileNetworkActivity;
+import com.android.settings.widget.AddPreference;
import org.junit.After;
import org.junit.Before;
@@ -44,7 +53,6 @@
import java.util.Arrays;
import androidx.lifecycle.Lifecycle;
-import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
@RunWith(RobolectricTestRunner.class)
@@ -52,10 +60,12 @@
@Mock
private Lifecycle mLifecycle;
@Mock
- PreferenceScreen mPreferenceScreen;
+ private TelephonyManager mTelephonyManager;
- Preference mPreference;
+ @Mock
+ private PreferenceScreen mPreferenceScreen;
+ private AddPreference mPreference;
private Context mContext;
private MobileNetworkSummaryController mController;
@@ -63,8 +73,11 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(Robolectric.setupActivity(Activity.class));
+ when(mContext.getSystemService(eq(TelephonyManager.class))).thenReturn(mTelephonyManager);
+ when(mTelephonyManager.getMultiSimConfiguration()).thenReturn(UNKNOWN);
+
mController = new MobileNetworkSummaryController(mContext, mLifecycle);
- mPreference = new Preference(mContext);
+ mPreference = spy(new AddPreference(mContext, null));
mPreference.setKey(mController.getPreferenceKey());
when(mPreferenceScreen.findPreference(eq(mController.getPreferenceKey()))).thenReturn(
mPreference);
@@ -76,15 +89,21 @@
}
@Test
- public void getSummary_noSubscriptions_correctSummary() {
+ public void getSummary_noSubscriptions_correctSummaryAndClickHandler() {
mController.displayPreference(mPreferenceScreen);
mController.onResume();
assertThat(mController.getSummary()).isEqualTo("Add a network");
+
+ mPreference.getOnPreferenceClickListener().onPreferenceClick(mPreference);
+ final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mContext).startActivity(intentCaptor.capture());
+ assertThat(intentCaptor.getValue().getAction()).isEqualTo(
+ EuiccManager.ACTION_PROVISION_EMBEDDED_SUBSCRIPTION);
}
@Test
public void getSummary_oneSubscription_correctSummaryAndClickHandler() {
- SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
+ final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
when(sub1.getSubscriptionId()).thenReturn(1);
when(sub1.getDisplayName()).thenReturn("sub1");
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1));
@@ -93,7 +112,7 @@
assertThat(mController.getSummary()).isEqualTo("sub1");
assertThat(mPreference.getFragment()).isNull();
mPreference.getOnPreferenceClickListener().onPreferenceClick(mPreference);
- ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mContext).startActivity(intentCaptor.capture());
assertThat(intentCaptor.getValue().getComponent().getClassName()).isEqualTo(
MobileNetworkActivity.class.getName());
@@ -101,8 +120,8 @@
@Test
public void getSummary_twoSubscriptions_correctSummaryAndFragment() {
- SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
- SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
+ final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
+ final SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
when(sub1.getSubscriptionId()).thenReturn(1);
when(sub2.getSubscriptionId()).thenReturn(2);
@@ -115,8 +134,8 @@
@Test
public void getSummaryAfterUpdate_twoSubscriptionsBecomesOne_correctSummaryAndFragment() {
- SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
- SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
+ final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
+ final SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
when(sub1.getSubscriptionId()).thenReturn(1);
when(sub2.getSubscriptionId()).thenReturn(2);
when(sub1.getDisplayName()).thenReturn("sub1");
@@ -135,7 +154,7 @@
assertThat(mController.getSummary()).isEqualTo("sub1");
assertThat(mPreference.getFragment()).isNull();
mPreference.getOnPreferenceClickListener().onPreferenceClick(mPreference);
- ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mContext).startActivity(intentCaptor.capture());
assertThat(intentCaptor.getValue().getComponent().getClassName()).isEqualTo(
MobileNetworkActivity.class.getName());
@@ -143,8 +162,8 @@
@Test
public void getSummaryAfterUpdate_oneSubscriptionBecomesTwo_correctSummaryAndFragment() {
- SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
- SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
+ final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
+ final SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
when(sub1.getSubscriptionId()).thenReturn(1);
when(sub2.getSubscriptionId()).thenReturn(2);
when(sub1.getDisplayName()).thenReturn("sub1");
@@ -156,7 +175,7 @@
assertThat(mController.getSummary()).isEqualTo("sub1");
assertThat(mPreference.getFragment()).isNull();
mPreference.getOnPreferenceClickListener().onPreferenceClick(mPreference);
- ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mContext).startActivity(intentCaptor.capture());
assertThat(intentCaptor.getValue().getComponent().getClassName()).isEqualTo(
MobileNetworkActivity.class.getName());
@@ -168,4 +187,53 @@
assertThat(mController.getSummary()).isEqualTo("2 SIMs");
assertThat(mPreference.getFragment()).isEqualTo(MobileNetworkListFragment.class.getName());
}
+
+ @Test
+ public void addButton_noSubscriptionsSingleSimMode_noAddClickListener() {
+ mController.displayPreference(mPreferenceScreen);
+ mController.onResume();
+ verify(mPreference, never()).setOnAddClickListener(notNull());
+ }
+
+ @Test
+ public void addButton_oneSubscriptionSingleSimMode_noAddClickListener() {
+ final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
+ SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1));
+ mController.displayPreference(mPreferenceScreen);
+ mController.onResume();
+ verify(mPreference, never()).setOnAddClickListener(notNull());
+ }
+
+ @Test
+ public void addButton_noSubscriptionsMultiSimMode_hasAddClickListenerAndPrefDisabled() {
+ when(mTelephonyManager.getMultiSimConfiguration()).thenReturn(DSDS);
+ mController.displayPreference(mPreferenceScreen);
+ mController.onResume();
+ assertThat(mPreference.isEnabled()).isFalse();
+ verify(mPreference, never()).setOnAddClickListener(isNull());
+ verify(mPreference).setOnAddClickListener(notNull());
+ }
+
+ @Test
+ public void addButton_oneSubscriptionMultiSimMode_hasAddClickListener() {
+ when(mTelephonyManager.getMultiSimConfiguration()).thenReturn(DSDS);
+ final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
+ SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1));
+ mController.displayPreference(mPreferenceScreen);
+ mController.onResume();
+ verify(mPreference, never()).setOnAddClickListener(isNull());
+ verify(mPreference).setOnAddClickListener(notNull());
+ }
+
+ @Test
+ public void addButton_twoSubscriptionsMultiSimMode_hasAddClickListener() {
+ when(mTelephonyManager.getMultiSimConfiguration()).thenReturn(DSDS);
+ final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
+ final SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
+ SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
+ mController.displayPreference(mPreferenceScreen);
+ mController.onResume();
+ verify(mPreference, never()).setOnAddClickListener(isNull());
+ verify(mPreference).setOnAddClickListener(notNull());
+ }
}
diff --git a/tests/robotests/src/com/android/settings/widget/AddPreferenceTest.java b/tests/robotests/src/com/android/settings/widget/AddPreferenceTest.java
new file mode 100644
index 0000000..3fccb34
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/widget/AddPreferenceTest.java
@@ -0,0 +1,149 @@
+/*
+ * 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.settings.widget;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.view.View;
+
+import com.android.settings.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import androidx.preference.PreferenceViewHolder;
+
+@RunWith(RobolectricTestRunner.class)
+public class AddPreferenceTest {
+
+ private Context mContext;
+ private PreferenceViewHolder mViewHolder;
+ private View mWidgetFrame;
+ private View mAddWidget;
+ private AddPreference mPreference;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mPreference = new AddPreference(mContext, null);
+
+ final View view = spy(View.inflate(mContext, mPreference.getLayoutResource(), null));
+ mViewHolder = PreferenceViewHolder.createInstanceForTests(view);
+ mWidgetFrame = view.findViewById(android.R.id.widget_frame);
+ mAddWidget = spy(View.inflate(mContext, mPreference.getSecondTargetResId(), null));
+ when(mViewHolder.findViewById(mPreference.getAddWidgetResId())).thenReturn(mAddWidget);
+ }
+
+ @Test
+ public void onBindViewHolder_noListener_addButtonNotVisible() {
+ mPreference.onBindViewHolder(mViewHolder);
+ assertThat(mPreference.shouldHideSecondTarget()).isTrue();
+ assertThat(mWidgetFrame.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void onBindViewHolder_hasListener_addButtonVisible() {
+ mPreference.setOnAddClickListener(p -> {});
+ mPreference.onBindViewHolder(mViewHolder);
+ assertThat(mPreference.shouldHideSecondTarget()).isFalse();
+ assertThat(mWidgetFrame.getVisibility()).isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void setOnAddClickListener_listenerAddedAfterBinding_addButtonBecomesVisible() {
+ mPreference.onBindViewHolder(mViewHolder);
+ assertThat(mPreference.shouldHideSecondTarget()).isTrue();
+ assertThat(mWidgetFrame.getVisibility()).isEqualTo(View.GONE);
+
+ mPreference.setOnAddClickListener(p -> {});
+ assertThat(mPreference.shouldHideSecondTarget()).isFalse();
+ assertThat(mWidgetFrame.getVisibility()).isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void setOnAddClickListener_listenerRemovedAfterBinding_addButtonNotVisible() {
+ mPreference.setOnAddClickListener(p -> {});
+
+ mPreference.onBindViewHolder(mViewHolder);
+ assertThat(mPreference.shouldHideSecondTarget()).isFalse();
+ assertThat(mWidgetFrame.getVisibility()).isEqualTo(View.VISIBLE);
+
+ mPreference.setOnAddClickListener(null);
+ assertThat(mPreference.shouldHideSecondTarget()).isTrue();
+ assertThat(mWidgetFrame.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void setOnAddClickListener_listenerAddedAndRemovedAfterBinding_addButtonNotVisible() {
+ mPreference.onBindViewHolder(mViewHolder);
+ assertThat(mPreference.shouldHideSecondTarget()).isTrue();
+ assertThat(mWidgetFrame.getVisibility()).isEqualTo(View.GONE);
+
+ mPreference.setOnAddClickListener(p -> {});
+ assertThat(mPreference.shouldHideSecondTarget()).isFalse();
+ assertThat(mWidgetFrame.getVisibility()).isEqualTo(View.VISIBLE);
+
+ mPreference.setOnAddClickListener(null);
+ assertThat(mPreference.shouldHideSecondTarget()).isTrue();
+ assertThat(mWidgetFrame.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void onClick_noListener_noCrash() {
+ mPreference.onBindViewHolder(mViewHolder);
+ // should be no crash here
+ mPreference.onClick(mAddWidget);
+ }
+
+ @Test
+ public void onClick_hasListenerBeforeBind_firesCorrectly() {
+ final AddPreference.OnAddClickListener listener = mock(
+ AddPreference.OnAddClickListener.class);
+ mPreference.setOnAddClickListener(listener);
+
+ mPreference.onBindViewHolder(mViewHolder);
+ assertThat(mWidgetFrame.getVisibility()).isEqualTo(View.VISIBLE);
+
+ mPreference.onClick(mAddWidget);
+ verify(listener).onAddClick(eq(mPreference));
+ }
+
+ @Test
+ public void onClick_listenerAddedAfterBind_firesCorrectly() {
+ mPreference.onBindViewHolder(mViewHolder);
+ assertThat(mWidgetFrame.getVisibility()).isEqualTo(View.GONE);
+
+ final AddPreference.OnAddClickListener listener = mock(
+ AddPreference.OnAddClickListener.class);
+ mPreference.setOnAddClickListener(listener);
+ assertThat(mWidgetFrame.getVisibility()).isEqualTo(View.VISIBLE);
+
+ mPreference.onClick(mAddWidget);
+ verify(listener).onAddClick(eq(mPreference));
+ }
+}