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.testutils.shadow.ShadowFragment; 44 import com.android.settings.widget.WorkOnlyCategory; 45 46 import org.junit.After; 47 import org.junit.Before; 48 import org.junit.Test; 49 import org.junit.runner.RunWith; 50 import org.mockito.Mock; 51 import org.mockito.MockitoAnnotations; 52 import org.robolectric.RobolectricTestRunner; 53 import org.robolectric.RuntimeEnvironment; 54 import org.robolectric.annotation.Config; 55 import org.robolectric.util.ReflectionHelpers; 56 57 @RunWith(RobolectricTestRunner.class) 58 public class SettingsPreferenceFragmentTest { 59 60 private static final int ITEM_COUNT = 5; 61 62 @Mock 63 private FragmentActivity mActivity; 64 @Mock 65 private View mListContainer; 66 @Mock 67 private PreferenceScreen mPreferenceScreen; 68 private Context mContext; 69 private TestFragment mFragment; 70 private TestFragment2 mFragment2; 71 private View mEmptyView; 72 private int mInitDeviceProvisionedValue; 73 74 @Before setUp()75 public void setUp() { 76 MockitoAnnotations.initMocks(this); 77 FakeFeatureFactory.setupForTest(); 78 mContext = RuntimeEnvironment.application; 79 mFragment = spy(new TestFragment()); 80 mFragment2 = spy(new TestFragment2()); 81 doReturn(mActivity).when(mFragment).getActivity(); 82 when(mFragment.getContext()).thenReturn(mContext); 83 when(mFragment2.getContext()).thenReturn(mContext); 84 85 mEmptyView = new View(mContext); 86 ReflectionHelpers.setField(mFragment, "mEmptyView", mEmptyView); 87 88 doReturn(ITEM_COUNT).when(mPreferenceScreen).getPreferenceCount(); 89 90 mInitDeviceProvisionedValue = Settings.Global.getInt(mContext.getContentResolver(), 91 Settings.Global.DEVICE_PROVISIONED, 0); 92 } 93 94 @After tearDown()95 public void tearDown() { 96 Settings.Global.putInt(mContext.getContentResolver(), 97 Settings.Global.DEVICE_PROVISIONED, mInitDeviceProvisionedValue); 98 } 99 100 @Test removePreference_nested_shouldRemove()101 public void removePreference_nested_shouldRemove() { 102 final String key = "test_key"; 103 final PreferenceScreen mScreen = spy(new PreferenceScreen(mContext, null)); 104 when(mScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class)); 105 106 final PreferenceCategory nestedCategory = new ProgressCategory(mContext); 107 final Preference preference = new Preference(mContext); 108 preference.setKey(key); 109 preference.setPersistent(false); 110 111 mScreen.addPreference(nestedCategory); 112 nestedCategory.addPreference(preference); 113 114 assertThat(mFragment.removePreference(mScreen, key)).isTrue(); 115 assertThat(nestedCategory.getPreferenceCount()).isEqualTo(0); 116 } 117 118 @Test removePreference_flat_shouldRemove()119 public void removePreference_flat_shouldRemove() { 120 final String key = "test_key"; 121 final PreferenceScreen mScreen = spy(new PreferenceScreen(mContext, null)); 122 when(mScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class)); 123 124 final Preference preference = mock(Preference.class); 125 when(preference.getKey()).thenReturn(key); 126 127 mScreen.addPreference(preference); 128 129 assertThat(mFragment.removePreference(mScreen, key)).isTrue(); 130 assertThat(mScreen.getPreferenceCount()).isEqualTo(0); 131 } 132 133 @Test removePreference_doNotExist_shouldNotRemove()134 public void removePreference_doNotExist_shouldNotRemove() { 135 final String key = "test_key"; 136 final PreferenceScreen mScreen = spy(new PreferenceScreen(mContext, null)); 137 when(mScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class)); 138 139 final Preference preference = mock(Preference.class); 140 when(preference.getKey()).thenReturn(key); 141 142 mScreen.addPreference(preference); 143 144 assertThat(mFragment.removePreference(mScreen, "not" + key)).isFalse(); 145 assertThat(mScreen.getPreferenceCount()).isEqualTo(1); 146 } 147 148 @Test testUpdateEmptyView_containerInvisible_emptyViewVisible()149 public void testUpdateEmptyView_containerInvisible_emptyViewVisible() { 150 doReturn(View.INVISIBLE).when(mListContainer).getVisibility(); 151 doReturn(mListContainer).when(mActivity).findViewById(android.R.id.list_container); 152 doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen(); 153 154 mFragment.updateEmptyView(); 155 156 assertThat(mEmptyView.getVisibility()).isEqualTo(View.VISIBLE); 157 } 158 159 @Test testUpdateEmptyView_containerNull_emptyViewGone()160 public void testUpdateEmptyView_containerNull_emptyViewGone() { 161 doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen(); 162 163 mFragment.updateEmptyView(); 164 165 assertThat(mEmptyView.getVisibility()).isEqualTo(View.GONE); 166 } 167 168 @Test 169 @Config(shadows = ShadowFragment.class) onCreate_hasExtraFragmentKey_shouldExpandPreferences()170 public void onCreate_hasExtraFragmentKey_shouldExpandPreferences() { 171 doReturn(mContext.getTheme()).when(mActivity).getTheme(); 172 doReturn(mContext.getResources()).when(mFragment).getResources(); 173 doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen(); 174 final Bundle bundle = new Bundle(); 175 bundle.putString(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY, "test_key"); 176 when(mFragment.getArguments()).thenReturn(bundle); 177 178 mFragment.onCreate(null /* icicle */); 179 180 verify(mPreferenceScreen).setInitialExpandedChildrenCount(Integer.MAX_VALUE); 181 } 182 183 @Test 184 @Config(shadows = ShadowFragment.class) 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