1 /* 2 * Copyright (C) 2016 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 package com.android.settings.dashboard; 17 18 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.DASHBOARD_CONTAINER; 19 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT; 20 21 import static com.google.common.truth.Truth.assertThat; 22 23 import static org.mockito.ArgumentMatchers.nullable; 24 import static org.mockito.Mockito.mock; 25 import static org.mockito.Mockito.never; 26 import static org.mockito.Mockito.spy; 27 import static org.mockito.Mockito.times; 28 import static org.mockito.Mockito.verify; 29 import static org.mockito.Mockito.when; 30 31 import android.app.settings.SettingsEnums; 32 import android.content.Context; 33 import android.content.pm.ActivityInfo; 34 import android.os.Bundle; 35 36 import androidx.preference.Preference; 37 import androidx.preference.PreferenceManager; 38 import androidx.preference.PreferenceScreen; 39 40 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 41 import com.android.settings.core.PreferenceControllerMixin; 42 import com.android.settings.slices.BlockingSlicePrefController; 43 import com.android.settings.testutils.FakeFeatureFactory; 44 import com.android.settingslib.core.AbstractPreferenceController; 45 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; 46 import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin; 47 import com.android.settingslib.drawer.DashboardCategory; 48 import com.android.settingslib.drawer.Tile; 49 50 import org.junit.Before; 51 import org.junit.Test; 52 import org.junit.runner.RunWith; 53 import org.mockito.Mock; 54 import org.mockito.MockitoAnnotations; 55 import org.robolectric.RobolectricTestRunner; 56 import org.robolectric.RuntimeEnvironment; 57 import org.robolectric.annotation.Config; 58 import org.robolectric.util.ReflectionHelpers; 59 60 import java.util.ArrayList; 61 import java.util.Arrays; 62 import java.util.HashMap; 63 import java.util.List; 64 import java.util.Map; 65 66 @RunWith(RobolectricTestRunner.class) 67 public class DashboardFragmentTest { 68 69 @Mock 70 private FakeFeatureFactory mFakeFeatureFactory; 71 private ActivityInfo mActivityInfo; 72 private DashboardCategory mDashboardCategory; 73 private Context mContext; 74 private TestFragment mTestFragment; 75 private List<AbstractPreferenceController> mControllers; 76 77 @Before setUp()78 public void setUp() { 79 MockitoAnnotations.initMocks(this); 80 mContext = spy(RuntimeEnvironment.application); 81 mActivityInfo = new ActivityInfo(); 82 mActivityInfo.packageName = "pkg"; 83 mActivityInfo.name = "class"; 84 mActivityInfo.metaData = new Bundle(); 85 mActivityInfo.metaData.putString(META_DATA_PREFERENCE_KEYHINT, "injected_tile_key"); 86 mFakeFeatureFactory = FakeFeatureFactory.setupForTest(); 87 mDashboardCategory = new DashboardCategory("key"); 88 mDashboardCategory.addTile(new Tile(mActivityInfo, mDashboardCategory.key)); 89 mTestFragment = new TestFragment(RuntimeEnvironment.application); 90 when(mFakeFeatureFactory.dashboardFeatureProvider 91 .getTilesForCategory(nullable(String.class))) 92 .thenReturn(mDashboardCategory); 93 mTestFragment.onAttach(RuntimeEnvironment.application); 94 when(mContext.getPackageName()).thenReturn("TestPackage"); 95 mControllers = new ArrayList<>(); 96 } 97 98 @Test testPreferenceControllerGetterSetter_shouldAddAndGetProperly()99 public void testPreferenceControllerGetterSetter_shouldAddAndGetProperly() { 100 final TestPreferenceController controller = new TestPreferenceController(mContext); 101 mTestFragment.addPreferenceController(controller); 102 103 final TestPreferenceController retrievedController = mTestFragment.use 104 (TestPreferenceController.class); 105 106 assertThat(controller).isSameAs(retrievedController); 107 } 108 109 @Test testPreferenceControllerSetter_shouldAddAndNotReplace()110 public void testPreferenceControllerSetter_shouldAddAndNotReplace() { 111 final TestPreferenceController controller1 = new TestPreferenceController(mContext); 112 mTestFragment.addPreferenceController(controller1); 113 final TestPreferenceController controller2 = new TestPreferenceController(mContext); 114 mTestFragment.addPreferenceController(controller2); 115 116 final TestPreferenceController retrievedController = mTestFragment.use 117 (TestPreferenceController.class); 118 119 assertThat(controller1).isSameAs(retrievedController); 120 } 121 122 @Test displayTilesAsPreference_shouldAddTilesWithIntent()123 public void displayTilesAsPreference_shouldAddTilesWithIntent() { 124 when(mFakeFeatureFactory.dashboardFeatureProvider 125 .getTilesForCategory(nullable(String.class))) 126 .thenReturn(mDashboardCategory); 127 when(mFakeFeatureFactory.dashboardFeatureProvider 128 .getDashboardKeyForTile(nullable(Tile.class))) 129 .thenReturn("test_key"); 130 mTestFragment.onCreatePreferences(new Bundle(), "rootKey"); 131 132 verify(mTestFragment.mScreen).addPreference(nullable(Preference.class)); 133 } 134 135 @Test displayTilesAsPreference_shouldNotAddTilesWithoutIntent()136 public void displayTilesAsPreference_shouldNotAddTilesWithoutIntent() { 137 mTestFragment.onCreatePreferences(new Bundle(), "rootKey"); 138 139 verify(mTestFragment.mScreen, never()).addPreference(nullable(Preference.class)); 140 } 141 142 @Test displayTilesAsPreference_withEmptyCategory_shouldNotAddTiles()143 public void displayTilesAsPreference_withEmptyCategory_shouldNotAddTiles() { 144 mDashboardCategory.removeTile(0); 145 mTestFragment.onCreatePreferences(new Bundle(), "rootKey"); 146 147 verify(mTestFragment.mScreen, never()).addPreference(nullable(Preference.class)); 148 } 149 150 @Test 151 @Config(qualifiers = "mcc999") displayTilesAsPreference_shouldNotAddSuppressedTiles()152 public void displayTilesAsPreference_shouldNotAddSuppressedTiles() { 153 when(mFakeFeatureFactory.dashboardFeatureProvider 154 .getTilesForCategory(nullable(String.class))) 155 .thenReturn(mDashboardCategory); 156 when(mFakeFeatureFactory.dashboardFeatureProvider 157 .getDashboardKeyForTile(nullable(Tile.class))) 158 .thenReturn("test_key"); 159 mTestFragment.onCreatePreferences(new Bundle(), "rootKey"); 160 161 verify(mTestFragment.mScreen, never()).addPreference(nullable(Preference.class)); 162 } 163 164 @Test onAttach_shouldCreatePlaceholderPreferenceController()165 public void onAttach_shouldCreatePlaceholderPreferenceController() { 166 final AbstractPreferenceController controller = mTestFragment.use( 167 DashboardTilePlaceholderPreferenceController.class); 168 169 assertThat(controller).isNotNull(); 170 } 171 172 @Test updateState_skipUnavailablePrefs()173 public void updateState_skipUnavailablePrefs() { 174 final List<AbstractPreferenceController> preferenceControllers = mTestFragment.mControllers; 175 final AbstractPreferenceController mockController1 = 176 mock(AbstractPreferenceController.class); 177 final AbstractPreferenceController mockController2 = 178 mock(AbstractPreferenceController.class); 179 when(mockController1.getPreferenceKey()).thenReturn("key1"); 180 when(mockController2.getPreferenceKey()).thenReturn("key2"); 181 preferenceControllers.add(mockController1); 182 preferenceControllers.add(mockController2); 183 when(mockController1.isAvailable()).thenReturn(false); 184 when(mockController2.isAvailable()).thenReturn(true); 185 mTestFragment.onAttach(RuntimeEnvironment.application); 186 mTestFragment.onResume(); 187 188 verify(mockController1).getPreferenceKey(); 189 verify(mockController2, times(2)).getPreferenceKey(); 190 } 191 192 @Test updateState_doesNotSkipControllersOfSameClass()193 public void updateState_doesNotSkipControllersOfSameClass() { 194 final AbstractPreferenceController mockController1 = 195 mock(AbstractPreferenceController.class); 196 final AbstractPreferenceController mockController2 = 197 mock(AbstractPreferenceController.class); 198 mTestFragment.addPreferenceController(mockController1); 199 mTestFragment.addPreferenceController(mockController2); 200 when(mockController1.isAvailable()).thenReturn(true); 201 when(mockController2.isAvailable()).thenReturn(true); 202 203 mTestFragment.updatePreferenceStates(); 204 205 verify(mockController1).getPreferenceKey(); 206 verify(mockController2).getPreferenceKey(); 207 } 208 209 @Test onExpandButtonClick_shouldLogAdvancedButtonExpand()210 public void onExpandButtonClick_shouldLogAdvancedButtonExpand() { 211 final MetricsFeatureProvider metricsFeatureProvider 212 = mFakeFeatureFactory.getMetricsFeatureProvider(); 213 mTestFragment.onExpandButtonClick(); 214 215 verify(metricsFeatureProvider).action(SettingsEnums.PAGE_UNKNOWN, 216 MetricsEvent.ACTION_SETTINGS_ADVANCED_BUTTON_EXPAND, 217 DASHBOARD_CONTAINER, null, 0); 218 } 219 220 @Test updatePreferenceVisibility_prefKeyNull_shouldNotCrash()221 public void updatePreferenceVisibility_prefKeyNull_shouldNotCrash() { 222 final Map<Class, List<AbstractPreferenceController>> prefControllers = new HashMap<>(); 223 final List<AbstractPreferenceController> controllerList = new ArrayList<>(); 224 controllerList.add(new TestPreferenceController(mContext)); 225 prefControllers.put(TestPreferenceController.class, controllerList); 226 mTestFragment.mBlockerController = new UiBlockerController(Arrays.asList("pref_key")); 227 228 // Should not crash 229 mTestFragment.updatePreferenceVisibility(prefControllers); 230 } 231 232 @Test checkUiBlocker_noUiBlocker_controllerIsNull()233 public void checkUiBlocker_noUiBlocker_controllerIsNull() { 234 mTestFragment.mBlockerController = null; 235 mControllers.add(new TestPreferenceController(mContext)); 236 237 mTestFragment.checkUiBlocker(mControllers); 238 239 assertThat(mTestFragment.mBlockerController).isNull(); 240 } 241 242 @Test checkUiBlocker_hasUiBlocker_controllerNotNull()243 public void checkUiBlocker_hasUiBlocker_controllerNotNull() { 244 mTestFragment.mBlockerController = null; 245 mControllers.add(new TestPreferenceController(mContext)); 246 mControllers.add(new BlockingSlicePrefController(mContext, "pref_key")); 247 248 mTestFragment.checkUiBlocker(mControllers); 249 250 assertThat(mTestFragment.mBlockerController).isNotNull(); 251 } 252 253 public static class TestPreferenceController extends AbstractPreferenceController 254 implements PreferenceControllerMixin { 255 TestPreferenceController(Context context)256 private TestPreferenceController(Context context) { 257 super(context); 258 } 259 260 @Override handlePreferenceTreeClick(Preference preference)261 public boolean handlePreferenceTreeClick(Preference preference) { 262 return false; 263 } 264 265 @Override isAvailable()266 public boolean isAvailable() { 267 return false; 268 } 269 270 @Override getPreferenceKey()271 public String getPreferenceKey() { 272 return null; 273 } 274 275 @Override updateNonIndexableKeys(List<String> keys)276 public void updateNonIndexableKeys(List<String> keys) { 277 } 278 } 279 280 public static class TestFragment extends DashboardFragment { 281 282 private final PreferenceManager mPreferenceManager; 283 private final Context mContext; 284 private final List<AbstractPreferenceController> mControllers; 285 286 public final PreferenceScreen mScreen; 287 TestFragment(Context context)288 public TestFragment(Context context) { 289 mContext = context; 290 mPreferenceManager = mock(PreferenceManager.class); 291 mScreen = mock(PreferenceScreen.class); 292 mControllers = new ArrayList<>(); 293 294 when(mPreferenceManager.getContext()).thenReturn(mContext); 295 ReflectionHelpers.setField( 296 this, "mVisibilityLoggerMixin", mock(VisibilityLoggerMixin.class)); 297 } 298 299 @Override getContext()300 public Context getContext() { 301 return mContext; 302 } 303 304 @Override getMetricsCategory()305 public int getMetricsCategory() { 306 return DASHBOARD_CONTAINER; 307 } 308 309 @Override getPreferenceScreen()310 public PreferenceScreen getPreferenceScreen() { 311 return mScreen; 312 } 313 314 @Override getLogTag()315 protected String getLogTag() { 316 return "TEST_FRAG"; 317 } 318 319 @Override getPreferenceScreenResId()320 protected int getPreferenceScreenResId() { 321 return 0; 322 } 323 324 @Override createPreferenceControllers(Context context)325 protected List<AbstractPreferenceController> createPreferenceControllers(Context context) { 326 return mControllers; 327 } 328 329 @Override getPreferenceManager()330 public PreferenceManager getPreferenceManager() { 331 return mPreferenceManager; 332 } 333 } 334 } 335