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.Intent;
25 import android.os.Bundle;
26 import android.view.View;
27 import android.view.inputmethod.InputMethodManager;
28 import android.widget.Button;
29 
30 import androidx.appcompat.app.AlertDialog;
31 
32 import com.android.settings.R;
33 import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment;
34 import com.android.settings.password.ChooseLockPassword.ChooseLockPasswordFragment.Stage;
35 import com.android.settings.password.ChooseLockPassword.IntentBuilder;
36 import com.android.settings.password.SetupChooseLockPassword.SetupChooseLockPasswordFragment;
37 import com.android.settings.testutils.shadow.SettingsShadowResources;
38 import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
39 import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
40 import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
41 import com.android.settings.testutils.shadow.ShadowUtils;
42 import com.android.settings.widget.ScrollToParentEditText;
43 
44 import com.google.android.setupcompat.PartnerCustomizationLayout;
45 import com.google.android.setupcompat.template.FooterBarMixin;
46 
47 import org.junit.After;
48 import org.junit.Before;
49 import org.junit.Test;
50 import org.junit.runner.RunWith;
51 import org.robolectric.RobolectricTestRunner;
52 import org.robolectric.Shadows;
53 import org.robolectric.android.controller.ActivityController;
54 import org.robolectric.annotation.Config;
55 import org.robolectric.annotation.Implementation;
56 import org.robolectric.annotation.Implements;
57 import org.robolectric.shadows.ShadowActivity;
58 import org.robolectric.shadows.ShadowDialog;
59 import org.robolectric.shadows.ShadowInputMethodManager;
60 
61 import java.util.Collections;
62 import java.util.List;
63 
64 @RunWith(RobolectricTestRunner.class)
65 @Config(
66         shadows = {
67                 SettingsShadowResources.class,
68                 ShadowLockPatternUtils.class,
69                 ShadowDevicePolicyManager.class,
70                 ShadowUtils.class,
71                 ShadowAlertDialogCompat.class
72         })
73 public class SetupChooseLockPasswordTest {
74 
75     @Before
setUp()76     public void setUp() {
77         SettingsShadowResources.overrideResource(
78                 com.android.internal.R.string.config_headlineFontFamily, "");
79     }
80 
81     @After
tearDown()82     public void tearDown() {
83         SettingsShadowResources.reset();
84     }
85 
86     @Test
createActivity_shouldNotCrash()87     public void createActivity_shouldNotCrash() {
88         // Basic test for activity created without crashing
89         final Intent intent =
90                 SetupChooseLockPassword.modifyIntentForSetup(
91                         application,
92                         new IntentBuilder(application).build());
93 
94         ActivityController.of(new SetupChooseLockPassword(), intent).setup().get();
95     }
96 
97     @Test
createActivity_withShowOptionsButtonExtra_shouldShowButton()98     public void createActivity_withShowOptionsButtonExtra_shouldShowButton() {
99         SetupChooseLockPassword activity = createSetupChooseLockPassword();
100         Button optionsButton = activity.findViewById(R.id.screen_lock_options);
101         assertThat(optionsButton).isNotNull();
102         optionsButton.performClick();
103         assertThat(ShadowDialog.getLatestDialog()).isNotNull();
104     }
105 
106     @Test
107     @Config(shadows = ShadowChooseLockGenericController.class)
createActivity_withShowOptionsButtonExtra_buttonNotVisibleIfNoVisibleLockTypes()108     public void createActivity_withShowOptionsButtonExtra_buttonNotVisibleIfNoVisibleLockTypes() {
109         SetupChooseLockPassword activity = createSetupChooseLockPassword();
110         Button optionsButton = activity.findViewById(R.id.screen_lock_options);
111         assertThat(optionsButton).isNotNull();
112         assertThat(optionsButton.getVisibility()).isEqualTo(View.GONE);
113     }
114 
115     @Test
allSecurityOptions_shouldBeShown_When_OptionsButtonIsClicked()116     public void allSecurityOptions_shouldBeShown_When_OptionsButtonIsClicked() {
117         SetupChooseLockPassword activity = createSetupChooseLockPassword();
118         activity.findViewById(R.id.screen_lock_options).performClick();
119         AlertDialog latestAlertDialog = (AlertDialog) ShadowDialog.getLatestDialog();
120         int count = latestAlertDialog.getListView().getCount();
121         assertWithMessage("List items shown").that(count).isEqualTo(3);
122     }
123 
124     @Test
createActivity_clickDifferentOption_extrasShouldBePropagated()125     public void createActivity_clickDifferentOption_extrasShouldBePropagated() {
126         Bundle bundle = new Bundle();
127         bundle.putString("foo", "bar");
128 
129         Intent intent = new IntentBuilder(application).build();
130         intent.putExtra(ChooseLockGenericFragment.EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS, bundle);
131         intent = SetupChooseLockPassword.modifyIntentForSetup(application, intent);
132         intent.putExtra(ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, true);
133 
134         SetupChooseLockPassword activity =
135                 ActivityController.of(new SetupChooseLockPassword(), intent).setup().get();
136 
137         SetupChooseLockPasswordFragment fragment =
138                 (SetupChooseLockPasswordFragment) activity.getSupportFragmentManager()
139                         .findFragmentById(R.id.main_content);
140         fragment.onLockTypeSelected(ScreenLockType.PATTERN);
141 
142         ShadowActivity shadowActivity = Shadows.shadowOf(activity);
143         final Intent nextStartedActivity = shadowActivity.getNextStartedActivity();
144         assertThat(nextStartedActivity).isNotNull();
145         assertThat(nextStartedActivity.getBooleanExtra(
146                 ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, false)).isTrue();
147         assertWithMessage("Foo extra").that(nextStartedActivity.getStringExtra("foo"))
148                 .isEqualTo("bar");
149     }
150 
151     @Test
createActivity_skipButtonInIntroductionStage_shouldBeVisible()152     public void createActivity_skipButtonInIntroductionStage_shouldBeVisible() {
153         SetupChooseLockPassword activity = createSetupChooseLockPassword();
154         final InputMethodManager inputMethodManager = activity
155                 .getSystemService(InputMethodManager.class);
156         final ShadowInputMethodManager shadowImm = Shadows.shadowOf(inputMethodManager);
157 
158         final PartnerCustomizationLayout layout = activity.findViewById(R.id.setup_wizard_layout);
159         final Button skipOrClearButton =
160                 layout.getMixin(FooterBarMixin.class).getSecondaryButtonView();
161         assertThat(skipOrClearButton).isNotNull();
162         assertThat(skipOrClearButton.getVisibility()).isEqualTo(View.VISIBLE);
163 
164         skipOrClearButton.performClick();
165         final AlertDialog chooserDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
166         assertThat(chooserDialog).isNotNull();
167         assertThat(shadowImm.isSoftInputVisible()).isFalse();
168     }
169 
170     @Test
createActivity_inputPasswordInConfirmStage_clearButtonShouldBeShown()171     public void createActivity_inputPasswordInConfirmStage_clearButtonShouldBeShown() {
172         SetupChooseLockPassword activity = createSetupChooseLockPassword();
173 
174         SetupChooseLockPasswordFragment fragment =
175             (SetupChooseLockPasswordFragment) activity.getSupportFragmentManager()
176                 .findFragmentById(R.id.main_content);
177 
178         ScrollToParentEditText passwordEntry = activity.findViewById(R.id.password_entry);
179         passwordEntry.setText("");
180         fragment.updateStage(Stage.NeedToConfirm);
181 
182         final PartnerCustomizationLayout layout = activity.findViewById(R.id.setup_wizard_layout);
183         final Button skipOrClearButton =
184                 layout.getMixin(FooterBarMixin.class).getSecondaryButtonView();
185         assertThat(skipOrClearButton.isEnabled()).isTrue();
186         assertThat(skipOrClearButton.getVisibility()).isEqualTo(View.GONE);
187 
188         passwordEntry.setText("1234");
189         fragment.updateUi();
190         assertThat(skipOrClearButton.getVisibility()).isEqualTo(View.VISIBLE);
191         assertThat(skipOrClearButton.getText())
192                 .isEqualTo(application.getString(R.string.lockpassword_clear_label));
193     }
194 
createSetupChooseLockPassword()195     private SetupChooseLockPassword createSetupChooseLockPassword() {
196         final Intent intent =
197                 SetupChooseLockPassword.modifyIntentForSetup(
198                         application,
199                         new IntentBuilder(application).build());
200         intent.putExtra(ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, true);
201         return ActivityController.of(new SetupChooseLockPassword(), intent).setup().get();
202     }
203 
204     @Implements(ChooseLockGenericController.class)
205     public static class ShadowChooseLockGenericController {
206         @Implementation
getVisibleScreenLockTypes()207         protected List<ScreenLockType> getVisibleScreenLockTypes() {
208             return Collections.emptyList();
209         }
210     }
211 }
212