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 package com.android.settings.accounts; 17 18 import static org.mockito.Answers.RETURNS_DEEP_STUBS; 19 import static org.mockito.ArgumentMatchers.nullable; 20 import static org.mockito.Matchers.any; 21 import static org.mockito.Matchers.anyInt; 22 import static org.mockito.Matchers.eq; 23 import static org.mockito.Mockito.mock; 24 import static org.mockito.Mockito.never; 25 import static org.mockito.Mockito.verify; 26 import static org.mockito.Mockito.when; 27 28 import android.accounts.Account; 29 import android.accounts.AccountManager; 30 import android.accounts.AccountManagerCallback; 31 import android.accounts.AuthenticatorDescription; 32 import android.app.Activity; 33 import android.app.FragmentManager; 34 import android.app.FragmentTransaction; 35 import android.content.ComponentName; 36 import android.content.Context; 37 import android.os.Bundle; 38 import android.os.Handler; 39 import android.os.UserHandle; 40 import android.os.UserManager; 41 import android.support.v14.preference.PreferenceFragment; 42 import android.support.v7.preference.PreferenceManager; 43 import android.support.v7.preference.PreferenceScreen; 44 import android.widget.Button; 45 46 import com.android.settings.R; 47 import com.android.settings.applications.LayoutPreference; 48 import com.android.settings.testutils.SettingsRobolectricTestRunner; 49 import com.android.settings.testutils.shadow.ShadowAccountManager; 50 import com.android.settings.testutils.shadow.ShadowContentResolver; 51 import com.android.settings.testutils.shadow.ShadowDevicePolicyManager; 52 import com.android.settings.testutils.shadow.ShadowUserManager; 53 54 import org.junit.Before; 55 import org.junit.Test; 56 import org.junit.runner.RunWith; 57 import org.mockito.Mock; 58 import org.mockito.MockitoAnnotations; 59 import org.robolectric.RuntimeEnvironment; 60 import org.robolectric.annotation.Config; 61 import org.robolectric.shadows.ShadowApplication; 62 63 import java.util.ArrayList; 64 import java.util.List; 65 66 @RunWith(SettingsRobolectricTestRunner.class) 67 @Config(shadows = { 68 ShadowUserManager.class, 69 ShadowDevicePolicyManager.class 70 }) 71 public class RemoveAccountPreferenceControllerTest { 72 73 private static final String KEY_REMOVE_ACCOUNT = "remove_account"; 74 private static final String TAG_REMOVE_ACCOUNT_DIALOG = "confirmRemoveAccount"; 75 76 @Mock(answer = RETURNS_DEEP_STUBS) 77 private AccountManager mAccountManager; 78 @Mock 79 private PreferenceFragment mFragment; 80 @Mock 81 private PreferenceManager mPreferenceManager; 82 @Mock 83 private PreferenceScreen mScreen; 84 @Mock 85 private FragmentManager mFragmentManager; 86 @Mock 87 private FragmentTransaction mFragmentTransaction; 88 @Mock 89 private LayoutPreference mPreference; 90 91 private RemoveAccountPreferenceController mController; 92 93 @Before 94 public void setUp() { 95 MockitoAnnotations.initMocks(this); 96 ShadowApplication.getInstance().setSystemService(Context.ACCOUNT_SERVICE, mAccountManager); 97 98 when(mFragment.getPreferenceScreen()).thenReturn(mScreen); 99 when(mFragment.getPreferenceManager()).thenReturn(mPreferenceManager); 100 when(mPreferenceManager.getContext()).thenReturn(RuntimeEnvironment.application); 101 when(mFragment.getFragmentManager()).thenReturn(mFragmentManager); 102 when(mFragmentManager.beginTransaction()).thenReturn(mFragmentTransaction); 103 when(mAccountManager.getAuthenticatorTypesAsUser(anyInt())) 104 .thenReturn(new AuthenticatorDescription[0]); 105 when(mAccountManager.getAccountsAsUser(anyInt())).thenReturn(new Account[0]); 106 mController = new RemoveAccountPreferenceController(RuntimeEnvironment.application, 107 mFragment); 108 } 109 110 @Test 111 public void displayPreference_shouldAddClickListener() { 112 when(mScreen.findPreference(KEY_REMOVE_ACCOUNT)).thenReturn(mPreference); 113 final Button button = mock(Button.class); 114 when(mPreference.findViewById(R.id.button)).thenReturn(button); 115 116 mController.displayPreference(mScreen); 117 118 verify(button).setOnClickListener(mController); 119 } 120 121 @Test 122 public void onClick_shouldStartConfirmDialog() { 123 when(mFragment.isAdded()).thenReturn(true); 124 mController.onClick(null); 125 126 verify(mFragmentTransaction).add( 127 any(RemoveAccountPreferenceController.ConfirmRemoveAccountDialog.class), 128 eq(TAG_REMOVE_ACCOUNT_DIALOG)); 129 } 130 131 @Test 132 public void onClick_shouldNotStartConfirmDialogWhenModifyAccountsIsDisallowed() { 133 when(mFragment.isAdded()).thenReturn(true); 134 135 final int userId = UserHandle.myUserId(); 136 mController.init(new Account("test", "test"), UserHandle.of(userId)); 137 138 List<UserManager.EnforcingUser> enforcingUsers = new ArrayList<>(); 139 enforcingUsers.add(new UserManager.EnforcingUser(userId, 140 UserManager.RESTRICTION_SOURCE_DEVICE_OWNER)); 141 ComponentName componentName = new ComponentName("test", "test"); 142 // Ensure that RestrictedLockUtils.checkIfRestrictionEnforced doesn't return null. 143 ShadowUserManager.getShadow().setUserRestrictionSources( 144 UserManager.DISALLOW_MODIFY_ACCOUNTS, 145 UserHandle.of(userId), 146 enforcingUsers); 147 ShadowDevicePolicyManager.getShadow().setDeviceOwnerComponentOnAnyUser(componentName); 148 149 mController.onClick(null); 150 151 verify(mFragmentTransaction, never()).add( 152 any(RemoveAccountPreferenceController.ConfirmRemoveAccountDialog.class), 153 eq(TAG_REMOVE_ACCOUNT_DIALOG)); 154 } 155 156 @Test 157 @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) 158 public void confirmRemove_shouldRemoveAccount() { 159 when(mFragment.isAdded()).thenReturn(true); 160 Activity activity = mock(Activity.class); 161 when(activity.getSystemService(Context.ACCOUNT_SERVICE)).thenReturn(mAccountManager); 162 when(mFragment.getActivity()).thenReturn(activity); 163 164 Account account = new Account("Account11", "com.acct1"); 165 UserHandle userHandle = new UserHandle(10); 166 RemoveAccountPreferenceController.ConfirmRemoveAccountDialog dialog = 167 RemoveAccountPreferenceController.ConfirmRemoveAccountDialog.show( 168 mFragment, account, userHandle); 169 dialog.onCreate(new Bundle()); 170 dialog.onClick(null, 0); 171 verify(mAccountManager).removeAccountAsUser(eq(account), nullable(Activity.class), 172 nullable(AccountManagerCallback.class), nullable(Handler.class), eq(userHandle)); 173 } 174 } 175