1 /*
2  * Copyright (C) 2021 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 android.content.Context.MODE_PRIVATE;
20 
21 import static com.android.settings.accessibility.AutoclickUtils.KEY_CUSTOM_DELAY_VALUE;
22 import static com.android.settings.accessibility.AutoclickUtils.KEY_DELAY_MODE;
23 import static com.android.settings.core.BasePreferenceController.AVAILABLE;
24 
25 import static com.google.common.truth.Truth.assertThat;
26 
27 import static org.mockito.ArgumentMatchers.anyInt;
28 import static org.mockito.ArgumentMatchers.anyString;
29 import static org.mockito.Mockito.doReturn;
30 import static org.mockito.Mockito.mock;
31 import static org.mockito.Mockito.verify;
32 import static org.robolectric.Shadows.shadowOf;
33 
34 import android.content.Context;
35 import android.content.SharedPreferences;
36 import android.provider.Settings;
37 import android.widget.ImageView;
38 import android.widget.SeekBar;
39 import android.widget.TextView;
40 
41 import androidx.preference.PreferenceScreen;
42 import androidx.test.core.app.ApplicationProvider;
43 
44 import com.android.settings.R;
45 import com.android.settingslib.widget.LayoutPreference;
46 
47 import org.junit.Before;
48 import org.junit.Rule;
49 import org.junit.Test;
50 import org.junit.runner.RunWith;
51 import org.mockito.Mock;
52 import org.mockito.Spy;
53 import org.mockito.junit.MockitoJUnit;
54 import org.mockito.junit.MockitoRule;
55 import org.robolectric.RobolectricTestRunner;
56 
57 /** Tests for {@link ToggleAutoclickCustomSeekbarController}. */
58 @RunWith(RobolectricTestRunner.class)
59 public class ToggleAutoclickCustomSeekbarControllerTest {
60 
61     private static final String KEY_CUSTOM_SEEKBAR = "autoclick_custom_seekbar";
62 
63     @Rule
64     public final MockitoRule mMockitoRule = MockitoJUnit.rule();
65     @Mock
66     private PreferenceScreen mScreen;
67     @Mock
68     private LayoutPreference mLayoutPreference;
69     @Spy
70     private Context mContext = ApplicationProvider.getApplicationContext();
71     private SharedPreferences mSharedPreferences;
72     private TextView mDelayLabel;
73     private ImageView mShorter;
74     private ImageView mLonger;
75     private SeekBar mSeekBar;
76     private ToggleAutoclickCustomSeekbarController mController;
77 
78     @Before
setUp()79     public void setUp() {
80         mSharedPreferences = mContext.getSharedPreferences(mContext.getPackageName(), MODE_PRIVATE);
81         mDelayLabel = new TextView(mContext);
82         mShorter = new ImageView(mContext);
83         mLonger = new ImageView(mContext);
84         mSeekBar = new SeekBar(mContext);
85         mController = new ToggleAutoclickCustomSeekbarController(mContext, KEY_CUSTOM_SEEKBAR);
86         doReturn(mLayoutPreference).when(mScreen).findPreference(KEY_CUSTOM_SEEKBAR);
87         doReturn(mSeekBar).when(mLayoutPreference).findViewById(R.id.autoclick_delay);
88         doReturn(mDelayLabel).when(mLayoutPreference).findViewById(R.id.current_label);
89         doReturn(mShorter).when(mLayoutPreference).findViewById(R.id.shorter);
90         doReturn(mLonger).when(mLayoutPreference).findViewById(R.id.longer);
91     }
92 
93     @Test
getAvailabilityStatus_available()94     public void getAvailabilityStatus_available() {
95         assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
96     }
97 
98     @Test
displayPreference_initSeekBar()99     public void displayPreference_initSeekBar() {
100         mSharedPreferences.edit().putInt(KEY_CUSTOM_DELAY_VALUE, 700).apply();
101 
102         mController.onStart();
103         mController.displayPreference(mScreen);
104         mController.onStop();
105         final SeekBar.OnSeekBarChangeListener mListener =
106                 shadowOf(mSeekBar).getOnSeekBarChangeListener();
107 
108         assertThat(mSeekBar.getMax()).isEqualTo(8);
109         assertThat(mSeekBar.getProgress()).isEqualTo(5);
110         assertThat(mListener).isNotNull();
111     }
112 
113     @Test
displayPreference_initDelayLabel()114     public void displayPreference_initDelayLabel() {
115         mSharedPreferences.edit().putInt(KEY_CUSTOM_DELAY_VALUE, 700).apply();
116 
117         mController.onStart();
118         mController.displayPreference(mScreen);
119         mController.onStop();
120 
121         assertThat(mDelayLabel.getText()).isEqualTo("0.7 seconds");
122     }
123 
124     @Test
onSharedPreferenceChanged_delayMode_updateCustomDelayValue()125     public void onSharedPreferenceChanged_delayMode_updateCustomDelayValue() {
126         mSharedPreferences.edit().putInt(KEY_CUSTOM_DELAY_VALUE, 700).apply();
127 
128         mController.displayPreference(mScreen);
129         mController.onSharedPreferenceChanged(mSharedPreferences, KEY_DELAY_MODE);
130         final int actualDelayValue =
131                 Settings.Secure.getInt(mContext.getContentResolver(),
132                         Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY, /* def= */ 0);
133         final int actualCustomDelayValue =
134                 mSharedPreferences.getInt(KEY_CUSTOM_DELAY_VALUE, /* defValue= */ 0);
135 
136         assertThat(mDelayLabel.getText()).isEqualTo("0.7 seconds");
137         assertThat(mSeekBar.getProgress()).isEqualTo(5);
138         assertThat(actualDelayValue).isEqualTo(700);
139         assertThat(actualCustomDelayValue).isEqualTo(700);
140     }
141 
142     @Test
onSeekBarProgressChanged_updateCustomDelayValue()143     public void onSeekBarProgressChanged_updateCustomDelayValue() {
144         mSharedPreferences.edit().putInt(KEY_CUSTOM_DELAY_VALUE, 700).apply();
145 
146         mController.displayPreference(mScreen);
147         mController.mSeekBarChangeListener.onProgressChanged(mock(SeekBar.class),
148                 /* value= */ 8,
149                 true);
150         final int actualDelayValue =
151                 Settings.Secure.getInt(mContext.getContentResolver(),
152                         Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY, /* def= */ 0);
153         final int actualCustomDelayValue =
154                 mSharedPreferences.getInt(KEY_CUSTOM_DELAY_VALUE, /* defValue= */ 0);
155 
156         assertThat(mDelayLabel.getText()).isEqualTo("1 second");
157         assertThat(mSeekBar.getProgress()).isEqualTo(8);
158         assertThat(actualDelayValue).isEqualTo(1000);
159         assertThat(actualCustomDelayValue).isEqualTo(1000);
160     }
161 
162     @Test
onShorterClicked_updateCustomDelayValue()163     public void onShorterClicked_updateCustomDelayValue() {
164         mSharedPreferences.edit().putInt(KEY_CUSTOM_DELAY_VALUE, 700).apply();
165 
166         mController.displayPreference(mScreen);
167         mShorter.callOnClick();
168         final int actualDelayValue =
169                 Settings.Secure.getInt(mContext.getContentResolver(),
170                 Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY, /* def= */ 0);
171         final int actualCustomDelayValue =
172                 mSharedPreferences.getInt(KEY_CUSTOM_DELAY_VALUE, /* defValue= */ 0);
173 
174         assertThat(mSeekBar.getProgress()).isEqualTo(4);
175         assertThat(mDelayLabel.getText()).isEqualTo("0.6 seconds");
176         assertThat(actualDelayValue).isEqualTo(600);
177         assertThat(actualCustomDelayValue).isEqualTo(600);
178     }
179 
180     @Test
onLongerClicked_updateCustomDelayValue()181     public void onLongerClicked_updateCustomDelayValue() {
182         mSharedPreferences.edit().putInt(KEY_CUSTOM_DELAY_VALUE, 700).apply();
183 
184         mController.displayPreference(mScreen);
185         mLonger.callOnClick();
186         final int actualDelayValue =
187                 Settings.Secure.getInt(mContext.getContentResolver(),
188                         Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY, /* def= */ 0);
189         final int actualCustomDelayValue =
190                 mSharedPreferences.getInt(KEY_CUSTOM_DELAY_VALUE, /* defValue= */ 0);
191 
192         assertThat(mSeekBar.getProgress()).isEqualTo(6);
193         assertThat(mDelayLabel.getText()).isEqualTo("0.8 seconds");
194         assertThat(actualDelayValue).isEqualTo(800);
195         assertThat(actualCustomDelayValue).isEqualTo(800);
196     }
197 
198     @Test
onStart_registerOnSharedPreferenceChangeListener()199     public void onStart_registerOnSharedPreferenceChangeListener() {
200         final SharedPreferences prefs = mock(SharedPreferences.class);
201         doReturn(prefs).when(mContext).getSharedPreferences(anyString(), anyInt());
202         final ToggleAutoclickCustomSeekbarController controller =
203                 new ToggleAutoclickCustomSeekbarController(mContext, KEY_CUSTOM_SEEKBAR);
204 
205         controller.onStart();
206 
207         verify(prefs).registerOnSharedPreferenceChangeListener(controller);
208     }
209 
210     @Test
onStop_unregisterOnSharedPreferenceChangeListener()211     public void onStop_unregisterOnSharedPreferenceChangeListener() {
212         final SharedPreferences prefs = mock(SharedPreferences.class);
213         doReturn(prefs).when(mContext).getSharedPreferences(anyString(), anyInt());
214         final ToggleAutoclickCustomSeekbarController controller =
215                 new ToggleAutoclickCustomSeekbarController(mContext, KEY_CUSTOM_SEEKBAR);
216 
217         controller.onStop();
218 
219         verify(prefs).unregisterOnSharedPreferenceChangeListener(controller);
220     }
221 }
222