1 /*
2  * Copyright (C) 2023 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.launcher3.taskbar;
17 
18 import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
19 
20 import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_HOVERING_ICONS;
21 
22 import static com.google.common.truth.Truth.assertThat;
23 
24 import static org.mockito.ArgumentMatchers.any;
25 import static org.mockito.ArgumentMatchers.anyInt;
26 import static org.mockito.ArgumentMatchers.anyString;
27 import static org.mockito.Mockito.doAnswer;
28 import static org.mockito.Mockito.doReturn;
29 import static org.mockito.Mockito.spy;
30 import static org.mockito.Mockito.verify;
31 import static org.mockito.Mockito.when;
32 
33 import android.content.Context;
34 import android.testing.AndroidTestingRunner;
35 import android.testing.TestableLooper;
36 import android.view.Display;
37 import android.view.MotionEvent;
38 
39 import androidx.test.filters.SmallTest;
40 
41 import com.android.launcher3.BubbleTextView;
42 import com.android.launcher3.folder.Folder;
43 import com.android.launcher3.folder.FolderIcon;
44 import com.android.launcher3.model.data.FolderInfo;
45 import com.android.launcher3.util.ActivityContextWrapper;
46 
47 import org.junit.Before;
48 import org.junit.Test;
49 import org.junit.runner.RunWith;
50 import org.mockito.Mock;
51 import org.mockito.MockitoAnnotations;
52 import org.mockito.stubbing.Answer;
53 
54 /**
55  * Tests for TaskbarHoverToolTipController.
56  */
57 @SmallTest
58 @RunWith(AndroidTestingRunner.class)
59 @TestableLooper.RunWithLooper(setAsMainLooper = true)
60 public class TaskbarHoverToolTipControllerTest extends TaskbarBaseTestCase {
61 
62     private TaskbarHoverToolTipController mTaskbarHoverToolTipController;
63     private TestableLooper mTestableLooper;
64 
65     @Mock private TaskbarView mTaskbarView;
66     @Mock private MotionEvent mMotionEvent;
67     @Mock private BubbleTextView mHoverBubbleTextView;
68     @Mock private FolderIcon mHoverFolderIcon;
69     @Mock private Display mDisplay;
70     @Mock private TaskbarDragLayer mTaskbarDragLayer;
71     private Folder mSpyFolderView;
72 
73     @Before
setup()74     public void setup() {
75         MockitoAnnotations.initMocks(this);
76 
77         Context context = getApplicationContext();
78 
79         doAnswer((Answer<Object>) invocation -> context.getSystemService(
80                 (String) invocation.getArgument(0)))
81                 .when(taskbarActivityContext).getSystemService(anyString());
82         when(taskbarActivityContext.getResources()).thenReturn(context.getResources());
83         when(taskbarActivityContext.getApplicationInfo()).thenReturn(
84                 context.getApplicationInfo());
85         when(taskbarActivityContext.getDragLayer()).thenReturn(mTaskbarDragLayer);
86         when(taskbarActivityContext.getMainLooper()).thenReturn(context.getMainLooper());
87         when(taskbarActivityContext.getDisplay()).thenReturn(mDisplay);
88 
89         when(mTaskbarDragLayer.getChildCount()).thenReturn(1);
90         mSpyFolderView = spy(new Folder(new ActivityContextWrapper(context), null));
91         when(mTaskbarDragLayer.getChildAt(anyInt())).thenReturn(mSpyFolderView);
92         doReturn(false).when(mSpyFolderView).isOpen();
93 
94         when(mHoverBubbleTextView.getText()).thenReturn("tooltip");
95         doAnswer((Answer<Void>) invocation -> {
96             Object[] args = invocation.getArguments();
97             ((int[]) args[0])[0] = 0;
98             ((int[]) args[0])[1] = 0;
99             return null;
100         }).when(mHoverBubbleTextView).getLocationOnScreen(any(int[].class));
101         when(mHoverBubbleTextView.getWidth()).thenReturn(100);
102         when(mHoverBubbleTextView.getHeight()).thenReturn(100);
103 
104         mHoverFolderIcon.mInfo = new FolderInfo();
105         mHoverFolderIcon.mInfo.title = "tooltip";
106         doAnswer((Answer<Void>) invocation -> {
107             Object[] args = invocation.getArguments();
108             ((int[]) args[0])[0] = 0;
109             ((int[]) args[0])[1] = 0;
110             return null;
111         }).when(mHoverFolderIcon).getLocationOnScreen(any(int[].class));
112         when(mHoverFolderIcon.getWidth()).thenReturn(100);
113         when(mHoverFolderIcon.getHeight()).thenReturn(100);
114 
115         when(mTaskbarView.getTop()).thenReturn(200);
116 
117         mTaskbarHoverToolTipController = new TaskbarHoverToolTipController(
118                 taskbarActivityContext, mTaskbarView, mHoverBubbleTextView);
119         mTestableLooper = TestableLooper.get(this);
120     }
121 
122     @Test
onHover_hoverEnterIcon_revealToolTip()123     public void onHover_hoverEnterIcon_revealToolTip() {
124         when(mMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_HOVER_ENTER);
125         when(mMotionEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_HOVER_ENTER);
126 
127         boolean hoverHandled =
128                 mTaskbarHoverToolTipController.onHover(mHoverBubbleTextView, mMotionEvent);
129         waitForIdleSync();
130 
131         assertThat(hoverHandled).isTrue();
132         verify(taskbarActivityContext).setAutohideSuspendFlag(FLAG_AUTOHIDE_SUSPEND_HOVERING_ICONS,
133                 true);
134     }
135 
136     @Test
onHover_hoverExitIcon_closeToolTip()137     public void onHover_hoverExitIcon_closeToolTip() {
138         when(mMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_HOVER_EXIT);
139         when(mMotionEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_HOVER_EXIT);
140 
141         boolean hoverHandled =
142                 mTaskbarHoverToolTipController.onHover(mHoverBubbleTextView, mMotionEvent);
143         waitForIdleSync();
144 
145         assertThat(hoverHandled).isTrue();
146         verify(taskbarActivityContext).setAutohideSuspendFlag(FLAG_AUTOHIDE_SUSPEND_HOVERING_ICONS,
147                 false);
148     }
149 
150     @Test
onHover_hoverEnterFolderIcon_revealToolTip()151     public void onHover_hoverEnterFolderIcon_revealToolTip() {
152         when(mMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_HOVER_ENTER);
153         when(mMotionEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_HOVER_ENTER);
154 
155         boolean hoverHandled =
156                 mTaskbarHoverToolTipController.onHover(mHoverFolderIcon, mMotionEvent);
157         waitForIdleSync();
158 
159         assertThat(hoverHandled).isTrue();
160         verify(taskbarActivityContext).setAutohideSuspendFlag(FLAG_AUTOHIDE_SUSPEND_HOVERING_ICONS,
161                 true);
162     }
163 
164     @Test
onHover_hoverExitFolderIcon_closeToolTip()165     public void onHover_hoverExitFolderIcon_closeToolTip() {
166         when(mMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_HOVER_EXIT);
167         when(mMotionEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_HOVER_EXIT);
168 
169         boolean hoverHandled =
170                 mTaskbarHoverToolTipController.onHover(mHoverFolderIcon, mMotionEvent);
171         waitForIdleSync();
172 
173         assertThat(hoverHandled).isTrue();
174         verify(taskbarActivityContext).setAutohideSuspendFlag(FLAG_AUTOHIDE_SUSPEND_HOVERING_ICONS,
175                 false);
176     }
177 
178     @Test
onHover_hoverExitFolderOpen_closeToolTip()179     public void onHover_hoverExitFolderOpen_closeToolTip() {
180         when(mMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_HOVER_EXIT);
181         when(mMotionEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_HOVER_EXIT);
182         doReturn(true).when(mSpyFolderView).isOpen();
183 
184         boolean hoverHandled =
185                 mTaskbarHoverToolTipController.onHover(mHoverFolderIcon, mMotionEvent);
186         waitForIdleSync();
187 
188         assertThat(hoverHandled).isTrue();
189         verify(taskbarActivityContext).setAutohideSuspendFlag(FLAG_AUTOHIDE_SUSPEND_HOVERING_ICONS,
190                 false);
191     }
192 
193     @Test
onHover_hoverEnterFolderOpen_noToolTip()194     public void onHover_hoverEnterFolderOpen_noToolTip() {
195         when(mMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_HOVER_ENTER);
196         when(mMotionEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_HOVER_ENTER);
197         doReturn(true).when(mSpyFolderView).isOpen();
198 
199         boolean hoverHandled =
200                 mTaskbarHoverToolTipController.onHover(mHoverFolderIcon, mMotionEvent);
201 
202         assertThat(hoverHandled).isFalse();
203     }
204 
205     @Test
onHover_hoverMove_noUpdate()206     public void onHover_hoverMove_noUpdate() {
207         when(mMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_HOVER_MOVE);
208         when(mMotionEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_HOVER_MOVE);
209 
210         boolean hoverHandled =
211                 mTaskbarHoverToolTipController.onHover(mHoverFolderIcon, mMotionEvent);
212 
213         assertThat(hoverHandled).isFalse();
214     }
215 
waitForIdleSync()216     private void waitForIdleSync() {
217         mTestableLooper.processAllMessages();
218     }
219 }
220