1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.mockito.ArgumentMatchers.any; 22 import static org.mockito.Mockito.doReturn; 23 import static org.mockito.Mockito.mock; 24 import static org.mockito.Mockito.never; 25 import static org.mockito.Mockito.spy; 26 import static org.mockito.Mockito.times; 27 import static org.mockito.Mockito.verify; 28 import static org.mockito.Mockito.when; 29 30 import android.content.Context; 31 import android.os.Bundle; 32 import android.provider.Settings; 33 import android.view.View; 34 import android.widget.FrameLayout; 35 36 import androidx.fragment.app.FragmentActivity; 37 import androidx.preference.Preference; 38 import androidx.preference.PreferenceCategory; 39 import androidx.preference.PreferenceManager; 40 import androidx.preference.PreferenceScreen; 41 42 import com.android.settings.testutils.FakeFeatureFactory; 43 import com.android.settings.widget.WorkOnlyCategory; 44 45 import org.junit.After; 46 import org.junit.Before; 47 import org.junit.Test; 48 import org.junit.runner.RunWith; 49 import org.mockito.Mock; 50 import org.mockito.MockitoAnnotations; 51 import org.robolectric.RobolectricTestRunner; 52 import org.robolectric.RuntimeEnvironment; 53 import org.robolectric.annotation.Config; 54 import org.robolectric.util.ReflectionHelpers; 55 56 @RunWith(RobolectricTestRunner.class) 57 @Config(shadows = { 58 com.android.settings.testutils.shadow.ShadowFragment.class, 59 }) 60 public class SettingsPreferenceFragmentTest { 61 62 private static final int ITEM_COUNT = 5; 63 64 @Mock 65 private FragmentActivity mActivity; 66 @Mock 67 private View mListContainer; 68 @Mock 69 private PreferenceScreen mPreferenceScreen; 70 private Context mContext; 71 private TestFragment mFragment; 72 private TestFragment2 mFragment2; 73 private View mEmptyView; 74 private int mInitDeviceProvisionedValue; 75 76 @Before setUp()77 public void setUp() { 78 MockitoAnnotations.initMocks(this); 79 FakeFeatureFactory.setupForTest(); 80 mContext = RuntimeEnvironment.application; 81 mFragment = spy(new TestFragment()); 82 mFragment2 = spy(new TestFragment2()); 83 doReturn(mActivity).when(mFragment).getActivity(); 84 when(mFragment.getContext()).thenReturn(mContext); 85 when(mFragment2.getContext()).thenReturn(mContext); 86 87 mEmptyView = new View(mContext); 88 ReflectionHelpers.setField(mFragment, "mEmptyView", mEmptyView); 89 90 doReturn(ITEM_COUNT).when(mPreferenceScreen).getPreferenceCount(); 91 92 mInitDeviceProvisionedValue = Settings.Global.getInt(mContext.getContentResolver(), 93 Settings.Global.DEVICE_PROVISIONED, 0); 94 } 95 96 @After tearDown()97 public void tearDown() { 98 Settings.Global.putInt(mContext.getContentResolver(), 99 Settings.Global.DEVICE_PROVISIONED, mInitDeviceProvisionedValue); 100 } 101 102 @Test removePreference_nested_shouldRemove()103 public void removePreference_nested_shouldRemove() { 104 final String key = "test_key"; 105 final PreferenceScreen mScreen = spy(new PreferenceScreen(mContext, null)); 106 when(mScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class)); 107 108 final PreferenceCategory nestedCategory = new ProgressCategory(mContext); 109 final Preference preference = new Preference(mContext); 110 preference.setKey(key); 111 preference.setPersistent(false); 112 113 mScreen.addPreference(nestedCategory); 114 nestedCategory.addPreference(preference); 115 116 assertThat(mFragment.removePreference(mScreen, key)).isTrue(); 117 assertThat(nestedCategory.getPreferenceCount()).isEqualTo(0); 118 } 119 120 @Test removePreference_flat_shouldRemove()121 public void removePreference_flat_shouldRemove() { 122 final String key = "test_key"; 123 final PreferenceScreen mScreen = spy(new PreferenceScreen(mContext, null)); 124 when(mScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class)); 125 126 final Preference preference = mock(Preference.class); 127 when(preference.getKey()).thenReturn(key); 128 129 mScreen.addPreference(preference); 130 131 assertThat(mFragment.removePreference(mScreen, key)).isTrue(); 132 assertThat(mScreen.getPreferenceCount()).isEqualTo(0); 133 } 134 135 @Test removePreference_doNotExist_shouldNotRemove()136 public void removePreference_doNotExist_shouldNotRemove() { 137 final String key = "test_key"; 138 final PreferenceScreen mScreen = spy(new PreferenceScreen(mContext, null)); 139 when(mScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class)); 140 141 final Preference preference = mock(Preference.class); 142 when(preference.getKey()).thenReturn(key); 143 144 mScreen.addPreference(preference); 145 146 assertThat(mFragment.removePreference(mScreen, "not" + key)).isFalse(); 147 assertThat(mScreen.getPreferenceCount()).isEqualTo(1); 148 } 149 150 @Test testUpdateEmptyView_containerInvisible_emptyViewVisible()151 public void testUpdateEmptyView_containerInvisible_emptyViewVisible() { 152 doReturn(View.INVISIBLE).when(mListContainer).getVisibility(); 153 doReturn(mListContainer).when(mActivity).findViewById(android.R.id.list_container); 154 doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen(); 155 156 mFragment.updateEmptyView(); 157 158 assertThat(mEmptyView.getVisibility()).isEqualTo(View.VISIBLE); 159 } 160 161 @Test testUpdateEmptyView_containerNull_emptyViewGone()162 public void testUpdateEmptyView_containerNull_emptyViewGone() { 163 doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen(); 164 165 mFragment.updateEmptyView(); 166 167 assertThat(mEmptyView.getVisibility()).isEqualTo(View.GONE); 168 } 169 170 @Test onCreate_hasExtraFragmentKey_shouldExpandPreferences()171 public void onCreate_hasExtraFragmentKey_shouldExpandPreferences() { 172 doReturn(mContext.getTheme()).when(mActivity).getTheme(); 173 doReturn(mContext.getResources()).when(mFragment).getResources(); 174 doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen(); 175 final Bundle bundle = new Bundle(); 176 bundle.putString(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY, "test_key"); 177 when(mFragment.getArguments()).thenReturn(bundle); 178 179 mFragment.onCreate(null /* icicle */); 180 181 verify(mPreferenceScreen).setInitialExpandedChildrenCount(Integer.MAX_VALUE); 182 } 183 184 @Test onCreate_noPreferenceScreen_shouldNotCrash()185 public void onCreate_noPreferenceScreen_shouldNotCrash() { 186 doReturn(mContext.getTheme()).when(mActivity).getTheme(); 187 doReturn(mContext.getResources()).when(mFragment).getResources(); 188 doReturn(null).when(mFragment).getPreferenceScreen(); 189 final Bundle bundle = new Bundle(); 190 bundle.putString(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY, "test_key"); 191 when(mFragment.getArguments()).thenReturn(bundle); 192 193 mFragment.onCreate(null /* icicle */); 194 // no crash 195 } 196 197 @Test checkAvailablePrefs_selfAvialbalePreferenceNotAvailable_shouldHidePreference()198 public void checkAvailablePrefs_selfAvialbalePreferenceNotAvailable_shouldHidePreference() { 199 doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen(); 200 final WorkOnlyCategory workOnlyCategory = mock(WorkOnlyCategory.class); 201 when(mPreferenceScreen.getPreferenceCount()).thenReturn(1); 202 when(mPreferenceScreen.getPreference(0)).thenReturn(workOnlyCategory); 203 when(workOnlyCategory.isAvailable(any(Context.class))).thenReturn(false); 204 205 mFragment.checkAvailablePrefs(mPreferenceScreen); 206 207 verify(mPreferenceScreen, never()).removePreference(workOnlyCategory); 208 verify(workOnlyCategory).setVisible(false); 209 } 210 211 @Test showPinnedHeader_shouldBeVisible()212 public void showPinnedHeader_shouldBeVisible() { 213 mFragment.mPinnedHeaderFrameLayout = new FrameLayout(mContext); 214 215 mFragment.showPinnedHeader(true); 216 217 assertThat(mFragment.mPinnedHeaderFrameLayout.getVisibility()).isEqualTo(View.VISIBLE); 218 } 219 220 @Test hidePinnedHeader_shouldBeInvisible()221 public void hidePinnedHeader_shouldBeInvisible() { 222 mFragment.mPinnedHeaderFrameLayout = new FrameLayout(mContext); 223 224 mFragment.showPinnedHeader(false); 225 226 assertThat(mFragment.mPinnedHeaderFrameLayout.getVisibility()).isEqualTo(View.INVISIBLE); 227 } 228 229 @Test onAttach_shouldNotSkipForSUWAndDeviceIsProvisioned_notCallFinish()230 public void onAttach_shouldNotSkipForSUWAndDeviceIsProvisioned_notCallFinish() { 231 Settings.Global.putInt(mContext.getContentResolver(), 232 Settings.Global.DEVICE_PROVISIONED, 1); 233 234 mFragment.onAttach(mContext); 235 236 verify(mFragment, never()).finish(); 237 } 238 239 @Test onAttach_shouldNotSkipForSUWAndDeviceIsNotProvisioned_notCallFinish()240 public void onAttach_shouldNotSkipForSUWAndDeviceIsNotProvisioned_notCallFinish() { 241 Settings.Global.putInt(mContext.getContentResolver(), 242 Settings.Global.DEVICE_PROVISIONED, 0); 243 244 mFragment.onAttach(mContext); 245 246 verify(mFragment, never()).finish(); 247 } 248 249 @Test onAttach_shouldSkipForSUWAndDeviceIsDeviceProvisioned_notCallFinish()250 public void onAttach_shouldSkipForSUWAndDeviceIsDeviceProvisioned_notCallFinish() { 251 Settings.Global.putInt(mContext.getContentResolver(), 252 Settings.Global.DEVICE_PROVISIONED, 1); 253 254 mFragment2.onAttach(mContext); 255 256 verify(mFragment2, never()).finish(); 257 } 258 259 @Test onAttach_shouldSkipForSUWAndDeviceProvisioned_notCallFinish()260 public void onAttach_shouldSkipForSUWAndDeviceProvisioned_notCallFinish() { 261 Settings.Global.putInt(mContext.getContentResolver(), 262 Settings.Global.DEVICE_PROVISIONED, 0); 263 264 mFragment2.onAttach(mContext); 265 266 verify(mFragment2, times(1)).finish(); 267 } 268 269 public static class TestFragment extends SettingsPreferenceFragment { 270 271 @Override shouldSkipForInitialSUW()272 protected boolean shouldSkipForInitialSUW() { 273 return false; 274 } 275 276 @Override getMetricsCategory()277 public int getMetricsCategory() { 278 return 0; 279 } 280 } 281 282 public static class TestFragment2 extends SettingsPreferenceFragment { 283 284 @Override shouldSkipForInitialSUW()285 protected boolean shouldSkipForInitialSUW() { 286 return true; 287 } 288 289 @Override getMetricsCategory()290 public int getMetricsCategory() { 291 return 0; 292 } 293 } 294 } 295