1 /*
2  * Copyright (C) 2019 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.accessibility;
18 
19 import static com.android.settings.accessibility.AccessibilityDialogUtils.CustomButton;
20 import static com.android.settings.accessibility.MagnificationCapabilities.MagnificationMode;
21 import static com.android.settings.accessibility.MagnificationModePreferenceController.MagnificationModeInfo;
22 import static com.android.settings.accessibility.MagnificationPreferenceFragment.ON;
23 
24 import static com.google.common.truth.Truth.assertThat;
25 
26 import static org.mockito.Mockito.never;
27 import static org.mockito.Mockito.verify;
28 
29 import android.app.Dialog;
30 import android.content.Context;
31 import android.os.Bundle;
32 import android.provider.Settings;
33 import android.widget.AdapterView;
34 import android.widget.ListView;
35 
36 import androidx.preference.Preference;
37 import androidx.preference.PreferenceManager;
38 import androidx.preference.PreferenceScreen;
39 
40 import com.android.settings.DialogCreatable;
41 import com.android.settings.R;
42 
43 import org.junit.Before;
44 import org.junit.Rule;
45 import org.junit.Test;
46 import org.junit.runner.RunWith;
47 import org.mockito.Spy;
48 import org.mockito.junit.MockitoJUnit;
49 import org.mockito.junit.MockitoRule;
50 import org.robolectric.RobolectricTestRunner;
51 import org.robolectric.RuntimeEnvironment;
52 
53 /** Tests for {@link MagnificationModePreferenceController}. */
54 @RunWith(RobolectricTestRunner.class)
55 public class MagnificationModePreferenceControllerTest {
56     private static final String PREF_KEY = "screen_magnification_mode";
57     private static final int MAGNIFICATION_MODE_DEFAULT = MagnificationMode.ALL;
58 
59     @Rule
60     public MockitoRule mocks = MockitoJUnit.rule();
61 
62     private PreferenceScreen mScreen;
63     private Context mContext;
64     private MagnificationModePreferenceController mController;
65     private Preference mModePreference;
66     @Spy
67     private TestDialogHelper mDialogHelper = new TestDialogHelper();
68 
69     @Before
setUp()70     public void setUp() {
71         mContext = RuntimeEnvironment.application;
72         final PreferenceManager preferenceManager = new PreferenceManager(mContext);
73         mScreen = preferenceManager.createPreferenceScreen(mContext);
74         mModePreference = new Preference(mContext);
75         mModePreference.setKey(PREF_KEY);
76         mScreen.addPreference(mModePreference);
77         MagnificationCapabilities.setCapabilities(mContext, MAGNIFICATION_MODE_DEFAULT);
78         mController = new MagnificationModePreferenceController(mContext, PREF_KEY);
79         showPreferenceOnTheScreen(null);
80     }
81 
82     @Test
clickPreference_settingsModeIsDefault_checkedModeInDialogIsDefault()83     public void clickPreference_settingsModeIsDefault_checkedModeInDialogIsDefault() {
84         mModePreference.getOnPreferenceClickListener().onPreferenceClick(mModePreference);
85 
86         assertThat(getCheckedModeFromDialog()).isEqualTo(
87                 MAGNIFICATION_MODE_DEFAULT);
88     }
89 
90     @Test
choseModeIsDifferentFromInSettings_checkedModeInDialogIsExpected()91     public void choseModeIsDifferentFromInSettings_checkedModeInDialogIsExpected() {
92         mModePreference.getOnPreferenceClickListener().onPreferenceClick(mModePreference);
93 
94         performItemClickWith(MagnificationMode.WINDOW);
95 
96         assertThat(getCheckedModeFromDialog()).isEqualTo(MagnificationMode.WINDOW);
97     }
98 
99     @Test
dialogIsReCreated_settingsModeIsAllAndChoseWindowMode_checkedModeIsWindow()100     public void dialogIsReCreated_settingsModeIsAllAndChoseWindowMode_checkedModeIsWindow() {
101         mModePreference.getOnPreferenceClickListener().onPreferenceClick(mModePreference);
102         performItemClickWith(MagnificationMode.WINDOW);
103 
104         reshowPreferenceOnTheScreen();
105         mDialogHelper.showDialog(MagnificationModePreferenceController.DIALOG_MAGNIFICATION_MODE);
106 
107         assertThat(getCheckedModeFromDialog()).isEqualTo(
108                 MagnificationMode.WINDOW);
109     }
110 
111     @Test
chooseWindowMode_tripleTapEnabled_showSwitchShortcutDialog()112     public void chooseWindowMode_tripleTapEnabled_showSwitchShortcutDialog() {
113         enableTripleTap();
114         mModePreference.getOnPreferenceClickListener().onPreferenceClick(mModePreference);
115 
116         performItemClickWith(MagnificationMode.WINDOW);
117 
118         verify(mDialogHelper).showDialog(
119                 MagnificationModePreferenceController.DIALOG_MAGNIFICATION_SWITCH_SHORTCUT);
120     }
121 
122     @Test
chooseModeAll_modeAllInSettingsAndTripleTapEnabled_notShowShortcutDialog()123     public void chooseModeAll_modeAllInSettingsAndTripleTapEnabled_notShowShortcutDialog() {
124         enableTripleTap();
125         mModePreference.getOnPreferenceClickListener().onPreferenceClick(mModePreference);
126 
127         performItemClickWith(MagnificationMode.ALL);
128 
129         verify(mDialogHelper, never()).showDialog(
130                 MagnificationModePreferenceController.DIALOG_MAGNIFICATION_SWITCH_SHORTCUT);
131     }
132 
133     @Test
onSwitchShortcutDialogPositiveButtonClicked_TripleTapEnabled_TripleTapDisabled()134     public void onSwitchShortcutDialogPositiveButtonClicked_TripleTapEnabled_TripleTapDisabled() {
135         enableTripleTap();
136 
137         mController.onSwitchShortcutDialogButtonClicked(CustomButton.POSITIVE);
138 
139         assertThat(MagnificationModePreferenceController.isTripleTapEnabled(mContext)).isFalse();
140     }
141 
142     @Test
getSummary_saveWindowScreen_shouldReturnWindowScreenSummary()143     public void getSummary_saveWindowScreen_shouldReturnWindowScreenSummary() {
144         MagnificationCapabilities.setCapabilities(mContext, MagnificationMode.WINDOW);
145 
146         assertThat(mController.getSummary())
147                 .isEqualTo(mContext.getString(
148                         R.string.accessibility_magnification_area_settings_window_screen_summary));
149     }
150 
151     @Test
getSummary_saveAll_shouldReturnAllSummary()152     public void getSummary_saveAll_shouldReturnAllSummary() {
153         MagnificationCapabilities.setCapabilities(mContext, MagnificationMode.ALL);
154 
155         assertThat(mController.getSummary())
156                 .isEqualTo(mContext.getString(
157                         R.string.accessibility_magnification_area_settings_all_summary));
158     }
159 
getCheckedModeFromDialog()160     private int getCheckedModeFromDialog() {
161         final ListView listView = mController.mMagnificationModesListView;
162         assertThat(listView).isNotNull();
163 
164         final int checkedPosition = listView.getCheckedItemPosition();
165         final MagnificationModeInfo modeInfo =
166                 (MagnificationModeInfo) listView.getAdapter().getItem(checkedPosition);
167         return modeInfo.mMagnificationMode;
168     }
169 
performItemClickWith(@agnificationMode int mode)170     private void performItemClickWith(@MagnificationMode int mode) {
171         final ListView listView = mController.mMagnificationModesListView;
172         assertThat(listView).isNotNull();
173 
174         int modeIndex = AdapterView.NO_ID;
175         // Index 0 is header.
176         for (int i = 1; i < listView.getAdapter().getCount(); i++) {
177             final MagnificationModeInfo modeInfo =
178                     (MagnificationModeInfo) listView.getAdapter().getItem(i);
179             if (modeInfo.mMagnificationMode == mode) {
180                 modeIndex = i;
181                 break;
182             }
183         }
184         if (modeIndex == AdapterView.NO_ID) {
185             throw new RuntimeException("The mode is not in the list.");
186         }
187 
188         listView.performItemClick(listView.getChildAt(modeIndex), modeIndex, modeIndex);
189     }
190 
enableTripleTap()191     private void enableTripleTap() {
192         Settings.Secure.putInt(mContext.getContentResolver(),
193                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, ON);
194     }
195 
reshowPreferenceOnTheScreen()196     private void reshowPreferenceOnTheScreen() {
197         final Bundle bundle = new Bundle();
198         mController.onSaveInstanceState(bundle);
199         showPreferenceOnTheScreen(bundle);
200     }
201 
showPreferenceOnTheScreen(Bundle savedInstanceState)202     private void showPreferenceOnTheScreen(Bundle savedInstanceState) {
203         mController.setDialogHelper(mDialogHelper);
204         mController.onCreate(savedInstanceState);
205         mController.displayPreference(mScreen);
206     }
207 
208     private static class TestDialogHelper implements DialogCreatable,
209             MagnificationModePreferenceController.DialogHelper {
210         private DialogCreatable mDialogDelegate;
211 
212         @Override
showDialog(int dialogId)213         public void showDialog(int dialogId) {
214             onCreateDialog(dialogId);
215         }
216 
217         @Override
setDialogDelegate(DialogCreatable delegate)218         public void setDialogDelegate(DialogCreatable delegate) {
219             mDialogDelegate = delegate;
220         }
221 
222         @Override
onCreateDialog(int dialogId)223         public Dialog onCreateDialog(int dialogId) {
224             return mDialogDelegate.onCreateDialog(dialogId);
225         }
226 
227         @Override
getDialogMetricsCategory(int dialogId)228         public int getDialogMetricsCategory(int dialogId) {
229             return mDialogDelegate.getDialogMetricsCategory(dialogId);
230         }
231     }
232 }
233