fix: 首次提交

This commit is contained in:
2024-12-09 11:25:23 +08:00
parent d0c01071e9
commit 2c2109a5f3
4741 changed files with 290641 additions and 0 deletions

View File

@@ -0,0 +1,266 @@
/*
* Copyright (C) 2023 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.settingslib.users;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RadioButton;
import androidx.fragment.app.FragmentActivity;
import com.android.settingslib.R;
import com.android.settingslib.RestrictedLockUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.android.controller.ActivityController;
@RunWith(RobolectricTestRunner.class)
public class CreateUserDialogControllerTest {
@Mock
private ActivityStarter mActivityStarter;
private boolean mPhotoRestrictedByBase;
private Activity mActivity;
private TestCreateUserDialogController mUnderTest;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mActivity = spy(ActivityController.of(new FragmentActivity()).get());
mActivity.setTheme(androidx.appcompat.R.style.Theme_AppCompat_DayNight);
mUnderTest = new TestCreateUserDialogController();
mPhotoRestrictedByBase = false;
}
@Test
public void positiveButton_grantAdminStage_noValue_OkButtonShouldBeDisabled() {
Runnable cancelCallback = mock(Runnable.class);
final AlertDialog dialog = (AlertDialog) mUnderTest.createDialog(mActivity,
mActivityStarter, true, null,
cancelCallback);
dialog.show();
assertThat(dialog.findViewById(R.id.button_ok).isEnabled()).isEqualTo(true);
Button next = dialog.findViewById(R.id.button_ok);
next.performClick();
assertThat(dialog.findViewById(R.id.button_ok).isEnabled()).isEqualTo(false);
((RadioButton) dialog.findViewById(R.id.grant_admin_yes)).setChecked(true);
assertThat(dialog.findViewById(R.id.button_ok).isEnabled()).isEqualTo(true);
dialog.dismiss();
}
@Test
public void positiveButton_MultipleAdminDisabled_shouldSkipGrantAdminStage() {
Runnable cancelCallback = mock(Runnable.class);
final AlertDialog dialog = (AlertDialog) mUnderTest.createDialog(mActivity,
mActivityStarter, false, null,
cancelCallback);
dialog.show();
assertThat(dialog.findViewById(R.id.grant_admin_view).getVisibility()).isEqualTo(View.GONE);
assertThat(dialog.findViewById(R.id.button_ok).isEnabled()).isEqualTo(true);
Button next = dialog.findViewById(R.id.button_ok);
next.performClick();
assertThat(dialog.findViewById(R.id.grant_admin_view).getVisibility()).isEqualTo(View.GONE);
assertThat(dialog.findViewById(R.id.button_ok).isEnabled()).isEqualTo(true);
Button back = dialog.findViewById(R.id.button_cancel);
back.performClick();
assertThat(dialog.findViewById(R.id.grant_admin_view).getVisibility()).isEqualTo(View.GONE);
dialog.dismiss();
}
@Test
public void editUserInfoController_shouldOnlyBeVisibleOnLastStage() {
Runnable cancelCallback = mock(Runnable.class);
final AlertDialog dialog = (AlertDialog) mUnderTest.createDialog(mActivity,
mActivityStarter, true, null,
cancelCallback);
dialog.show();
assertThat(dialog.findViewById(R.id.user_info_editor).getVisibility()).isEqualTo(View.GONE);
Button next = dialog.findViewById(R.id.button_ok);
next.performClick();
((RadioButton) dialog.findViewById(R.id.grant_admin_yes)).setChecked(true);
assertThat(dialog.findViewById(R.id.user_info_editor).getVisibility()).isEqualTo(View.GONE);
next.performClick();
assertThat(dialog.findViewById(R.id.user_info_editor).getVisibility())
.isEqualTo(View.VISIBLE);
dialog.dismiss();
}
@Test
public void positiveButton_MultipleAdminEnabled_shouldShowGrantAdminStage() {
Runnable cancelCallback = mock(Runnable.class);
final AlertDialog dialog = (AlertDialog) mUnderTest.createDialog(mActivity,
mActivityStarter, true, null,
cancelCallback);
dialog.show();
assertThat(dialog.findViewById(R.id.grant_admin_view).getVisibility()).isEqualTo(View.GONE);
assertThat(dialog.findViewById(R.id.button_ok).isEnabled()).isEqualTo(true);
Button next = dialog.findViewById(R.id.button_ok);
next.performClick();
assertThat(dialog.findViewById(R.id.grant_admin_view).getVisibility())
.isEqualTo(View.VISIBLE);
((RadioButton) dialog.findViewById(R.id.grant_admin_yes)).setChecked(true);
next.performClick();
assertThat(dialog.findViewById(R.id.grant_admin_view).getVisibility()).isEqualTo(View.GONE);
dialog.dismiss();
}
@Test
public void cancelCallback_isCalled_whenCancelled() {
NewUserData successCallback = mock(NewUserData.class);
Runnable cancelCallback = mock(Runnable.class);
AlertDialog dialog = (AlertDialog) mUnderTest.createDialog(mActivity,
mActivityStarter, true, successCallback,
cancelCallback);
dialog.show();
dialog.cancel();
verifyNoInteractions(successCallback);
verify(cancelCallback, times(1))
.run();
}
@Test
public void cancelCallback_isCalled_whenNegativeButtonClickedOnFirstStage() {
NewUserData successCallback = mock(NewUserData.class);
Runnable cancelCallback = mock(Runnable.class);
AlertDialog dialog = (AlertDialog) mUnderTest.createDialog(mActivity,
mActivityStarter, true, successCallback,
cancelCallback);
dialog.show();
Button back = dialog.findViewById(R.id.button_cancel);
back.performClick();
verifyNoInteractions(successCallback);
verify(cancelCallback, times(1))
.run();
}
@Test
public void cancelCallback_isNotCalled_whenNegativeButtonClickedOnSecondStage() {
NewUserData successCallback = mock(NewUserData.class);
Runnable cancelCallback = mock(Runnable.class);
AlertDialog dialog = (AlertDialog) mUnderTest.createDialog(mActivity,
mActivityStarter, true, successCallback,
cancelCallback);
dialog.show();
Button next = dialog.findViewById(R.id.button_ok);
next.performClick();
Button back = dialog.findViewById(R.id.button_cancel);
back.performClick();
verifyNoInteractions(successCallback);
verifyNoInteractions(cancelCallback);
dialog.dismiss();
}
@Test
public void successCallback_isCalled_setNameAndAdminStatus() {
NewUserData successCallback = mock(NewUserData.class);
Runnable cancelCallback = mock(Runnable.class);
AlertDialog dialog = (AlertDialog) mUnderTest.createDialog(mActivity,
mActivityStarter, true, successCallback,
cancelCallback);
// No photo chosen
when(mUnderTest.getPhotoController().getNewUserPhotoDrawable()).thenReturn(null);
dialog.show();
Button next = dialog.findViewById(R.id.button_ok);
next.performClick();
((RadioButton) dialog.findViewById(R.id.grant_admin_yes)).setChecked(true);
next.performClick();
String expectedNewName = "Test";
EditText editText = dialog.findViewById(R.id.user_name);
editText.setText(expectedNewName);
next.performClick();
verify(successCallback, times(1))
.onSuccess(expectedNewName, null, true);
verifyNoInteractions(cancelCallback);
}
@Test
public void successCallback_isCalled_setName_MultipleAdminDisabled() {
NewUserData successCallback = mock(NewUserData.class);
Runnable cancelCallback = mock(Runnable.class);
AlertDialog dialog = (AlertDialog) mUnderTest.createDialog(mActivity,
mActivityStarter, false, successCallback,
cancelCallback);
// No photo chosen
when(mUnderTest.getPhotoController().getNewUserPhotoDrawable()).thenReturn(null);
dialog.show();
Button next = dialog.findViewById(R.id.button_ok);
next.performClick();
String expectedNewName = "Test";
EditText editText = dialog.findViewById(R.id.user_name);
editText.setText(expectedNewName);
next.performClick();
verify(successCallback, times(1))
.onSuccess(expectedNewName, null, false);
verifyNoInteractions(cancelCallback);
}
private class TestCreateUserDialogController extends CreateUserDialogController {
private EditUserPhotoController mPhotoController;
TestCreateUserDialogController() {
super("file_authority");
}
private EditUserPhotoController getPhotoController() {
return mPhotoController;
}
@Override
EditUserPhotoController createEditUserPhotoController(ImageView userPhotoView) {
mPhotoController = mock(EditUserPhotoController.class, Answers.RETURNS_DEEP_STUBS);
return mPhotoController;
}
@Override
RestrictedLockUtils.EnforcedAdmin getChangePhotoAdminRestriction(Context context) {
return null;
}
@Override
boolean isChangePhotoRestrictedByBase(Context context) {
return mPhotoRestrictedByBase;
}
}
}

View File

@@ -0,0 +1,273 @@
/*
* Copyright (C) 2018 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.settingslib.users;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.widget.EditText;
import android.widget.ImageView;
import androidx.fragment.app.FragmentActivity;
import com.android.settingslib.R;
import com.android.settingslib.RestrictedLockUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.android.controller.ActivityController;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowDialog;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@RunWith(RobolectricTestRunner.class)
public class EditUserInfoControllerTest {
private static final int MAX_USER_NAME_LENGTH = 100;
@Mock
private Drawable mCurrentIcon;
@Mock
private ActivityStarter mActivityStarter;
private boolean mPhotoRestrictedByBase;
private Activity mActivity;
private TestEditUserInfoController mController;
public class TestEditUserInfoController extends EditUserInfoController {
private EditUserPhotoController mPhotoController;
TestEditUserInfoController() {
super("file_authority");
}
private EditUserPhotoController getPhotoController() {
return mPhotoController;
}
@Override
EditUserPhotoController createEditUserPhotoController(Activity activity,
ActivityStarter activityStarter, ImageView userPhotoView) {
mPhotoController = mock(EditUserPhotoController.class, Answers.RETURNS_DEEP_STUBS);
return mPhotoController;
}
@Override
RestrictedLockUtils.EnforcedAdmin getChangePhotoAdminRestriction(Context context) {
return null;
}
@Override
boolean isChangePhotoRestrictedByBase(Context context) {
return mPhotoRestrictedByBase;
}
}
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mActivity = spy(ActivityController.of(new FragmentActivity()).get());
mActivity.setTheme(androidx.appcompat.R.style.Theme_AppCompat_DayNight);
mController = new TestEditUserInfoController();
mPhotoRestrictedByBase = false;
}
@Test
public void photoControllerOnActivityResult_whenWaiting_isCalled() {
mController.createDialog(mActivity, mActivityStarter, mCurrentIcon, "test user",
null, null);
mController.startingActivityForResult();
Intent resultData = new Intent();
mController.onActivityResult(0, 0, resultData);
EditUserPhotoController photoController = mController.getPhotoController();
assertThat(photoController).isNotNull();
verify(photoController).onActivityResult(0, 0, resultData);
}
@Test
@Config(shadows = ShadowDialog.class)
public void userNameView_inputLongName_shouldBeConstrained() {
// generate a string of 200 'A's
final String longName = Stream.generate(
() -> String.valueOf('A')).limit(200).collect(Collectors.joining());
final AlertDialog dialog = (AlertDialog) mController.createDialog(mActivity,
mActivityStarter, mCurrentIcon, "test user", null, null);
dialog.show();
final EditText userNameEditText = dialog.findViewById(R.id.user_name);
userNameEditText.setText(longName);
assertThat(userNameEditText.getText().length()).isEqualTo(MAX_USER_NAME_LENGTH);
}
@Test
public void cancelCallback_isCalled_whenCancelled() {
BiConsumer<String, Drawable> successCallback = mock(BiConsumer.class);
Runnable cancelCallback = mock(Runnable.class);
AlertDialog dialog = (AlertDialog) mController.createDialog(
mActivity, mActivityStarter, mCurrentIcon, "test",
successCallback, cancelCallback);
dialog.show();
dialog.cancel();
verifyNoInteractions(successCallback);
verify(cancelCallback, times(1))
.run();
}
@Test
public void cancelCallback_isCalled_whenNegativeClicked() {
BiConsumer<String, Drawable> successCallback = mock(BiConsumer.class);
Runnable cancelCallback = mock(Runnable.class);
AlertDialog dialog = (AlertDialog) mController.createDialog(
mActivity, mActivityStarter, mCurrentIcon, "test",
successCallback, cancelCallback);
dialog.show();
dialog.findViewById(R.id.button_back).performClick();
verifyNoInteractions(successCallback);
verify(cancelCallback, times(1))
.run();
}
@Test
public void successCallback_isCalled_whenNothingChanged() {
BiConsumer<String, Drawable> successCallback = mock(BiConsumer.class);
Runnable cancelCallback = mock(Runnable.class);
Drawable oldUserIcon = mCurrentIcon;
AlertDialog dialog = (AlertDialog) mController.createDialog(
mActivity, mActivityStarter, oldUserIcon, "test",
successCallback, cancelCallback);
// No change to the photo.
when(mController.getPhotoController().getNewUserPhotoDrawable()).thenReturn(null);
dialog.show();
dialog.findViewById(R.id.button_ok).performClick();
verify(successCallback, times(1))
.accept("test", oldUserIcon);
verifyNoInteractions(cancelCallback);
}
@Test
public void successCallback_calledWithNullIcon_whenOldIconIsNullAndNothingChanged() {
BiConsumer<String, Drawable> successCallback = mock(BiConsumer.class);
Runnable cancelCallback = mock(Runnable.class);
AlertDialog dialog = (AlertDialog) mController.createDialog(
mActivity, mActivityStarter, null, "test",
successCallback, cancelCallback);
// No change to the photo.
when(mController.getPhotoController().getNewUserPhotoDrawable()).thenReturn(null);
dialog.show();
dialog.findViewById(R.id.button_ok).performClick();
verify(successCallback, times(1))
.accept("test", null);
verifyNoInteractions(cancelCallback);
}
@Test
public void successCallback_isCalled_whenLabelChanges() {
BiConsumer<String, Drawable> successCallback = mock(BiConsumer.class);
Runnable cancelCallback = mock(Runnable.class);
AlertDialog dialog = (AlertDialog) mController.createDialog(
mActivity, mActivityStarter, mCurrentIcon, "test",
successCallback, cancelCallback);
// No change to the photo.
when(mController.getPhotoController().getNewUserPhotoDrawable()).thenReturn(null);
dialog.show();
String expectedNewName = "new test user";
EditText editText = (EditText) dialog.findViewById(R.id.user_name);
editText.setText(expectedNewName);
dialog.findViewById(R.id.button_ok).performClick();
verify(successCallback, times(1))
.accept(expectedNewName, mCurrentIcon);
verifyNoInteractions(cancelCallback);
}
@Test
public void successCallback_isCalled_whenPhotoChanges() {
BiConsumer<String, Drawable> successCallback = mock(BiConsumer.class);
Runnable cancelCallback = mock(Runnable.class);
AlertDialog dialog = (AlertDialog) mController.createDialog(
mActivity, mActivityStarter, mCurrentIcon, "test",
successCallback, cancelCallback);
// A different drawable.
Drawable newPhoto = mock(Drawable.class);
when(mController.getPhotoController().getNewUserPhotoDrawable()).thenReturn(newPhoto);
dialog.show();
dialog.findViewById(R.id.button_ok).performClick();
verify(successCallback, times(1))
.accept("test", newPhoto);
verifyNoInteractions(cancelCallback);
}
@Test
public void successCallback_isCalledWithChangedPhoto_whenOldIconIsNullAndPhotoChanges() {
BiConsumer<String, Drawable> successCallback = mock(BiConsumer.class);
Runnable cancelCallback = mock(Runnable.class);
AlertDialog dialog = (AlertDialog) mController.createDialog(
mActivity, mActivityStarter, null, "test",
successCallback, cancelCallback);
// A different drawable.
Drawable newPhoto = mock(Drawable.class);
when(mController.getPhotoController().getNewUserPhotoDrawable()).thenReturn(newPhoto);
dialog.show();
dialog.findViewById(R.id.button_ok).performClick();
verify(successCallback, times(1))
.accept("test", newPhoto);
verifyNoInteractions(cancelCallback);
}
@Test
public void createDialog_canNotChangePhoto_nullPhotoController() {
mPhotoRestrictedByBase = true;
mController.createDialog(mActivity, mActivityStarter, mCurrentIcon,
"test", null, null);
assertThat(mController.mPhotoController).isNull();
}
}