• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.password;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 import static com.google.common.truth.Truth.assertWithMessage;
21 
22 import static org.robolectric.RuntimeEnvironment.application;
23 
24 import android.content.ComponentName;
25 import android.content.Intent;
26 import android.content.pm.PackageManager;
27 import android.content.res.Resources;
28 import android.os.UserHandle;
29 import android.util.TypedValue;
30 import android.view.View;
31 import android.widget.Button;
32 import android.widget.TextView;
33 
34 import androidx.appcompat.app.AlertDialog;
35 import androidx.fragment.app.FragmentActivity;
36 
37 import com.android.internal.widget.LockPatternUtils;
38 import com.android.internal.widget.LockPatternView;
39 import com.android.internal.widget.LockPatternView.Cell;
40 import com.android.internal.widget.LockPatternView.DisplayMode;
41 import com.android.settings.R;
42 import com.android.settings.SetupRedactionInterstitial;
43 import com.android.settings.password.ChooseLockPattern.ChooseLockPatternFragment;
44 import com.android.settings.password.ChooseLockPattern.IntentBuilder;
45 import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
46 import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
47 import com.android.settings.testutils.shadow.ShadowUtils;
48 import com.android.settings.utils.ActivityControllerWrapper;
49 
50 import com.google.android.setupcompat.PartnerCustomizationLayout;
51 import com.google.android.setupcompat.template.FooterBarMixin;
52 import com.google.android.setupcompat.template.FooterButton;
53 
54 import org.junit.Before;
55 import org.junit.Ignore;
56 import org.junit.Test;
57 import org.junit.runner.RunWith;
58 import org.robolectric.Robolectric;
59 import org.robolectric.RobolectricTestRunner;
60 import org.robolectric.Shadows;
61 import org.robolectric.annotation.Config;
62 import org.robolectric.shadows.ShadowPackageManager;
63 import org.robolectric.util.ReflectionHelpers;
64 import org.robolectric.util.ReflectionHelpers.ClassParameter;
65 
66 import java.util.Arrays;
67 
68 @RunWith(RobolectricTestRunner.class)
69 @Config(shadows = {ShadowUtils.class, ShadowAlertDialogCompat.class, ShadowLockPatternUtils.class})
70 public class SetupChooseLockPatternTest {
71 
72     private SetupChooseLockPattern mActivity;
73 
74     @Before
setUp()75     public void setUp() {
76         application.getPackageManager().setComponentEnabledSetting(
77                 new ComponentName(application, SetupRedactionInterstitial.class),
78                 PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
79                 PackageManager.DONT_KILL_APP);
80 
81         final Intent intent =
82                 SetupChooseLockPattern.modifyIntentForSetup(
83                         application,
84                         new IntentBuilder(application)
85                                 .setUserId(UserHandle.myUserId())
86                                 .build());
87 
88         mActivity = (SetupChooseLockPattern) ActivityControllerWrapper.setup(
89                 Robolectric.buildActivity(SetupChooseLockPattern.class, intent)).get();
90     }
91 
92     @Test
chooseLockSaved_shouldEnableRedactionInterstitial()93     public void chooseLockSaved_shouldEnableRedactionInterstitial() {
94         findFragment(mActivity).onChosenLockSaveFinished(false, null);
95 
96         ShadowPackageManager spm = Shadows.shadowOf(application.getPackageManager());
97         ComponentName cname = new ComponentName(application, SetupRedactionInterstitial.class);
98         final int componentEnabled = spm.getComponentEnabledSettingFlags(cname)
99                 & PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
100         assertThat(componentEnabled).isEqualTo(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
101     }
102 
103     @Ignore
104     @Test
optionsButton_whenPatternSelected_shouldBeVisible()105     public void optionsButton_whenPatternSelected_shouldBeVisible() {
106         final Button button = mActivity.findViewById(R.id.screen_lock_options);
107         assertThat(button).isNotNull();
108         assertThat(button.getVisibility()).isEqualTo(View.VISIBLE);
109 
110         final LockPatternView lockPatternView = mActivity.findViewById(R.id.lockPattern);
111         ReflectionHelpers.callInstanceMethod(lockPatternView, "notifyPatternDetected");
112 
113         enterPattern();
114         assertThat(button.getVisibility()).isEqualTo(View.VISIBLE);
115     }
116 
verifyScreenLockOptionsShown()117     private void verifyScreenLockOptionsShown() {
118         final Button button = mActivity.findViewById(R.id.screen_lock_options);
119         assertThat(button).isNotNull();
120         assertThat(button.getVisibility()).isEqualTo(View.VISIBLE);
121 
122         button.performClick();
123         final AlertDialog chooserDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
124         assertThat(chooserDialog).isNotNull();
125         int count = chooserDialog.getListView().getCount();
126         assertWithMessage("List items shown").that(count).isEqualTo(3);
127     }
128 
129     @Ignore
130     @Config(qualifiers = "sw400dp")
131     @Test
sw400dp_shouldShowScreenLockOptions()132     public void sw400dp_shouldShowScreenLockOptions() {
133         verifyScreenLockOptionsShown();
134     }
135 
136     @Ignore
137     @Config(qualifiers = "sw400dp-land")
138     @Test
sw400dpLandscape_shouldShowScreenLockOptions()139     public void sw400dpLandscape_shouldShowScreenLockOptions() {
140         verifyScreenLockOptionsShown();
141     }
142 
verifyScreenLockOptionsHidden()143     private void verifyScreenLockOptionsHidden() {
144         Button button = mActivity.findViewById(R.id.screen_lock_options);
145         assertThat(button).isNotNull();
146         assertThat(button.getVisibility()).isEqualTo(View.GONE);
147     }
148 
149     @Config(qualifiers = "sw300dp")
150     @Test
smallScreens_shouldHideScreenLockOptions()151     public void smallScreens_shouldHideScreenLockOptions() {
152         verifyScreenLockOptionsHidden();
153     }
154 
155     @Config(qualifiers = "sw300dp-land")
156     @Test
smallScreensLandscape_shouldHideScreenLockOptions()157     public void smallScreensLandscape_shouldHideScreenLockOptions() {
158         verifyScreenLockOptionsHidden();
159     }
160 
161     @Ignore
162     @Test
skipButton_shouldBeVisible_duringNonFingerprintFlow()163     public void skipButton_shouldBeVisible_duringNonFingerprintFlow() {
164         final PartnerCustomizationLayout layout = mActivity.findViewById(R.id.setup_wizard_layout);
165         final Button skipOrClearButton =
166                 layout.getMixin(FooterBarMixin.class).getSecondaryButtonView();
167 
168         assertThat(skipOrClearButton).isNotNull();
169         assertThat(skipOrClearButton.getVisibility()).isEqualTo(View.VISIBLE);
170 
171         skipOrClearButton.performClick();
172         AlertDialog chooserDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
173         assertThat(chooserDialog).isNotNull();
174     }
175 
176     @Test
clearButton_shouldBeVisible_duringRetryStage()177     public void clearButton_shouldBeVisible_duringRetryStage() {
178         enterPattern();
179 
180         final PartnerCustomizationLayout layout = mActivity.findViewById(R.id.setup_wizard_layout);
181         final Button skipOrClearButton =
182                 layout.getMixin(FooterBarMixin.class).getSecondaryButtonView();
183 
184         assertThat(skipOrClearButton.getVisibility()).isEqualTo(View.VISIBLE);
185         assertThat(skipOrClearButton.isEnabled()).isTrue();
186 
187         skipOrClearButton.performClick();
188 
189         assertThat(findFragment(mActivity).mChosenPattern).isNull();
190     }
191 
192     @Test
createActivity_enterPattern_clearButtonShouldBeShown()193     public void createActivity_enterPattern_clearButtonShouldBeShown() {
194         final PartnerCustomizationLayout layout = mActivity.findViewById(R.id.setup_wizard_layout);
195         final Button skipOrClearButton =
196                 layout.getMixin(FooterBarMixin.class).getSecondaryButtonView();
197 
198         assertThat(skipOrClearButton.isEnabled()).isTrue();
199         assertThat(skipOrClearButton.getVisibility()).isEqualTo(View.VISIBLE);
200         assertThat(skipOrClearButton.getText())
201                 .isEqualTo(application.getString(R.string.skip_label));
202 
203         enterPattern();
204 
205         assertThat(skipOrClearButton.isEnabled()).isTrue();
206         assertThat(skipOrClearButton.getVisibility()).isEqualTo(View.VISIBLE);
207         assertThat(skipOrClearButton.getText())
208                 .isEqualTo(application.getString(R.string.lockpattern_retry_button_text));
209     }
210 
211     @Test
createActivity_patternDescription_shouldBeShown()212     public void createActivity_patternDescription_shouldBeShown() {
213         final PartnerCustomizationLayout layout = mActivity.findViewById(R.id.setup_wizard_layout);
214         final TextView patternDescription =
215                 layout.findViewById(R.id.sud_layout_subtitle);
216 
217         assertThat(patternDescription.getVisibility()).isEqualTo(View.VISIBLE);
218         assertThat(patternDescription.getText()).isEqualTo(
219                 application.getString(R.string.lockpassword_choose_your_pattern_description));
220     }
221 
222     @Test
inIntroductionStage_theHeaderHeight_shouldSetMinLinesTwoToPreventFlicker()223     public void inIntroductionStage_theHeaderHeight_shouldSetMinLinesTwoToPreventFlicker() {
224         final PartnerCustomizationLayout layout = mActivity.findViewById(R.id.setup_wizard_layout);
225         final TextView headerView = layout.findViewById(R.id.sud_layout_subtitle);
226 
227         assertThat(headerView.getVisibility()).isEqualTo(View.VISIBLE);
228         assertThat(headerView.getText().toString()).isEqualTo(
229                 application.getString(R.string.lockpassword_choose_your_pattern_description));
230     }
231 
232     @Test
createActivity_enterPattern_shouldGoToFirstChoiceValidStage()233     public void createActivity_enterPattern_shouldGoToFirstChoiceValidStage() {
234         final PartnerCustomizationLayout layout = mActivity.findViewById(R.id.setup_wizard_layout);
235         final TextView headerView = layout.findViewById(R.id.sud_layout_subtitle);
236 
237         assertThat(headerView.getVisibility()).isEqualTo(View.VISIBLE);
238 
239         enterPattern();
240 
241         assertThat(headerView.getText().toString()).isEqualTo(
242                 application.getString(R.string.lockpattern_pattern_entered_header));
243     }
244 
245     @Test
createActivity_enterShortPattern_shouldGoToChoiceTooShortStage()246     public void createActivity_enterShortPattern_shouldGoToChoiceTooShortStage() {
247         final PartnerCustomizationLayout layout = mActivity.findViewById(R.id.setup_wizard_layout);
248         final TextView headerView = layout.findViewById(R.id.sud_layout_subtitle);
249 
250         enterShortPattern();
251 
252         assertThat(headerView.getVisibility()).isEqualTo(View.VISIBLE);
253         assertThat(headerView.getText().toString()).isEqualTo(
254                 application.getResources().getString(
255                         R.string.lockpattern_recording_incorrect_too_short,
256                         LockPatternUtils.MIN_LOCK_PATTERN_SIZE));
257     }
258 
259     @Test
inChoiceTooShortStage_theHeaderColor_shouldTintOnErrorColor()260     public void inChoiceTooShortStage_theHeaderColor_shouldTintOnErrorColor() {
261         final PartnerCustomizationLayout layout = mActivity.findViewById(R.id.setup_wizard_layout);
262         final TextView headerView = layout.findViewById(R.id.sud_layout_subtitle);
263         final TypedValue typedValue = new TypedValue();
264         final Resources.Theme theme = mActivity.getTheme();
265         theme.resolveAttribute(R.attr.colorError, typedValue, true);
266         final int errorColor = typedValue.data;
267 
268         enterShortPattern();
269 
270         assertThat(headerView.getVisibility()).isEqualTo(View.VISIBLE);
271         assertThat(headerView.getTextColors().getDefaultColor()).isEqualTo(errorColor);
272     }
273 
274     @Test
inFirstChoiceValidStage_nextButtonState_shouldEnabled()275     public void inFirstChoiceValidStage_nextButtonState_shouldEnabled() {
276         final PartnerCustomizationLayout layout = mActivity.findViewById(R.id.setup_wizard_layout);
277         final FooterBarMixin footerBarMixin = layout.getMixin(FooterBarMixin.class);
278         final FooterButton nextButton = footerBarMixin.getPrimaryButton();
279 
280         assertThat(nextButton.getVisibility()).isEqualTo(View.VISIBLE);
281         assertThat(nextButton.isEnabled()).isFalse();
282 
283         enterPattern();
284 
285         assertThat(nextButton.isEnabled()).isTrue();
286     }
287 
288     @Test
inFirstChoiceValidStage_clickNextButton_shouldGoToNeedToConfirmStage()289     public void inFirstChoiceValidStage_clickNextButton_shouldGoToNeedToConfirmStage() {
290         final PartnerCustomizationLayout layout = mActivity.findViewById(R.id.setup_wizard_layout);
291         final TextView headerView = layout.findViewById(R.id.sud_layout_subtitle);
292         final FooterBarMixin footerBarMixin = layout.getMixin(FooterBarMixin.class);
293         final Button nextButton = footerBarMixin.getPrimaryButtonView();
294 
295         assertThat(headerView.getVisibility()).isEqualTo(View.VISIBLE);
296 
297         enterPattern();
298         nextButton.performClick();
299 
300         assertThat(headerView.getText().toString()).isEqualTo(
301                 application.getString(R.string.lockpattern_need_to_confirm));
302     }
303 
304     @Test
inNeedToConfirmStage_enterWrongPattern_shouldGoToConfirmWrongStage()305     public void inNeedToConfirmStage_enterWrongPattern_shouldGoToConfirmWrongStage() {
306         final PartnerCustomizationLayout layout = mActivity.findViewById(R.id.setup_wizard_layout);
307         final TextView headerView = layout.findViewById(R.id.sud_layout_subtitle);
308         final FooterBarMixin footerBarMixin = layout.getMixin(FooterBarMixin.class);
309         final Button nextButton = footerBarMixin.getPrimaryButtonView();
310         // IntroductionStage
311         assertThat(headerView.getVisibility()).isEqualTo(View.VISIBLE);
312 
313         enterPattern();
314         nextButton.performClick();
315 
316         // NeedToConfirmStage
317         assertThat(headerView.getText().toString()).isEqualTo(
318                 application.getString(R.string.lockpattern_need_to_confirm));
319 
320         enterShortPattern();
321 
322         // ConfirmWrongStage
323         assertThat(headerView.getText().toString()).isEqualTo(
324                 application.getString(R.string.lockpattern_need_to_unlock_wrong));
325         assertThat(nextButton.getText().toString()).isEqualTo(
326                 application.getString(R.string.lockpattern_confirm_button_text));
327         assertThat(nextButton.isEnabled()).isFalse();
328     }
329 
330     @Test
inNeedToConfirmStage_enterCorrectPattern_shouldGoToChoiceConfirmedStage()331     public void inNeedToConfirmStage_enterCorrectPattern_shouldGoToChoiceConfirmedStage() {
332         final PartnerCustomizationLayout layout = mActivity.findViewById(R.id.setup_wizard_layout);
333         final TextView headerView = layout.findViewById(R.id.sud_layout_subtitle);
334         final FooterBarMixin footerBarMixin = layout.getMixin(FooterBarMixin.class);
335         final Button nextButton = footerBarMixin.getPrimaryButtonView();
336         // IntroductionStage
337         assertThat(headerView.getVisibility()).isEqualTo(View.VISIBLE);
338 
339         enterPattern();
340         nextButton.performClick();
341 
342         // NeedToConfirmStage
343         assertThat(headerView.getText().toString()).isEqualTo(
344                 application.getString(R.string.lockpattern_need_to_confirm));
345 
346         enterPattern();
347 
348         // ChoiceConfirmedStage
349         assertThat(headerView.getText().toString()).isEqualTo(
350                 application.getString(R.string.lockpattern_pattern_confirmed_header));
351         assertThat(nextButton.getText().toString()).isEqualTo(
352                 application.getString(R.string.lockpattern_confirm_button_text));
353         assertThat(nextButton.isEnabled()).isTrue();
354     }
355 
findFragment(FragmentActivity activity)356     private ChooseLockPatternFragment findFragment(FragmentActivity activity) {
357         return (ChooseLockPatternFragment)
358                 activity.getSupportFragmentManager().findFragmentById(R.id.main_content);
359     }
360 
enterPattern()361     private void enterPattern() {
362         LockPatternView lockPatternView = mActivity.findViewById(R.id.lockPattern);
363         lockPatternView.setPattern(
364                 DisplayMode.Animate,
365                 Arrays.asList(
366                         createCell(0, 0),
367                         createCell(0, 1),
368                         createCell(1, 1),
369                         createCell(1, 0)));
370         ReflectionHelpers.callInstanceMethod(lockPatternView, "notifyPatternDetected");
371     }
372 
enterShortPattern()373     private void enterShortPattern() {
374         LockPatternView lockPatternView = mActivity.findViewById(R.id.lockPattern);
375         lockPatternView.setPattern(
376                 DisplayMode.Animate,
377                 Arrays.asList(
378                         createCell(0, 0),
379                         createCell(0, 1),
380                         createCell(1, 1)));
381         ReflectionHelpers.callInstanceMethod(lockPatternView, "notifyPatternDetected");
382     }
383 
createCell(int row, int column)384     private Cell createCell(int row, int column) {
385         return ReflectionHelpers.callConstructor(
386                 Cell.class,
387                 ClassParameter.from(int.class, row),
388                 ClassParameter.from(int.class, column));
389     }
390 }
391