From 6269a92e162bb46bfd4c18d5760ab4a39bfd9782 Mon Sep 17 00:00:00 2001 From: ryanlwlin Date: Tue, 27 Apr 2021 20:03:21 +0800 Subject: [PATCH] Move Magnification Mode Settings to the main page We move the mode settings because currently there is only one item in the settings page. To fully test all logic, we don't use fragament anymore in the controllerTest, and test the interaction between the controller and the fragment in the test of these two fragments. Bug: 182992338 Test: atest ToggleScreenMagnificationPreferenceFragmentTest atest MagnificationModePreferenceControllerTest atest MagnificationSettingsFragmentTest manually test Change-Id: Ia6b0ea4f116f3215407637d7aeaddb8d8196d8fb --- res/values/styles.xml | 4 +- .../AccessibilityEditDialogUtils.java | 6 +- ...MagnificationModePreferenceController.java | 37 ++++-- .../MagnificationSettingsFragment.java | 25 +++-- ...ScreenMagnificationPreferenceFragment.java | 43 ++++++- ...ificationModePreferenceControllerTest.java | 105 +++++++----------- .../MagnificationSettingsFragmentTest.java | 63 ++++++++++- ...enMagnificationPreferenceFragmentTest.java | 98 +++++++++++++--- .../ShadowSettingsPreferenceFragment.java | 43 +++++++ 9 files changed, 317 insertions(+), 107 deletions(-) create mode 100644 tests/robotests/src/com/android/settings/testutils/shadow/ShadowSettingsPreferenceFragment.java diff --git a/res/values/styles.xml b/res/values/styles.xml index b27cc5de530..783a1487d17 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -715,8 +715,8 @@ parent="@*android:style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog"> match_parent 56dp - 8dp - 8dp + 8dp + 8dp ?android:attr/selectableItemBackground diff --git a/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java b/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java index 26c23137729..803550b8cc4 100644 --- a/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java +++ b/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java @@ -118,16 +118,16 @@ public class AccessibilityEditDialogUtils { * Method to show the magnification edit shortcut dialog in Magnification. * * @param context A valid context - * @param dialogTitle The title of magnify edit shortcut dialog * @param positiveBtnListener The positive button listener * @return A magnification edit shortcut dialog in Magnification */ public static Dialog createMagnificationSwitchShortcutDialog(Context context, - CharSequence dialogTitle, CustomButtonsClickListener positiveBtnListener) { + CustomButtonsClickListener positiveBtnListener) { final View contentView = createSwitchShortcutDialogContentView(context); final AlertDialog alertDialog = new AlertDialog.Builder(context) .setView(contentView) - .setTitle(dialogTitle) + .setTitle(context.getString( + R.string.accessibility_magnification_switch_shortcut_title)) .create(); setCustomButtonsClickListener(alertDialog, contentView, positiveBtnListener, /* negativeBtnListener= */ null); diff --git a/src/com/android/settings/accessibility/MagnificationModePreferenceController.java b/src/com/android/settings/accessibility/MagnificationModePreferenceController.java index 67b68ccb93d..ef858345cea 100644 --- a/src/com/android/settings/accessibility/MagnificationModePreferenceController.java +++ b/src/com/android/settings/accessibility/MagnificationModePreferenceController.java @@ -47,6 +47,7 @@ import com.android.settings.accessibility.MagnificationCapabilities.Magnificatio import com.android.settings.core.BasePreferenceController; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnCreate; +import com.android.settingslib.core.lifecycle.events.OnResume; import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState; import java.util.ArrayList; @@ -55,8 +56,9 @@ import java.util.StringJoiner; /** Controller that shows the magnification area mode summary and the preference click behavior. */ public class MagnificationModePreferenceController extends BasePreferenceController implements - DialogCreatable, LifecycleObserver, OnCreate, OnSaveInstanceState { + DialogCreatable, LifecycleObserver, OnCreate, OnResume, OnSaveInstanceState { + static final String PREF_KEY = "screen_magnification_mode"; private static final int DIALOG_ID_BASE = 10; @VisibleForTesting static final int DIALOG_MAGNIFICATION_MODE = DIALOG_ID_BASE + 1; @@ -68,7 +70,7 @@ public class MagnificationModePreferenceController extends BasePreferenceControl private static final String TAG = "MagnificationModePreferenceController"; private static final char COMPONENT_NAME_SEPARATOR = ':'; - private MagnificationSettingsFragment mParentFragment; + private DialogHelper mDialogHelper; // The magnification mode in the dialog. private int mMode = MagnificationMode.NONE; private Preference mModePreference; @@ -121,7 +123,7 @@ public class MagnificationModePreferenceController extends BasePreferenceControl mModePreference = screen.findPreference(getPreferenceKey()); mModePreference.setOnPreferenceClickListener(preference -> { mMode = MagnificationCapabilities.getCapabilities(mContext); - mParentFragment.showDialog(DIALOG_MAGNIFICATION_MODE); + mDialogHelper.showDialog(DIALOG_MAGNIFICATION_MODE); return true; }); } @@ -131,8 +133,12 @@ public class MagnificationModePreferenceController extends BasePreferenceControl outState.putInt(EXTRA_MODE, mMode); } - public void setParentFragment(MagnificationSettingsFragment parentFragment) { - mParentFragment = parentFragment; + /** + * Sets {@link DialogHelper} used to show the dialog. + */ + public void setDialogHelper(DialogHelper dialogHelper) { + mDialogHelper = dialogHelper; + mDialogHelper.setDialogDelegate(this); } @Override @@ -207,7 +213,7 @@ public class MagnificationModePreferenceController extends BasePreferenceControl } mMode = modeInfo.mMagnificationMode; if (isTripleTapEnabled(mContext) && mMode != MagnificationMode.FULLSCREEN) { - mParentFragment.showDialog(DIALOG_MAGNIFICATION_SWITCH_SHORTCUT); + mDialogHelper.showDialog(DIALOG_MAGNIFICATION_SWITCH_SHORTCUT); } } @@ -229,9 +235,7 @@ public class MagnificationModePreferenceController extends BasePreferenceControl } private Dialog createMagnificationShortCutConfirmDialog() { - final String title = mContext.getString( - R.string.accessibility_magnification_switch_shortcut_title); - return AccessibilityEditDialogUtils.createMagnificationSwitchShortcutDialog(mContext, title, + return AccessibilityEditDialogUtils.createMagnificationSwitchShortcutDialog(mContext, this::onSwitchShortcutDialogButtonClicked); } @@ -267,6 +271,21 @@ public class MagnificationModePreferenceController extends BasePreferenceControl joiner.toString()); } + // TODO(b/186731461): Remove it when this controller is used in DashBoardFragment only. + @Override + public void onResume() { + updateState(mModePreference); + } + + + /** + * An interface to help the delegate to show the dialog. It will be injected to the delegate. + */ + interface DialogHelper extends DialogCreatable { + void showDialog(int dialogId); + void setDialogDelegate(DialogCreatable delegate); + } + @VisibleForTesting static class MagnificationModeInfo extends ItemInfoArrayAdapter.ItemInfo { @MagnificationMode diff --git a/src/com/android/settings/accessibility/MagnificationSettingsFragment.java b/src/com/android/settings/accessibility/MagnificationSettingsFragment.java index 0af40fdca45..a898076033c 100644 --- a/src/com/android/settings/accessibility/MagnificationSettingsFragment.java +++ b/src/com/android/settings/accessibility/MagnificationSettingsFragment.java @@ -20,6 +20,7 @@ import android.app.Dialog; import android.app.settings.SettingsEnums; import android.content.Context; +import com.android.settings.DialogCreatable; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.search.BaseSearchIndexProvider; @@ -27,11 +28,13 @@ import com.android.settingslib.search.SearchIndexable; /** Settings page for magnification. */ @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC) -public class MagnificationSettingsFragment extends DashboardFragment { +public class MagnificationSettingsFragment extends DashboardFragment implements + MagnificationModePreferenceController.DialogHelper { private static final String TAG = "MagnificationSettingsFragment"; - private MagnificationModePreferenceController mMagnificationModePreferenceController; + private DialogCreatable mDialogDelegate; + @Override public int getMetricsCategory() { @@ -41,19 +44,23 @@ public class MagnificationSettingsFragment extends DashboardFragment { @Override public void onAttach(Context context) { super.onAttach(context); - mMagnificationModePreferenceController = use(MagnificationModePreferenceController.class); - mMagnificationModePreferenceController.setParentFragment(this); + use(MagnificationModePreferenceController.class).setDialogHelper(this); } @Override - protected void showDialog(int dialogId) { + public void showDialog(int dialogId) { super.showDialog(dialogId); } + @Override + public void setDialogDelegate(DialogCreatable delegate) { + mDialogDelegate = delegate; + } + @Override public int getDialogMetricsCategory(int dialogId) { - if (mMagnificationModePreferenceController != null) { - return mMagnificationModePreferenceController.getDialogMetricsCategory(dialogId); + if (mDialogDelegate != null) { + return mDialogDelegate.getDialogMetricsCategory(dialogId); } return 0; } @@ -70,8 +77,8 @@ public class MagnificationSettingsFragment extends DashboardFragment { @Override public Dialog onCreateDialog(int dialogId) { - if (mMagnificationModePreferenceController != null) { - final Dialog dialog = mMagnificationModePreferenceController.onCreateDialog(dialogId); + if (mDialogDelegate != null) { + final Dialog dialog = mDialogDelegate.onCreateDialog(dialogId); if (dialog != null) { return dialog; } diff --git a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java index 738d284bda0..7c03ba9e9a8 100644 --- a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java @@ -42,6 +42,7 @@ import androidx.preference.Preference; import androidx.preference.PreferenceCategory; import com.android.internal.annotations.VisibleForTesting; +import com.android.settings.DialogCreatable; import com.android.settings.R; import com.android.settings.accessibility.AccessibilityUtil.UserShortcutType; @@ -55,7 +56,8 @@ import java.util.StringJoiner; * and does not have toggle bar to turn on service to use. */ public class ToggleScreenMagnificationPreferenceFragment extends - ToggleFeaturePreferenceFragment { + ToggleFeaturePreferenceFragment implements + MagnificationModePreferenceController.DialogHelper { // TODO(b/147021230): Move duplicated functions with android/internal/accessibility into util. private TouchExplorationStateChangeListener mTouchExplorationStateChangeListener; @@ -67,6 +69,9 @@ public class ToggleScreenMagnificationPreferenceFragment extends private static final TextUtils.SimpleStringSplitter sStringColonSplitter = new TextUtils.SimpleStringSplitter(COMPONENT_NAME_SEPARATOR); + private MagnificationModePreferenceController mModePreferenceController; + private DialogCreatable mDialogDelegate; + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -108,6 +113,12 @@ public class ToggleScreenMagnificationPreferenceFragment extends @Override public Dialog onCreateDialog(int dialogId) { + if (mDialogDelegate != null) { + final Dialog dialog = mDialogDelegate.onCreateDialog(dialogId); + if (dialog != null) { + return dialog; + } + } final AlertDialog dialog; switch (dialogId) { case DialogEnums.GESTURE_NAVIGATION_TUTORIAL: @@ -128,20 +139,35 @@ public class ToggleScreenMagnificationPreferenceFragment extends @Override protected void initSettingsPreference() { + // If the device doesn't support magnification area, it should hide the settings preference. if (!getContext().getResources().getBoolean( com.android.internal.R.bool.config_magnification_area)) { return; } mSettingsPreference = new Preference(getPrefContext()); - mSettingsPreference.setTitle(R.string.accessibility_menu_item_settings); - // TODO(b/177371954): "magnification area" should be brought up to the highest level of the - // settings UI so that it appears below "shortcut" to replace "settings. - mSettingsPreference.setFragment(MagnificationSettingsFragment.class.getName()); + mSettingsPreference.setTitle(R.string.accessibility_magnification_mode_title); + mSettingsPreference.setKey(MagnificationModePreferenceController.PREF_KEY); mSettingsPreference.setPersistent(false); final PreferenceCategory generalCategory = findPreference(KEY_GENERAL_CATEGORY); generalCategory.addPreference(mSettingsPreference); + + mModePreferenceController = new MagnificationModePreferenceController(getContext(), + MagnificationModePreferenceController.PREF_KEY); + mModePreferenceController.setDialogHelper(this); + getSettingsLifecycle().addObserver(mModePreferenceController); + mModePreferenceController.displayPreference(getPreferenceScreen()); + } + + @Override + public void showDialog(int dialogId) { + super.showDialog(dialogId); + } + + @Override + public void setDialogDelegate(DialogCreatable delegate) { + mDialogDelegate = delegate; } @Override @@ -278,6 +304,13 @@ public class ToggleScreenMagnificationPreferenceFragment extends @Override public int getDialogMetricsCategory(int dialogId) { + if (mDialogDelegate != null) { + final int category = mDialogDelegate.getDialogMetricsCategory(dialogId); + if (category != 0) { + return category; + } + } + switch (dialogId) { case DialogEnums.GESTURE_NAVIGATION_TUTORIAL: return SettingsEnums.DIALOG_TOGGLE_SCREEN_MAGNIFICATION_GESTURE_NAVIGATION; diff --git a/tests/robotests/src/com/android/settings/accessibility/MagnificationModePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/MagnificationModePreferenceControllerTest.java index 4b053ab457b..d4b7ea038fe 100644 --- a/tests/robotests/src/com/android/settings/accessibility/MagnificationModePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/MagnificationModePreferenceControllerTest.java @@ -16,8 +16,6 @@ package com.android.settings.accessibility; -import static androidx.lifecycle.Lifecycle.Event.ON_CREATE; - import static com.android.settings.accessibility.AccessibilityEditDialogUtils.CustomButton; import static com.android.settings.accessibility.MagnificationCapabilities.MagnificationMode; import static com.android.settings.accessibility.MagnificationModePreferenceController.MagnificationModeInfo; @@ -25,41 +23,35 @@ import static com.android.settings.accessibility.MagnificationPreferenceFragment import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; +import android.app.Dialog; import android.content.Context; import android.os.Bundle; import android.provider.Settings; import android.widget.AdapterView; import android.widget.ListView; -import androidx.fragment.app.FragmentManager; import androidx.preference.Preference; +import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; +import com.android.settings.DialogCreatable; import com.android.settings.R; -import com.android.settings.testutils.shadow.ShadowDashboardFragment; -import com.android.settingslib.core.AbstractPreferenceController; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Answers; -import org.mockito.Mock; +import org.mockito.Spy; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; -import org.robolectric.annotation.Config; - +/** Tests for {@link MagnificationModePreferenceController}. */ @RunWith(RobolectricTestRunner.class) -@Config(shadows = ShadowDashboardFragment.class) public class MagnificationModePreferenceControllerTest { private static final String PREF_KEY = "screen_magnification_mode"; private static final int MAGNIFICATION_MODE_DEFAULT = MagnificationMode.ALL; @@ -67,39 +59,38 @@ public class MagnificationModePreferenceControllerTest { @Rule public MockitoRule mocks = MockitoJUnit.rule(); - @Mock private PreferenceScreen mScreen; private Context mContext; - private TestMagnificationSettingsFragment mFragment; private MagnificationModePreferenceController mController; private Preference mModePreference; + @Spy + private TestDialogHelper mDialogHelper = new TestDialogHelper(); @Before public void setUp() { mContext = RuntimeEnvironment.application; - mController = new MagnificationModePreferenceController(mContext, PREF_KEY); - mScreen = spy(new PreferenceScreen(mContext, null)); + final PreferenceManager preferenceManager = new PreferenceManager(mContext); + mScreen = preferenceManager.createPreferenceScreen(mContext); mModePreference = new Preference(mContext); - mFragment = spy(new TestMagnificationSettingsFragment(mController)); - - doReturn(mScreen).when(mFragment).getPreferenceScreen(); - doReturn(mock(FragmentManager.class, Answers.RETURNS_DEEP_STUBS)).when( - mFragment).getChildFragmentManager(); - mContext.setTheme(R.style.Theme_AppCompat); - doReturn(mModePreference).when(mScreen).findPreference(PREF_KEY); + mModePreference.setKey(PREF_KEY); + mScreen.addPreference(mModePreference); MagnificationCapabilities.setCapabilities(mContext, MAGNIFICATION_MODE_DEFAULT); + mController = new MagnificationModePreferenceController(mContext, PREF_KEY); showPreferenceOnTheScreen(null); - mModePreference.getOnPreferenceClickListener().onPreferenceClick(mModePreference); } @Test - public void settingsModeIsDefault_checkedModeInDialogIsDefault() { + public void clickPreference_settingsModeIsDefault_checkedModeInDialogIsDefault() { + mModePreference.getOnPreferenceClickListener().onPreferenceClick(mModePreference); + assertThat(getCheckedModeFromDialog()).isEqualTo( MAGNIFICATION_MODE_DEFAULT); } @Test public void choseModeIsDifferentFromInSettings_checkedModeInDialogIsExpected() { + mModePreference.getOnPreferenceClickListener().onPreferenceClick(mModePreference); + performItemClickWith(MagnificationMode.WINDOW); assertThat(getCheckedModeFromDialog()).isEqualTo(MagnificationMode.WINDOW); @@ -107,11 +98,11 @@ public class MagnificationModePreferenceControllerTest { @Test public void dialogIsReCreated_settingsModeIsAllAndChoseWindowMode_checkedModeIsWindow() { - showPreferenceOnTheScreen(null); + mModePreference.getOnPreferenceClickListener().onPreferenceClick(mModePreference); performItemClickWith(MagnificationMode.WINDOW); reshowPreferenceOnTheScreen(); - mFragment.showDialog(MagnificationModePreferenceController.DIALOG_MAGNIFICATION_MODE); + mDialogHelper.showDialog(MagnificationModePreferenceController.DIALOG_MAGNIFICATION_MODE); assertThat(getCheckedModeFromDialog()).isEqualTo( MagnificationMode.WINDOW); @@ -120,24 +111,22 @@ public class MagnificationModePreferenceControllerTest { @Test public void chooseWindowMode_tripleTapEnabled_showSwitchShortcutDialog() { enableTripleTap(); + mModePreference.getOnPreferenceClickListener().onPreferenceClick(mModePreference); performItemClickWith(MagnificationMode.WINDOW); - verify(mFragment).showDialog( + verify(mDialogHelper).showDialog( MagnificationModePreferenceController.DIALOG_MAGNIFICATION_SWITCH_SHORTCUT); } @Test public void chooseModeAll_modeAllInSettingsAndTripleTapEnabled_notShowShortcutDialog() { enableTripleTap(); - MagnificationCapabilities.setCapabilities(mContext, - Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL); - mFragment.onCreate(Bundle.EMPTY); - mFragment.onCreateDialog(MagnificationModePreferenceController.DIALOG_MAGNIFICATION_MODE); + mModePreference.getOnPreferenceClickListener().onPreferenceClick(mModePreference); performItemClickWith(MagnificationMode.ALL); - verify(mFragment, never()).showDialog( + verify(mDialogHelper, never()).showDialog( MagnificationModePreferenceController.DIALOG_MAGNIFICATION_SWITCH_SHORTCUT); } @@ -206,48 +195,38 @@ public class MagnificationModePreferenceControllerTest { private void reshowPreferenceOnTheScreen() { final Bundle bundle = new Bundle(); - mFragment.onSaveInstanceState(bundle); - mFragment.onDetach(); + mController.onSaveInstanceState(bundle); showPreferenceOnTheScreen(bundle); - } private void showPreferenceOnTheScreen(Bundle savedInstanceState) { - mFragment.onAttach(mContext); - mFragment.onCreate(savedInstanceState); + mController.setDialogHelper(mDialogHelper); + mController.onCreate(savedInstanceState); mController.displayPreference(mScreen); } - private static class TestMagnificationSettingsFragment extends MagnificationSettingsFragment { - - TestMagnificationSettingsFragment(AbstractPreferenceController... controllers) { - // Add given controllers for injection. Although controllers will be added in - // onAttach(). use(AbstractPreferenceController.class) returns the first added one. - for (int i = 0; i < controllers.length; i++) { - addPreferenceController(controllers[i]); - } - } + private static class TestDialogHelper implements DialogCreatable, + MagnificationModePreferenceController.DialogHelper { + private DialogCreatable mDialogDelegate; @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - // Simulate the observable behaviour because ShadowDashFragment doesn't call - // super.create. - - getSettingsLifecycle().onCreate(icicle); - getSettingsLifecycle().handleLifecycleEvent(ON_CREATE); - } - - @Override - protected void showDialog(int dialogId) { - super.showDialog(dialogId); - // In current fragment architecture, we could assume onCreateDialog is called directly. + public void showDialog(int dialogId) { onCreateDialog(dialogId); } @Override - protected void addPreferenceController(AbstractPreferenceController controller) { - super.addPreferenceController(controller); + public void setDialogDelegate(DialogCreatable delegate) { + mDialogDelegate = delegate; + } + + @Override + public Dialog onCreateDialog(int dialogId) { + return mDialogDelegate.onCreateDialog(dialogId); + } + + @Override + public int getDialogMetricsCategory(int dialogId) { + return mDialogDelegate.getDialogMetricsCategory(dialogId); } } } diff --git a/tests/robotests/src/com/android/settings/accessibility/MagnificationSettingsFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/MagnificationSettingsFragmentTest.java index 789362b6de4..73d29cf4ef4 100644 --- a/tests/robotests/src/com/android/settings/accessibility/MagnificationSettingsFragmentTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/MagnificationSettingsFragmentTest.java @@ -18,23 +18,78 @@ package com.android.settings.accessibility; import static com.google.common.truth.Truth.assertThat; -import android.content.Context; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.RETURNS_DEEP_STUBS; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import android.content.Context; +import android.os.Bundle; + +import androidx.fragment.app.FragmentManager; +import androidx.preference.PreferenceScreen; import androidx.test.core.app.ApplicationProvider; +import com.android.settings.DialogCreatable; import com.android.settings.R; import com.android.settings.testutils.XmlTestUtils; +import com.android.settings.testutils.shadow.ShadowDashboardFragment; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Answers; import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; import java.util.List; /** Tests for {@link MagnificationSettingsFragment} */ @RunWith(RobolectricTestRunner.class) +@Config(shadows = ShadowDashboardFragment.class) public class MagnificationSettingsFragmentTest { + private final Context mContext = ApplicationProvider.getApplicationContext(); + private MagnificationSettingsFragment mFragment; + private PreferenceScreen mScreen; + + @Before + public void setup() { + mContext.setTheme(R.style.Theme_AppCompat); + mFragment = spy(new MagnificationSettingsFragment()); + mScreen = new PreferenceScreen(mContext, null); + + doReturn(mContext).when(mFragment).getContext(); + doReturn(mScreen).when(mFragment).getPreferenceScreen(); + doReturn(mock(FragmentManager.class, Answers.RETURNS_DEEP_STUBS)).when( + mFragment).getChildFragmentManager(); + + } + + @Test + public void showPreferenceOnTheScreen_setDialogHelper() { + showPreferenceOnTheScreen(null); + + verify(mFragment).setDialogDelegate(any(MagnificationModePreferenceController.class)); + } + + @Test + public void onCreateDialog_setDialogDelegate_invokeDialogDelegate() { + final DialogCreatable dialogDelegate = mock(DialogCreatable.class, RETURNS_DEEP_STUBS); + when(dialogDelegate.getDialogMetricsCategory(anyInt())).thenReturn(1); + + mFragment.setDialogDelegate(dialogDelegate); + + mFragment.onCreateDialog(1); + mFragment.getDialogMetricsCategory(1); + + verify(dialogDelegate).onCreateDialog(1); + verify(dialogDelegate).getDialogMetricsCategory(1); + } @Test public void getNonIndexableKeys_existInXmlLayout() { @@ -46,4 +101,10 @@ public class MagnificationSettingsFragmentTest { R.xml.accessibility_magnification_service_settings); assertThat(keys).containsAtLeastElementsIn(niks); } + + private void showPreferenceOnTheScreen(Bundle savedInstanceState) { + mFragment.onAttach(mContext); + mFragment.onCreate(savedInstanceState); + mFragment.onResume(); + } } diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentTest.java index 0ed6747e517..c8ad94faecb 100644 --- a/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentTest.java @@ -23,9 +23,13 @@ import static com.android.settings.accessibility.ToggleFeaturePreferenceFragment import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.RETURNS_DEEP_STUBS; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.ComponentName; @@ -34,6 +38,7 @@ import android.content.DialogInterface; import android.content.res.Resources; import android.os.Bundle; import android.provider.Settings; +import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -41,21 +46,28 @@ import android.view.ViewGroup; import androidx.annotation.XmlRes; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.FragmentActivity; +import androidx.preference.Preference; import androidx.preference.PreferenceManager; +import androidx.preference.PreferenceScreen; import androidx.test.core.app.ApplicationProvider; +import com.android.settings.DialogCreatable; import com.android.settings.R; import com.android.settings.testutils.shadow.ShadowFragment; +import com.android.settings.testutils.shadow.ShadowSettingsPreferenceFragment; +import com.android.settingslib.core.lifecycle.Lifecycle; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; @RunWith(RobolectricTestRunner.class) +@Config(shadows = {ShadowSettingsPreferenceFragment.class}) public class ToggleScreenMagnificationPreferenceFragmentTest { private static final String PLACEHOLDER_PACKAGE_NAME = "com.mock.example"; @@ -79,9 +91,6 @@ public class ToggleScreenMagnificationPreferenceFragmentTest { private Context mContext; private Resources mResources; - @Mock - private PreferenceManager mPreferenceManager; - @Mock private FragmentActivity mActivity; @Before @@ -89,14 +98,11 @@ public class ToggleScreenMagnificationPreferenceFragmentTest { MockitoAnnotations.initMocks(this); mContext = spy(ApplicationProvider.getApplicationContext()); - mFragment = spy(new TestToggleScreenMagnificationPreferenceFragment()); - when(mFragment.getPreferenceManager()).thenReturn(mPreferenceManager); - when(mFragment.getPreferenceManager().getContext()).thenReturn(mContext); - when(mFragment.getContext()).thenReturn(mContext); + mActivity = Robolectric.setupActivity(FragmentActivity.class); + mFragment = spy(new TestToggleScreenMagnificationPreferenceFragment(mContext)); mResources = spy(mContext.getResources()); when(mContext.getResources()).thenReturn(mResources); when(mFragment.getContext().getResources()).thenReturn(mResources); - doReturn(null).when(mFragment).getPreferenceScreen(); doReturn(mActivity).when(mFragment).getActivity(); } @@ -257,15 +263,38 @@ public class ToggleScreenMagnificationPreferenceFragmentTest { } @Test - public void initSettingsPreference_notSupportsMagnificationArea_settingsPreferenceIsNull() { + public void onCreateView_notSupportsMagnificationArea_settingsPreferenceIsNull() { when(mResources.getBoolean( com.android.internal.R.bool.config_magnification_area)) .thenReturn(false); - mFragment.initSettingsPreference(); + + mFragment.onCreateView(LayoutInflater.from(mContext), mock(ViewGroup.class), Bundle.EMPTY); assertThat(mFragment.mSettingsPreference).isNull(); } + @Test + public void onCreateView_setDialogDelegateAndAddTheControllerToLifeCycleObserver() { + mFragment.onCreateView(LayoutInflater.from(mContext), mock(ViewGroup.class), Bundle.EMPTY); + + verify(mFragment).setDialogDelegate(any(MagnificationModePreferenceController.class)); + verify(mFragment.mSpyLifeyCycle).addObserver( + any(MagnificationModePreferenceController.class)); + } + + @Test + public void onCreateDialog_setDialogDelegate_invokeDialogDelegate() { + final DialogCreatable dialogDelegate = mock(DialogCreatable.class, RETURNS_DEEP_STUBS); + when(dialogDelegate.getDialogMetricsCategory(anyInt())).thenReturn(1); + mFragment.setDialogDelegate(dialogDelegate); + + mFragment.onCreateDialog(1); + mFragment.getDialogMetricsCategory(1); + + verify(dialogDelegate).onCreateDialog(1); + verify(dialogDelegate).getDialogMetricsCategory(1); + } + private void putStringIntoSettings(String key, String componentName) { Settings.Secure.putString(mContext.getContentResolver(), key, componentName); } @@ -291,8 +320,25 @@ public class ToggleScreenMagnificationPreferenceFragmentTest { private void callEmptyOnClicked(DialogInterface dialog, int which) {} - public static class TestToggleScreenMagnificationPreferenceFragment + /** + * a test fragment that initializes PreferenceScreen for testing. + */ + static class TestToggleScreenMagnificationPreferenceFragment extends ToggleScreenMagnificationPreferenceFragment { + + private final Lifecycle mSpyLifeyCycle = Mockito.mock(Lifecycle.class); + + private final Context mContext; + private final PreferenceManager mPreferenceManager; + + TestToggleScreenMagnificationPreferenceFragment(Context context) { + super(); + mContext = context; + mPreferenceManager = new PreferenceManager(context); + mPreferenceManager.setPreferences(mPreferenceManager.createPreferenceScreen(context)); + setArguments(new Bundle()); + } + @Override protected void onPreferenceToggled(String preferenceKey, boolean enabled) { } @@ -313,9 +359,21 @@ public class ToggleScreenMagnificationPreferenceFragmentTest { } @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - return mock(View.class); + public PreferenceScreen getPreferenceScreen() { + return mPreferenceManager.getPreferenceScreen(); + } + + @Override + public T findPreference(CharSequence key) { + if (TextUtils.isEmpty(key)) { + return null; + } + return getPreferenceScreen().findPreference(key); + } + + @Override + public PreferenceManager getPreferenceManager() { + return mPreferenceManager; } @Override @@ -337,5 +395,15 @@ public class ToggleScreenMagnificationPreferenceFragmentTest { protected void updateShortcutPreference() { // UI related function, do nothing in tests } + + @Override + public Lifecycle getSettingsLifecycle() { + return mSpyLifeyCycle; + } + + @Override + public Context getContext() { + return mContext; + } } } diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowSettingsPreferenceFragment.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowSettingsPreferenceFragment.java new file mode 100644 index 00000000000..27fca621930 --- /dev/null +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowSettingsPreferenceFragment.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2021 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.shadow; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.android.settings.SettingsPreferenceFragment; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; + +/** + * Shadow of {@link SettingsPreferenceFragment}. + * + * Override the {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}} to skip inflating + * a View from a xml. + */ +@Implements(SettingsPreferenceFragment.class) +public class ShadowSettingsPreferenceFragment extends ShadowFragment { + + @Implementation + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return container; + } +}