Add additional Preference instrumentation tests
Fixes: 161316242
Test: atest CarUILibUnitTests
Change-Id: Ia83d2ef060837b2b91502abdbdde3187b0c5447e
diff --git a/car-ui-lib/tests/unit/res/drawable/ic_settings_gear.xml b/car-ui-lib/tests/unit/res/drawable/ic_settings_gear.xml
new file mode 100644
index 0000000..2b7fa2f
--- /dev/null
+++ b/car-ui-lib/tests/unit/res/drawable/ic_settings_gear.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 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.
+-->
+
+<vector
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportHeight="48.0"
+ android:viewportWidth="48.0">
+ <path
+ android:fillColor="#fff"
+ android:pathData="M38.86,25.95c0.08,-0.64 0.14,-1.29 0.14,-1.95s-0.06,-1.31 -0.14,-1.95l4.23,-3.31c0.38,-0.3 0.49,-0.84 0.24,-1.28l-4,-6.93c-0.25,-0.43 -0.77,-0.61 -1.22,-0.43l-4.98,2.01c-1.03,-0.79 -2.16,-1.46 -3.38,-1.97L29,4.84c-0.09,-0.47 -0.5,-0.84 -1,-0.84h-8c-0.5,0 -0.91,0.37 -0.99,0.84l-0.75,5.3c-1.22,0.51 -2.35,1.17 -3.38,1.97L9.9,10.1c-0.45,-0.17 -0.97,0 -1.22,0.43l-4,6.93c-0.25,0.43 -0.14,0.97 0.24,1.28l4.22,3.31C9.06,22.69 9,23.34 9,24s0.06,1.31 0.14,1.95l-4.22,3.31c-0.38,0.3 -0.49,0.84 -0.24,1.28l4,6.93c0.25,0.43 0.77,0.61 1.22,0.43l4.98,-2.01c1.03,0.79 2.16,1.46 3.38,1.97l0.75,5.3c0.08,0.47 0.49,0.84 0.99,0.84h8c0.5,0 0.91,-0.37 0.99,-0.84l0.75,-5.3c1.22,-0.51 2.35,-1.17 3.38,-1.97l4.98,2.01c0.45,0.17 0.97,0 1.22,-0.43l4,-6.93c0.25,-0.43 0.14,-0.97 -0.24,-1.28l-4.22,-3.31zM24,31c-3.87,0 -7,-3.13 -7,-7s3.13,-7 7,-7 7,3.13 7,7 -3.13,7 -7,7z"/>
+</vector>
diff --git a/car-ui-lib/tests/unit/res/layout/details_preference_widget.xml b/car-ui-lib/tests/unit/res/layout/details_preference_widget.xml
new file mode 100644
index 0000000..3912de1
--- /dev/null
+++ b/car-ui-lib/tests/unit/res/layout/details_preference_widget.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 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:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:src="@drawable/ic_settings_gear"/>
diff --git a/car-ui-lib/tests/unit/res/values/strings.xml b/car-ui-lib/tests/unit/res/values/strings.xml
index 2deb0ed..21f4ee4 100644
--- a/car-ui-lib/tests/unit/res/values/strings.xml
+++ b/car-ui-lib/tests/unit/res/values/strings.xml
@@ -23,4 +23,12 @@
<string name="title_multi_list_preference">Multi-select list preference</string>
<string name="summary_multi_list_preference">Shows a dialog with multiple choice options</string>
<string name="dialog_title_multi_list_preference">Choose some options!</string>
+ <string name="preference_widgets_category">Widgets</string>
+ <string name="title_checkbox_preference">Checkbox preference</string>
+ <string name="summary_checkbox_preference">Tap anywhere in this preference to toggle state</string>
+ <string name="title_switch_preference">Switch preference</string>
+ <string name="summary_switch_preference">Tap anywhere in this preference to toggle state</string>
+ <string name="title_dropdown_preference">Dropdown preference</string>
+ <string name="title_twoaction_preference">TwoAction preference</string>
+ <string name="summary_twoaction_preference">A widget should be visible on the right</string>
</resources>
diff --git a/car-ui-lib/tests/unit/res/xml/test_preferences.xml b/car-ui-lib/tests/unit/res/xml/test_preferences.xml
index 2fd740b..042bbb0 100644
--- a/car-ui-lib/tests/unit/res/xml/test_preferences.xml
+++ b/car-ui-lib/tests/unit/res/xml/test_preferences.xml
@@ -20,7 +20,8 @@
app:title="@string/preferences_screen_title">
<PreferenceCategory
- android:title="@string/preference_dialog_category">
+ android:title="@string/preference_dialog_category"
+ android:order="1">
<ListPreference
android:dialogTitle="@string/dialog_title_list_preference"
diff --git a/car-ui-lib/tests/unit/src/com/android/car/ui/preference/PreferenceTest.java b/car-ui-lib/tests/unit/src/com/android/car/ui/preference/PreferenceTest.java
index 1c3b48a..73f0a09 100644
--- a/car-ui-lib/tests/unit/src/com/android/car/ui/preference/PreferenceTest.java
+++ b/car-ui-lib/tests/unit/src/com/android/car/ui/preference/PreferenceTest.java
@@ -20,12 +20,14 @@
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.isChecked;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.isNotChecked;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static com.android.car.ui.matchers.ViewMatchers.withIndex;
+import static org.hamcrest.Matchers.not;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
@@ -35,7 +37,10 @@
import android.content.res.Resources;
+import androidx.preference.CheckBoxPreference;
+import androidx.preference.DropDownPreference;
import androidx.preference.Preference;
+import androidx.preference.SwitchPreference;
import androidx.test.rule.ActivityTestRule;
import com.android.car.ui.tests.unit.R;
@@ -68,6 +73,9 @@
@Test
public void testListPreference() {
+ // Scroll until list preference is visible
+ mActivity.runOnUiThread(() -> mActivity.scrollToPreference("list"));
+
// Display full screen list preference.
onView(withText(R.string.title_list_preference)).perform(click());
@@ -77,7 +85,6 @@
mActivity.setOnPreferenceChangeListener("list", mockListener);
// Check that no option is initially selected.
- onView(withIndex(withId(R.id.radio_button_widget), 0)).check(matches(isNotChecked()));
onView(withIndex(withId(R.id.radio_button_widget), 1)).check(matches(isNotChecked()));
onView(withIndex(withId(R.id.radio_button_widget), 2)).check(matches(isNotChecked()));
@@ -122,6 +129,9 @@
@Test
public void testMultiSelectListPreference() {
+ // Scroll until multi-select preference is visible
+ mActivity.runOnUiThread(() -> mActivity.scrollToPreference("multi_select_list"));
+
// Display full screen list preference.
onView(withText(R.string.title_multi_list_preference)).perform(click());
@@ -160,4 +170,157 @@
onView(withIndex(withId(R.id.checkbox_widget), 1)).check(matches(isNotChecked()));
onView(withIndex(withId(R.id.checkbox_widget), 2)).check(matches(isChecked()));
}
+
+ @Test
+ public void testCheckboxPreference() {
+ // Create checkbox preference and add it to screen.
+ CheckBoxPreference preference = new CheckBoxPreference(mActivity);
+ preference.setOrder(0);
+ preference.setKey("checkbox");
+ preference.setTitle(R.string.title_checkbox_preference);
+ preference.setSummary(R.string.summary_checkbox_preference);
+ mActivity.addPreference(preference);
+
+ // Check title and summary are displayed as expected.
+ onView(withIndex(withId(android.R.id.title), 0)).check(matches(
+ withText(mActivity.getString(R.string.title_checkbox_preference))));
+ onView(withIndex(withId(android.R.id.summary), 0)).check(matches(
+ withText(mActivity.getString(R.string.summary_checkbox_preference))));
+
+ // Ensure checkbox preference is initially not selected.
+ onView(withId(android.R.id.checkbox)).check(matches(isNotChecked()));
+
+ Preference.OnPreferenceChangeListener mockListener = mock(
+ Preference.OnPreferenceChangeListener.class);
+ when(mockListener.onPreferenceChange(any(), any())).thenReturn(true);
+ mActivity.setOnPreferenceChangeListener("checkbox", mockListener);
+
+ // Select checkbox preference.
+ onView(withText(R.string.title_checkbox_preference)).perform(click());
+
+ // Verify preference value was updated.
+ verify(mockListener, times(1)).onPreferenceChange(any(), eq(true));
+
+ // Verify checkbox preference correctly indicates preference is selected.
+ onView(withId(android.R.id.checkbox)).check(matches(isChecked()));
+
+ // Un-select checkbox preference.
+ onView(withText(R.string.title_checkbox_preference)).perform(click());
+
+ // Verify preference value was updated.
+ verify(mockListener, times(1)).onPreferenceChange(any(), eq(false));
+
+ // Verify checkbox preference correctly indicates preference is selected.
+ onView(withId(android.R.id.checkbox)).check(matches(isNotChecked()));
+ }
+
+ @Test
+ public void testSwitchPreference() {
+ // Create switch preference and add it to screen.
+ SwitchPreference preference = new SwitchPreference(mActivity);
+ preference.setOrder(0);
+ preference.setKey("switch");
+ preference.setTitle(R.string.title_switch_preference);
+ preference.setSummary(R.string.summary_switch_preference);
+ mActivity.addPreference(preference);
+
+ // Check title and summary are displayed as expected.
+ onView(withIndex(withId(android.R.id.title), 0)).check(matches(
+ withText(mActivity.getString(R.string.title_switch_preference))));
+ onView(withIndex(withId(android.R.id.summary), 0)).check(matches(
+ withText(mActivity.getString(R.string.summary_switch_preference))));
+
+ // Ensure switch preference is initially not selected.
+ onView(withId(android.R.id.switch_widget)).check(matches(isNotChecked()));
+
+ Preference.OnPreferenceChangeListener mockListener = mock(
+ Preference.OnPreferenceChangeListener.class);
+ when(mockListener.onPreferenceChange(any(), any())).thenReturn(true);
+ mActivity.setOnPreferenceChangeListener("switch", mockListener);
+
+ // Select switch preference.
+ onView(withText(R.string.title_switch_preference)).perform(click());
+
+ // Verify preference value was updated.
+ verify(mockListener, times(1)).onPreferenceChange(any(), eq(true));
+
+ // Verify switch preference correctly indicates preference is selected.
+ onView(withId(android.R.id.switch_widget)).check(matches(isChecked()));
+
+ // Un-select switch preference.
+ onView(withText(R.string.title_switch_preference)).perform(click());
+
+ // Verify preference value was updated.
+ verify(mockListener, times(1)).onPreferenceChange(any(), eq(false));
+
+ // Verify switch preference correctly indicates preference is selected.
+ onView(withId(android.R.id.switch_widget)).check(matches(isNotChecked()));
+ }
+
+ @Test
+ public void testDropDownPreference() {
+ // Create drop-down preference and add it to screen.
+ DropDownPreference preference = new CarUiDropDownPreference(mActivity);
+ preference.setKey("dropdown");
+ preference.setTitle(R.string.title_dropdown_preference);
+ preference.setEntries(mEntries);
+ preference.setEntryValues(mEntriesValues);
+ preference.setOrder(0);
+ mActivity.addPreference(preference);
+
+ // Display full screen list preference.
+ onView(withText(R.string.title_dropdown_preference)).perform(click());
+
+ Preference.OnPreferenceChangeListener mockListener = mock(
+ Preference.OnPreferenceChangeListener.class);
+ when(mockListener.onPreferenceChange(any(), any())).thenReturn(true);
+ mActivity.setOnPreferenceChangeListener("dropdown", mockListener);
+
+ // Check that first option is initially selected.
+ onView(withIndex(withId(R.id.radio_button_widget), 0)).check(matches(isChecked()));
+ onView(withIndex(withId(R.id.radio_button_widget), 1)).check(matches(isNotChecked()));
+ onView(withIndex(withId(R.id.radio_button_widget), 2)).check(matches(isNotChecked()));
+
+ // Select third option.
+ onView(withText(mEntries[2])).perform(click());
+ // Check that first option is selected.
+ onView(withIndex(withId(R.id.radio_button_widget), 0)).check(matches(isNotChecked()));
+ onView(withIndex(withId(R.id.radio_button_widget), 1)).check(matches(isNotChecked()));
+ onView(withIndex(withId(R.id.radio_button_widget), 2)).check(matches(isChecked()));
+
+ // Press back to save selection.
+ onView(withId(R.id.car_ui_toolbar_nav_icon)).perform(click());
+ // Verify preference value was updated.
+ verify(mockListener, times(1)).onPreferenceChange(any(), eq(mEntriesValues[2]));
+
+ onView(withText(R.string.title_dropdown_preference)).perform(click());
+
+ // Check that first option is selected.
+ onView(withIndex(withId(R.id.radio_button_widget), 0)).check(matches(isNotChecked()));
+ onView(withIndex(withId(R.id.radio_button_widget), 1)).check(matches(isNotChecked()));
+ onView(withIndex(withId(R.id.radio_button_widget), 2)).check(matches(isChecked()));
+ }
+
+ @Test
+ public void testTwoActionPreference() {
+ // Create drop-down preference and add it to screen.
+ CarUiTwoActionPreference preference = new CarUiTwoActionPreference(mActivity);
+ preference.setKey("twoaction");
+ preference.setTitle(R.string.title_twoaction_preference);
+ preference.setSummary(R.string.summary_twoaction_preference);
+ preference.setOrder(0);
+ preference.setWidgetLayoutResource(R.layout.details_preference_widget);
+ mActivity.addPreference(preference);
+
+ // Check that widget is displayed
+ onView(withIndex(withId(com.android.car.ui.R.id.action_widget_container), 0)).check(
+ matches(isDisplayed()));
+
+ // Hide second action.
+ mActivity.runOnUiThread(() -> preference.showAction(false));
+
+ // Ensure second action isn't displayed.
+ onView(withIndex(withId(com.android.car.ui.R.id.action_widget_container), 0)).check(
+ matches(not(isDisplayed())));
+ }
}
diff --git a/car-ui-lib/tests/unit/src/com/android/car/ui/preference/PreferenceTestActivity.java b/car-ui-lib/tests/unit/src/com/android/car/ui/preference/PreferenceTestActivity.java
index f4a762c..0916f4b 100644
--- a/car-ui-lib/tests/unit/src/com/android/car/ui/preference/PreferenceTestActivity.java
+++ b/car-ui-lib/tests/unit/src/com/android/car/ui/preference/PreferenceTestActivity.java
@@ -44,4 +44,12 @@
String key, Preference.OnPreferenceChangeListener listener) {
mPreferenceFragment.setOnPreferenceChangeListener(key, listener);
}
+
+ public void scrollToPreference(String key) {
+ mPreferenceFragment.scrollToPreference(key);
+ }
+
+ public void addPreference(Preference preference) {
+ mPreferenceFragment.addPreference(preference);
+ }
}
diff --git a/car-ui-lib/tests/unit/src/com/android/car/ui/preference/PreferenceTestFragment.java b/car-ui-lib/tests/unit/src/com/android/car/ui/preference/PreferenceTestFragment.java
index b21ef72..8d557fc 100644
--- a/car-ui-lib/tests/unit/src/com/android/car/ui/preference/PreferenceTestFragment.java
+++ b/car-ui-lib/tests/unit/src/com/android/car/ui/preference/PreferenceTestFragment.java
@@ -46,6 +46,10 @@
findPreference(key).setOnPreferenceChangeListener(listener);
}
+ public void addPreference(Preference preference) {
+ getPreferenceManager().getPreferenceScreen().addPreference(preference);
+ }
+
/**
* Custom data store to be used for testing as SharedPreferences for instrumentation tests
* are not initialized as expected.
@@ -53,6 +57,7 @@
public static class TestDataStore extends PreferenceDataStore {
private Map<String, String> mStringStore = new HashMap<>();
+ private Map<String, Boolean> mBooleanStore = new HashMap<>();
private Map<String, Set<String>> mStringSetStore = new HashMap<>();
@Override
@@ -80,5 +85,15 @@
}
return mStringSetStore.getOrDefault(key, defValues);
}
+
+ @Override
+ public void putBoolean(String key, boolean value) {
+ mBooleanStore.put(key, value);
+ }
+
+ @Override
+ public boolean getBoolean(String key, boolean defValue) {
+ return mBooleanStore.getOrDefault(key, defValue);
+ }
}
}