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