1 /*
2  * Copyright (C) 2020 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;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.mockito.Mockito.any;
22 import static org.mockito.Mockito.anyInt;
23 import static org.mockito.Mockito.never;
24 import static org.mockito.Mockito.verify;
25 import static org.mockito.Mockito.verifyZeroInteractions;
26 import static org.mockito.Mockito.when;
27 
28 import android.content.ClipData;
29 import android.content.ClipboardManager;
30 import android.testing.TestableLooper;
31 import android.view.View;
32 import android.widget.TextView;
33 
34 import androidx.test.ext.junit.runners.AndroidJUnit4;
35 import androidx.test.filters.SmallTest;
36 
37 import com.android.systemui.plugins.ActivityStarter;
38 import com.android.systemui.plugins.FalsingManager;
39 import com.android.systemui.res.R;
40 import com.android.systemui.retail.data.repository.FakeRetailModeRepository;
41 import com.android.systemui.retail.domain.interactor.RetailModeInteractorImpl;
42 import com.android.systemui.settings.UserTracker;
43 import com.android.systemui.utils.leaks.LeakCheckedTest;
44 
45 import org.junit.Before;
46 import org.junit.Test;
47 import org.junit.runner.RunWith;
48 import org.mockito.ArgumentCaptor;
49 import org.mockito.Mock;
50 import org.mockito.MockitoAnnotations;
51 
52 @RunWith(AndroidJUnit4.class)
53 @TestableLooper.RunWithLooper
54 @SmallTest
55 public class QSFooterViewControllerTest extends LeakCheckedTest {
56 
57     @Mock
58     private QSFooterView mView;
59     @Mock
60     private UserTracker mUserTracker;
61     @Mock
62     private QSPanelController mQSPanelController;
63     @Mock
64     private ClipboardManager mClipboardManager;
65     @Mock
66     private TextView mBuildText;
67     @Mock
68     private FalsingManager mFalsingManager;
69     @Mock
70     private ActivityStarter mActivityStarter;
71 
72     private FakeRetailModeRepository mRetailModeRepository;
73 
74     private QSFooterViewController mController;
75     private View mEditButton;
76 
77     @Before
setup()78     public void setup() throws Exception {
79         MockitoAnnotations.initMocks(this);
80 
81         mRetailModeRepository = new FakeRetailModeRepository();
82         mRetailModeRepository.setRetailMode(false);
83 
84         mEditButton = new View(mContext);
85 
86         injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
87 
88         mContext.addMockSystemService(ClipboardManager.class, mClipboardManager);
89 
90         when(mView.getContext()).thenReturn(mContext);
91         when(mView.getResources()).thenReturn(mContext.getResources());
92         when(mUserTracker.getUserContext()).thenReturn(mContext);
93 
94         when(mView.isAttachedToWindow()).thenReturn(true);
95         when(mView.findViewById(R.id.build)).thenReturn(mBuildText);
96         when(mView.findViewById(android.R.id.edit)).thenReturn(mEditButton);
97 
98         mController = new QSFooterViewController(mView, mUserTracker, mFalsingManager,
99                 mActivityStarter, mQSPanelController,
100                 new RetailModeInteractorImpl(mRetailModeRepository));
101 
102         mController.init();
103     }
104 
105     @Test
testBuildTextCopy()106     public void testBuildTextCopy() {
107         String text = "TEST";
108         ArgumentCaptor<View.OnLongClickListener> onLongClickCaptor =
109                 ArgumentCaptor.forClass(View.OnLongClickListener.class);
110 
111         verify(mBuildText).setOnLongClickListener(onLongClickCaptor.capture());
112 
113         when(mBuildText.getText()).thenReturn(text);
114         onLongClickCaptor.getValue().onLongClick(mBuildText);
115 
116         ArgumentCaptor<ClipData> captor = ArgumentCaptor.forClass(ClipData.class);
117         verify(mClipboardManager).setPrimaryClip(captor.capture());
118         assertThat(captor.getValue().getItemAt(0).getText()).isEqualTo(text);
119     }
120 
121     @Test
testEditButton_falseTap()122     public void testEditButton_falseTap() {
123         when(mFalsingManager.isFalseTap(anyInt())).thenReturn(true);
124 
125         mEditButton.performClick();
126 
127         verify(mQSPanelController, never()).showEdit(any());
128         verifyZeroInteractions(mActivityStarter);
129     }
130 
131     @Test
testEditButton_realTap()132     public void testEditButton_realTap() {
133         when(mFalsingManager.isFalseTap(anyInt())).thenReturn(false);
134 
135         mEditButton.performClick();
136 
137         ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class);
138 
139         verify(mActivityStarter).postQSRunnableDismissingKeyguard(captor.capture());
140         captor.getValue().run();
141         verify(mQSPanelController).showEdit(mEditButton);
142     }
143 
144     @Test
testEditButton_notRetailMode_visible()145     public void testEditButton_notRetailMode_visible() {
146         mRetailModeRepository.setRetailMode(false);
147 
148         mController.setVisibility(View.VISIBLE);
149         assertThat(mEditButton.getVisibility()).isEqualTo(View.VISIBLE);
150     }
151 
152     @Test
testEditButton_retailMode_notVisible()153     public void testEditButton_retailMode_notVisible() {
154         mRetailModeRepository.setRetailMode(true);
155 
156         mController.setVisibility(View.VISIBLE);
157         assertThat(mEditButton.getVisibility()).isEqualTo(View.GONE);
158     }
159 }
160