/* * Copyright (C) 2016 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.dashboard; import android.content.Context; import android.support.v14.preference.PreferenceFragment; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceManager; import android.support.v7.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; import com.android.settings.testutils.FakeFeatureFactory; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Answers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowApplication; import org.robolectric.util.ReflectionHelpers; import java.util.List; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) public class ProgressiveDisclosureTest { @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext; @Mock(answer = Answers.RETURNS_DEEP_STUBS) private PreferenceFragment mPreferenceFragment; @Mock private ExpandPreference mExpandButton; private PreferenceScreen mScreen; private Context mAppContext; private Preference mPreference; private ProgressiveDisclosureMixin mMixin; @Before public void setUp() { MockitoAnnotations.initMocks(this); FakeFeatureFactory.setupForTest(mContext); mScreen = mPreferenceFragment.getPreferenceScreen(); mAppContext = ShadowApplication.getInstance().getApplicationContext(); mMixin = new ProgressiveDisclosureMixin(mAppContext, mPreferenceFragment, false /* keepExpanded */); ReflectionHelpers.setField(mMixin, "mExpandButton", mExpandButton); mPreference = new Preference(mAppContext); mPreference.setKey("test"); } @Test public void shouldNotCollapse_lessPreferenceThanLimit() { when(mScreen.getPreferenceCount()).thenReturn(5); mMixin.setTileLimit(10); assertThat(mMixin.shouldCollapse(mScreen)).isFalse(); } @Test public void shouldNotCollapse_preferenceCountSameAsThreshold() { when(mScreen.getPreferenceCount()).thenReturn(5); mMixin.setTileLimit(5); assertThat(mMixin.shouldCollapse(mScreen)).isFalse(); } @Test public void shouldNotCollapse_whenStartAsExpanded() { when(mScreen.getPreferenceCount()).thenReturn(5); mMixin = new ProgressiveDisclosureMixin(mAppContext, mPreferenceFragment, true /* keepExpanded */); mMixin.setTileLimit(10); assertThat(mMixin.shouldCollapse(mScreen)).isFalse(); } @Test public void shouldCollapse_morePreferenceThanLimit() { when(mScreen.getPreferenceCount()).thenReturn(5); mMixin.setTileLimit(3); assertThat(mMixin.shouldCollapse(mScreen)).isTrue(); } @Test public void findPreference_prefInCollapsedList_shouldFindIt() { when(mScreen.findPreference(anyString())).thenReturn(null); mMixin.addToCollapsedList(mPreference); Preference pref = mMixin.findPreference(mScreen, mPreference.getKey()); assertThat(pref).isNotNull(); assertThat(pref).isSameAs(mPreference); } @Test public void findPreference_prefOnScreen_shouldFindIt() { when(mScreen.findPreference(mPreference.getKey())).thenReturn(mPreference); Preference pref = mMixin.findPreference(mScreen, mPreference.getKey()); assertThat(pref).isNotNull(); assertThat(pref).isSameAs(mPreference); } @Test public void findPreference_prefNotInCollapsedListOrScreen_shouldNotFindIt() { when(mScreen.findPreference(anyString())).thenReturn(null); Preference pref = mMixin.findPreference(mScreen, mPreference.getKey()); assertThat(pref).isNull(); } @Test public void findPreference_prefRemovedFromCollapsedList_shouldNotFindIt() { when(mScreen.findPreference(anyString())).thenReturn(null); mMixin.addToCollapsedList(mPreference); mMixin.removePreference(mPreferenceFragment.getPreferenceScreen(), mPreference.getKey()); Preference pref = mMixin.findPreference(mScreen, mPreference.getKey()); assertThat(pref).isNull(); } @Test public void findPreference_nestedPrefInCollapsedList_shouldFindIt() { when(mScreen.findPreference(anyString())).thenReturn(null); final PreferenceScreen prefGroup = spy(new PreferenceScreen(mAppContext, null)); when(prefGroup.getPreferenceManager()).thenReturn(mock(PreferenceManager.class)); final Preference preference = mock(Preference.class); when(preference.getKey()).thenReturn("TestKey"); prefGroup.addPreference(preference); mMixin.addToCollapsedList(prefGroup); Preference pref = mMixin.findPreference(mScreen, "TestKey"); assertThat(pref).isNotNull(); assertThat(pref).isSameAs(preference); } @Test public void removePreference_shouldRemoveOnScreenPreference() { when(mScreen.findPreference(mPreference.getKey())).thenReturn(mPreference); mMixin.removePreference(mScreen, mPreference.getKey()); verify(mScreen).removePreference(mPreference); } @Test public void removeLastPreference_shouldRemoveExpandButtonToo() { when(mScreen.findPreference(anyString())).thenReturn(null); mMixin.addToCollapsedList(mPreference); // Collapsed assertThat(mMixin.isCollapsed()).isTrue(); mMixin.removePreference(mScreen, mPreference.getKey()); // Removing expand button verify(mScreen).removePreference(any(Preference.class)); // No longer collapsed assertThat(mMixin.isCollapsed()).isFalse(); } @Test public void collapse_shouldDoNothingIfNotCollapsible() { final PreferenceScreen screen = mPreferenceFragment.getPreferenceScreen(); when(screen.getPreferenceCount()).thenReturn(5); mMixin.setTileLimit(15); mMixin.collapse(screen); assertThat(mMixin.isCollapsed()).isFalse(); verify(mExpandButton, never()).setSummary(anyString()); verify(screen, never()).addPreference(any(Preference.class)); verify(screen, never()).removePreference(any(Preference.class)); } @Test public void collapse_shouldRemovePrefAndAddExpandButton() { final PreferenceScreen screen = mPreferenceFragment.getPreferenceScreen(); when(screen.getPreferenceCount()).thenReturn(5); when(screen.getPreference(anyInt())).thenReturn(mPreference); mMixin.setTileLimit(2); mMixin.collapse(screen); assertThat(mMixin.isCollapsed()).isTrue(); verify(mExpandButton, atLeastOnce()).setSummary(anyString()); verify(screen).addPreference(any(ExpandPreference.class)); verify(screen, times(3)).removePreference(any(Preference.class)); } @Test public void addToCollapsedList_shouldAddInOrder() { final Preference pref1 = new Preference(mAppContext); final Preference pref2 = new Preference(mAppContext); pref1.setOrder(10); pref2.setOrder(20); // Pref1 has lower order than pref2, but add pref2 first. The collapsed list should maintain // items in increasing order. mMixin.addToCollapsedList(pref2); mMixin.addToCollapsedList(pref1); List collapsedList = mMixin.getCollapsedPrefs(); assertThat(collapsedList.get(0)).isSameAs(pref1); assertThat(collapsedList.get(1)).isSameAs(pref2); } @Test public void addPreferenceWhenCollapsed_noPrefOnScreen_shouldAddToList() { // Add something to collapsed list so we are in collapsed state. mMixin.addToCollapsedList(new Preference(mAppContext)); assertThat(mMixin.getCollapsedPrefs().size()).isEqualTo(1); // Just 1 preference on screen: the more button when(mScreen.getPreferenceCount()).thenReturn(1); final Preference toBeAdded = new Preference(mAppContext); toBeAdded.setOrder(100); mMixin.addPreference(mScreen, toBeAdded); // Should have 2 prefs in collapsed list now assertThat(mMixin.getCollapsedPrefs().size()).isEqualTo(2); assertThat(mMixin.getCollapsedPrefs().get(0)).isSameAs(toBeAdded); } @Test public void addPreferenceWhenCollapsed_prefOrderLessThanLastOnScreen_shouldAddToScreen() { final Preference lastPref = new Preference(mAppContext); lastPref.setOrder(100); // Add something to collapsed list so we are in collapsed state. mMixin.addToCollapsedList(new Preference(mAppContext)); verify(mExpandButton).setSummary(anyString()); assertThat(mMixin.getCollapsedPrefs().size()).isEqualTo(1); // 3 prefs on screen, 2 are real and the last one is more button. when(mScreen.getPreferenceCount()).thenReturn(3); when(mScreen.getPreference(1)).thenReturn(lastPref); final Preference toBeAdded = new Preference(mAppContext); toBeAdded.setOrder(50); mMixin.addPreference(mScreen, toBeAdded); verify(mScreen).removePreference(lastPref); verify(mScreen).addPreference(toBeAdded); assertThat(mMixin.getCollapsedPrefs().get(0)).isSameAs(lastPref); } @Test public void addPreferenceWhenCollapsed_prefOrderMoreThanLastOnScreen_shouldAddToList() { final Preference lastPref = new Preference(mAppContext); lastPref.setOrder(100); // Add something to collapsed list so we are in collapsed state. mMixin.addToCollapsedList(new Preference(mAppContext)); verify(mExpandButton).setSummary(anyString()); assertThat(mMixin.getCollapsedPrefs().size()).isEqualTo(1); // 3 prefs on screen, 2 are real and the last one is more button. when(mScreen.getPreferenceCount()).thenReturn(3); when(mScreen.getPreference(1)).thenReturn(lastPref); final Preference toBeAdded = new Preference(mAppContext); toBeAdded.setOrder(200); mMixin.addPreference(mScreen, toBeAdded); verify(mScreen, never()).removePreference(any(Preference.class)); verify(mScreen, never()).addPreference(any(Preference.class)); verify(mExpandButton, times(2)).setSummary(anyString()); assertThat(mMixin.getCollapsedPrefs().get(0)).isSameAs(toBeAdded); } @Test public void updateExpandSummary_noPref_noSummary() { mMixin.updateExpandButtonSummary(); verify(mExpandButton).setSummary(null); } @Test public void updateExpandSummary_doNotIncludeEmptyPrefTitle() { final Preference pref1 = new Preference(mAppContext); pref1.setTitle("1"); final Preference pref2 = new Preference(mAppContext); pref2.setTitle(null); final Preference pref3 = new Preference(mAppContext); pref3.setTitle("3"); final Preference pref4 = new Preference(mAppContext); pref4.setTitle(""); mMixin.addToCollapsedList(pref1); mMixin.addToCollapsedList(pref2); mMixin.addToCollapsedList(pref3); mMixin.addToCollapsedList(pref4); verify(mExpandButton).setSummary("1, 3"); } @Test public void updateExapndSummary_singlePref_expandSummarySameAsPrefTitle() { final String TEST = "test"; final Preference pref = new Preference(mAppContext); pref.setTitle(TEST); mMixin.addToCollapsedList(pref); verify(mExpandButton).setSummary(TEST); } @Test public void updateExapndSummary_multiPrefs_useCombinedPrefTitleAsSummary() { final String TEST1 = "test1"; final String TEST2 = "test2"; final Preference pref1 = new Preference(mAppContext); pref1.setTitle(TEST1); final Preference pref2 = new Preference(mAppContext); pref2.setTitle(TEST2); mMixin.addToCollapsedList(pref1); mMixin.addToCollapsedList(pref2); verify(mExpandButton) .setSummary(mAppContext.getString(R.string.join_many_items_middle, TEST1, TEST2)); } }