diff --git a/src/com/android/settings/dashboard/DashboardFragment.java b/src/com/android/settings/dashboard/DashboardFragment.java index 28d153e8542..8a0a753e7d0 100644 --- a/src/com/android/settings/dashboard/DashboardFragment.java +++ b/src/com/android/settings/dashboard/DashboardFragment.java @@ -96,6 +96,10 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment DashboardCategory category) { final Context context = getContext(); List tiles = category.tiles; + if (tiles == null) { + Log.d(TAG, "tile list is empty, skipping category " + category.title); + return; + } for (Tile tile : tiles) { final String key = mDashboardFeatureProvider.getDashboardKeyForTile(tile); if (TextUtils.isEmpty(key)) { diff --git a/src/com/android/settings/overlay/FeatureFactory.java b/src/com/android/settings/overlay/FeatureFactory.java index dd3e9c83394..485abd08bdf 100644 --- a/src/com/android/settings/overlay/FeatureFactory.java +++ b/src/com/android/settings/overlay/FeatureFactory.java @@ -35,7 +35,7 @@ public abstract class FeatureFactory { private static final String LOG_TAG = "FeatureFactory"; private static final boolean DEBUG = false; - private static FeatureFactory sFactory; + protected static FeatureFactory sFactory; /** * Returns a factory for creating feature controllers. Creates the factory if it does not diff --git a/tests/robotests/src/com/android/settings/core/PreferenceControllerTest.java b/tests/robotests/src/com/android/settings/core/PreferenceControllerTest.java new file mode 100644 index 00000000000..e20efbeeb66 --- /dev/null +++ b/tests/robotests/src/com/android/settings/core/PreferenceControllerTest.java @@ -0,0 +1,97 @@ +/* + * 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.core; + +import android.content.Context; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceScreen; + +import com.android.settings.TestConfig; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +import java.util.List; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(RobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class PreferenceControllerTest { + private static final String KEY_PREF = "test_pref"; + + @Mock + private Context mContext; + @Mock + private PreferenceScreen mScreen; + @Mock + private Preference mPreference; + + private TestPrefController mTestPrefController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mTestPrefController = new TestPrefController(mContext); + } + + @Test + public void removeExistingPref_shouldBeRemoved() { + when(mScreen.findPreference(KEY_PREF)).thenReturn(mPreference); + + mTestPrefController.removePreference(mScreen, KEY_PREF); + + verify(mScreen).removePreference(mPreference); + } + + @Test + public void removeNonExistingPref_shouldNotRemoveAnything() { + mTestPrefController.removePreference(mScreen, KEY_PREF); + + verify(mScreen, never()).removePreference(any(Preference.class)); + } + + private class TestPrefController extends PreferenceController { + + public TestPrefController(Context context) { + super(context); + } + + @Override + public void displayPreference(PreferenceScreen screen) { + + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + return false; + } + + @Override + public void updateNonIndexableKeys(List keys) { + + } + } + +} diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java new file mode 100644 index 00000000000..de233667e2a --- /dev/null +++ b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java @@ -0,0 +1,154 @@ +/* + * 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.v7.preference.Preference; +import android.support.v7.preference.PreferenceScreen; + +import com.android.settings.TestConfig; +import com.android.settings.core.PreferenceController; +import com.android.settings.overlay.FeatureFactory; +import com.android.settings.testutils.FakeFeatureFactory; +import com.android.settingslib.drawer.DashboardCategory; +import com.android.settingslib.drawer.Tile; + +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.RobolectricTestRunner; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowApplication; + +import java.util.ArrayList; +import java.util.List; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(RobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class DashboardFragmentTest { + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private Context mContext; + @Mock + private DashboardCategory mDashboardCategory; + @Mock + private FakeFeatureFactory mFakeFeatureFactory; + @Mock + private PreferenceScreen mScreen; + private TestFragment mTestFragment; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + FakeFeatureFactory.setupForTest(mContext); + mFakeFeatureFactory = (FakeFeatureFactory) FeatureFactory.getFactory(mContext); + mDashboardCategory.tiles = new ArrayList<>(); + mDashboardCategory.tiles.add(new Tile()); + mTestFragment = new TestFragment(ShadowApplication.getInstance().getApplicationContext()); + mTestFragment.onAttach(mContext); + } + + @Test + public void testPreferenceControllerGetterSetter_shouldAddAndGetProperly() { + final TestPreferenceController controller = new TestPreferenceController(mContext); + mTestFragment.addPreferenceController(controller); + + final TestPreferenceController retrievedController = mTestFragment.getPreferenceController + (TestPreferenceController.class); + + assertThat(controller).isSameAs(retrievedController); + } + + @Test + public void displayTilesAsPreference_shouldAddTilesWithIntent() { + when(mFakeFeatureFactory.dashboardFeatureProvider.getDashboardKeyForTile(any(Tile.class))) + .thenReturn("test_key"); + mTestFragment.displayTilesAsPreference("TEST_FRAGMENT", mScreen, mDashboardCategory); + + verify(mScreen).addPreference(any(DashboardTilePreference.class)); + } + + @Test + public void displayTilesAsPreference_shouldNotAddTilesWithoutIntent() { + mTestFragment.displayTilesAsPreference("TEST_FRAGMENT", mScreen, mDashboardCategory); + + verify(mScreen, never()).addPreference(any(DashboardTilePreference.class)); + } + + @Test + public void displayTilesAsPreference_withEmptyCategory_shouldNotAddTiles() { + mDashboardCategory.tiles = null; + mTestFragment.displayTilesAsPreference("TEST_FRAGMENT", mScreen, mDashboardCategory); + + verify(mScreen, never()).addPreference(any(DashboardTilePreference.class)); + } + + public static class TestPreferenceController extends PreferenceController { + + public TestPreferenceController(Context context) { + super(context); + } + + @Override + public void displayPreference(PreferenceScreen screen) { + + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + return false; + } + + @Override + public void updateNonIndexableKeys(List keys) { + + } + } + + public static class TestFragment extends DashboardFragment { + + private final Context mContext; + + public TestFragment(Context context) { + mContext = context; + } + + @Override + public Context getContext() { + return mContext; + } + + @Override + public int getMetricsCategory() { + return 0; + } + + @Override + public void onCategoriesChanged() { + + } + } + +} diff --git a/tests/robotests/src/com/android/settings/deviceinfo/ManageStoragePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/ManageStoragePreferenceControllerTest.java new file mode 100644 index 00000000000..d2c169e8844 --- /dev/null +++ b/tests/robotests/src/com/android/settings/deviceinfo/ManageStoragePreferenceControllerTest.java @@ -0,0 +1,99 @@ +/* + * 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.deviceinfo; + + +import android.content.Context; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceScreen; + +import com.android.settings.TestConfig; + +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.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +import java.util.ArrayList; +import java.util.List; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Answers.RETURNS_DEEP_STUBS; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(RobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class ManageStoragePreferenceControllerTest { + + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private Context mContext; + @Mock(answer = RETURNS_DEEP_STUBS) + private PreferenceScreen mScreen; + + private ManageStoragePreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mController = new ManageStoragePreferenceController(mContext); + } + + @Test + public void updateNonIndexableKey_prefUnavaiable_shouldUpdate() { + final List keys = new ArrayList<>(); + mController.updateNonIndexableKeys(keys); + + assertThat(keys).isNotEmpty(); + } + + @Test + public void updateNonIndexableKey_prefAvaiable_shouldNotUpdate() { + final List keys = new ArrayList<>(); + when(mContext.getResources().getBoolean( + com.android.settings.R.bool.config_storage_manager_settings_enabled)) + .thenReturn(true); + + mController.updateNonIndexableKeys(keys); + + assertThat(keys).isEmpty(); + } + + @Test + public void displayPref_prefAvaiable_shouldDisplay() { + when(mContext.getResources().getBoolean( + com.android.settings.R.bool.config_storage_manager_settings_enabled)) + .thenReturn(true); + + mController.displayPreference(mScreen); + + verify(mScreen, never()).removePreference(any(Preference.class)); + } + + @Test + public void displayPref_prefAvaiable_shouldNotDisplay() { + mController.displayPreference(mScreen); + + verify(mScreen).removePreference(any(Preference.class)); + } +} diff --git a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java new file mode 100644 index 00000000000..0aaec5a547c --- /dev/null +++ b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java @@ -0,0 +1,87 @@ +/* + * 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.testutils; + +import android.content.Context; + +import com.android.settings.core.instrumentation.MetricsFeatureProvider; +import com.android.settings.dashboard.DashboardFeatureProvider; +import com.android.settings.fuelgauge.PowerUsageFeatureProvider; +import com.android.settings.overlay.FeatureFactory; +import com.android.settings.overlay.SupportFeatureProvider; + +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * Test util to provide fake FeatureFactory. To use this factory, call {@code setupForTest} in + * {@code @Before} method of the test class. + */ +public class FakeFeatureFactory extends FeatureFactory { + + public final SupportFeatureProvider supportFeatureProvider; + public final MetricsFeatureProvider metricsFeatureProvider; + public final PowerUsageFeatureProvider powerUsageFeatureProvider; + public final DashboardFeatureProvider dashboardFeatureProvider; + + /** + * Call this in {@code @Before} method of the test class to use fake factory. + * + * @param context The context must be a deep mock. + */ + public static void setupForTest(Context context) { + sFactory = null; + when(context.getString(com.android.settings.R.string.config_featureFactory)) + .thenReturn(FakeFeatureFactory.class.getName()); + try { + Class c = FakeFeatureFactory.class; + when(context.getClassLoader().loadClass(anyString())).thenReturn(c); + } catch (ClassNotFoundException e) { + // Ignore. + } + } + + /** + * Used by reflection. Do not call directly. + */ + public FakeFeatureFactory() { + supportFeatureProvider = mock(SupportFeatureProvider.class); + metricsFeatureProvider = mock(MetricsFeatureProvider.class); + powerUsageFeatureProvider = mock(PowerUsageFeatureProvider.class); + dashboardFeatureProvider = mock(DashboardFeatureProvider.class); + } + + @Override + public SupportFeatureProvider getSupportFeatureProvider(Context context) { + return supportFeatureProvider; + } + + @Override + public MetricsFeatureProvider getMetricsFeatureProvider() { + return metricsFeatureProvider; + } + + @Override + public PowerUsageFeatureProvider getPowerUsageFeatureProvider() { + return powerUsageFeatureProvider; + } + + @Override + public DashboardFeatureProvider getDashboardFeatureProvider(Context context) { + return dashboardFeatureProvider; + } +} diff --git a/tests/robotests/src/com/android/settings/shadow/ShadowTextUtils.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowTextUtils.java similarity index 97% rename from tests/robotests/src/com/android/settings/shadow/ShadowTextUtils.java rename to tests/robotests/src/com/android/settings/testutils/shadow/ShadowTextUtils.java index 4a98f6a23c4..c6ed2faaee5 100644 --- a/tests/robotests/src/com/android/settings/shadow/ShadowTextUtils.java +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowTextUtils.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.settings.shadow; +package com.android.settings.testutils.shadow; import android.icu.util.ULocale; import android.os.SystemProperties; diff --git a/tests/robotests/src/com/android/settings/widget/RtlCompatibleViewPagerTest.java b/tests/robotests/src/com/android/settings/widget/RtlCompatibleViewPagerTest.java index b5213f1ead4..cce0f32f247 100644 --- a/tests/robotests/src/com/android/settings/widget/RtlCompatibleViewPagerTest.java +++ b/tests/robotests/src/com/android/settings/widget/RtlCompatibleViewPagerTest.java @@ -23,7 +23,7 @@ import android.view.View; import android.view.ViewGroup; import com.android.settings.TestConfig; -import com.android.settings.shadow.ShadowTextUtils; +import com.android.settings.testutils.shadow.ShadowTextUtils; import org.junit.Before; import org.junit.Test;