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.systemui.qs.user 18 19 import android.content.DialogInterface 20 import android.content.Intent 21 import android.provider.Settings 22 import android.widget.Button 23 import androidx.test.ext.junit.runners.AndroidJUnit4 24 import androidx.test.filters.SmallTest 25 import com.android.internal.logging.UiEventLogger 26 import com.android.systemui.SysuiTestCase 27 import com.android.systemui.animation.DialogTransitionAnimator 28 import com.android.systemui.animation.Expandable 29 import com.android.systemui.plugins.ActivityStarter 30 import com.android.systemui.plugins.FalsingManager 31 import com.android.systemui.qs.PseudoGridView 32 import com.android.systemui.qs.QSUserSwitcherEvent 33 import com.android.systemui.qs.tiles.UserDetailView 34 import com.android.systemui.statusbar.phone.SystemUIDialog 35 import com.android.systemui.util.mockito.any 36 import com.android.systemui.util.mockito.capture 37 import com.android.systemui.util.mockito.eq 38 import com.android.systemui.util.mockito.mock 39 import com.android.systemui.util.mockito.whenever 40 import org.junit.Before 41 import org.junit.Test 42 import org.junit.runner.RunWith 43 import org.mockito.ArgumentCaptor 44 import org.mockito.ArgumentMatcher 45 import org.mockito.Captor 46 import org.mockito.Mock 47 import org.mockito.Mockito.anyBoolean 48 import org.mockito.Mockito.anyInt 49 import org.mockito.Mockito.argThat 50 import org.mockito.Mockito.never 51 import org.mockito.Mockito.verify 52 import org.mockito.Mockito.`when` 53 import org.mockito.MockitoAnnotations 54 55 @SmallTest 56 @RunWith(AndroidJUnit4::class) 57 class UserSwitchDialogControllerTest : SysuiTestCase() { 58 59 @Mock 60 private lateinit var dialogFactory: SystemUIDialog.Factory 61 @Mock 62 private lateinit var dialog: SystemUIDialog 63 @Mock 64 private lateinit var falsingManager: FalsingManager 65 @Mock 66 private lateinit var activityStarter: ActivityStarter 67 @Mock 68 private lateinit var userDetailViewAdapter: UserDetailView.Adapter 69 @Mock 70 private lateinit var launchExpandable: Expandable 71 @Mock 72 private lateinit var neutralButton: Button 73 @Mock 74 private lateinit var mDialogTransitionAnimator: DialogTransitionAnimator 75 @Mock 76 private lateinit var uiEventLogger: UiEventLogger 77 @Captor 78 private lateinit var clickCaptor: ArgumentCaptor<DialogInterface.OnClickListener> 79 80 private lateinit var controller: UserSwitchDialogController 81 82 @Before setUpnull83 fun setUp() { 84 MockitoAnnotations.initMocks(this) 85 86 whenever(dialog.context).thenReturn(mContext) 87 whenever(dialogFactory.create()).thenReturn(dialog) 88 89 controller = UserSwitchDialogController( 90 { userDetailViewAdapter }, 91 activityStarter, 92 falsingManager, 93 mDialogTransitionAnimator, 94 uiEventLogger, 95 dialogFactory 96 ) 97 } 98 99 @Test showDialog_callsDialogShownull100 fun showDialog_callsDialogShow() { 101 val launchController = mock<DialogTransitionAnimator.Controller>() 102 `when`(launchExpandable.dialogTransitionController(any())).thenReturn(launchController) 103 controller.showDialog(context, launchExpandable) 104 verify(mDialogTransitionAnimator).show(eq(dialog), eq(launchController), anyBoolean()) 105 verify(uiEventLogger).log(QSUserSwitcherEvent.QS_USER_DETAIL_OPEN) 106 } 107 108 @Test dialog_showForAllUsersnull109 fun dialog_showForAllUsers() { 110 controller.showDialog(context, launchExpandable) 111 verify(dialog).setShowForAllUsers(true) 112 } 113 114 @Test dialog_cancelOnTouchOutsidenull115 fun dialog_cancelOnTouchOutside() { 116 controller.showDialog(context, launchExpandable) 117 verify(dialog).setCanceledOnTouchOutside(true) 118 } 119 120 @Test adapterAndGridLinkednull121 fun adapterAndGridLinked() { 122 controller.showDialog(context, launchExpandable) 123 verify(userDetailViewAdapter).linkToViewGroup(any<PseudoGridView>()) 124 } 125 126 @Test doneButtonLogsCorrectlynull127 fun doneButtonLogsCorrectly() { 128 controller.showDialog(context, launchExpandable) 129 130 verify(dialog).setPositiveButton(anyInt(), capture(clickCaptor)) 131 132 clickCaptor.value.onClick(dialog, DialogInterface.BUTTON_NEUTRAL) 133 134 verify(uiEventLogger).log(QSUserSwitcherEvent.QS_USER_DETAIL_CLOSE) 135 } 136 137 @Test clickSettingsButton_noFalsing_opensSettingsnull138 fun clickSettingsButton_noFalsing_opensSettings() { 139 `when`(falsingManager.isFalseTap(anyInt())).thenReturn(false) 140 141 controller.showDialog(context, launchExpandable) 142 143 verify(dialog) 144 .setNeutralButton(anyInt(), capture(clickCaptor), eq(false) /* dismissOnClick */) 145 `when`(dialog.getButton(DialogInterface.BUTTON_NEUTRAL)).thenReturn(neutralButton) 146 147 clickCaptor.value.onClick(dialog, DialogInterface.BUTTON_NEUTRAL) 148 149 verify(activityStarter) 150 .postStartActivityDismissingKeyguard( 151 argThat(IntentMatcher(Settings.ACTION_USER_SETTINGS)), 152 eq(0), 153 eq(null) 154 ) 155 verify(uiEventLogger).log(QSUserSwitcherEvent.QS_USER_MORE_SETTINGS) 156 } 157 158 @Test clickSettingsButton_Falsing_notOpensSettingsnull159 fun clickSettingsButton_Falsing_notOpensSettings() { 160 `when`(falsingManager.isFalseTap(anyInt())).thenReturn(true) 161 162 controller.showDialog(context, launchExpandable) 163 164 verify(dialog) 165 .setNeutralButton(anyInt(), capture(clickCaptor), eq(false) /* dismissOnClick */) 166 167 clickCaptor.value.onClick(dialog, DialogInterface.BUTTON_NEUTRAL) 168 169 verify(activityStarter, never()).postStartActivityDismissingKeyguard(any(), anyInt()) 170 } 171 172 private class IntentMatcher(private val action: String) : ArgumentMatcher<Intent> { matchesnull173 override fun matches(argument: Intent?): Boolean { 174 return argument?.action == action 175 } 176 } 177 } 178