blob: 098fa62f40445b37375f1c1fd83c778e70e7525e [file] [log] [blame]
Aaron Heuckroth45d20be2018-09-18 13:47:26 -04001/*
2 * Copyright (C) 2018 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 * * http://www.apache.org/licenses/LICENSE-2.0 *
7 * Unless required by applicable law or agreed to in writing, software
8 * distributed under the License is distributed on an "AS IS" BASIS,
9 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 * See the License for the specific language governing permissions and
11 * limitations under the License
12 */
13
14package com.android.systemui.statusbar.notification.stack;
15
16import static junit.framework.Assert.assertEquals;
17import static junit.framework.Assert.assertFalse;
Aaron Heuckroth45d20be2018-09-18 13:47:26 -040018import static junit.framework.Assert.assertTrue;
19
20import static org.mockito.ArgumentMatchers.any;
Aaron Heuckroth45d20be2018-09-18 13:47:26 -040021import static org.mockito.Mockito.doAnswer;
22import static org.mockito.Mockito.doNothing;
23import static org.mockito.Mockito.doReturn;
24import static org.mockito.Mockito.mock;
Aaron Heuckroth45d20be2018-09-18 13:47:26 -040025import static org.mockito.Mockito.spy;
26import static org.mockito.Mockito.times;
27import static org.mockito.Mockito.verify;
28import static org.mockito.Mockito.when;
29
30import android.animation.Animator;
31import android.animation.ValueAnimator.AnimatorUpdateListener;
Aaron Heuckroth45d20be2018-09-18 13:47:26 -040032import android.os.Handler;
Aaron Heuckroth45d20be2018-09-18 13:47:26 -040033import android.service.notification.StatusBarNotification;
Aaron Heuckroth45d20be2018-09-18 13:47:26 -040034import android.support.test.filters.SmallTest;
35import android.support.test.runner.AndroidJUnit4;
Beverlyc4305e62018-11-06 14:45:30 -050036import android.testing.UiThreadTest;
Aaron Heuckroth45d20be2018-09-18 13:47:26 -040037import android.view.MotionEvent;
Aaron Heuckroth45d20be2018-09-18 13:47:26 -040038import android.view.View;
Aaron Heuckroth45d20be2018-09-18 13:47:26 -040039
40import com.android.systemui.SwipeHelper;
41import com.android.systemui.SysuiTestCase;
42import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
43import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
44import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
Aaron Heuckroth45d20be2018-09-18 13:47:26 -040045
Aaron Heuckroth45d20be2018-09-18 13:47:26 -040046import org.junit.Before;
47import org.junit.Rule;
48import org.junit.Test;
49import org.junit.runner.RunWith;
Aaron Heuckroth45d20be2018-09-18 13:47:26 -040050import org.mockito.junit.MockitoJUnit;
51import org.mockito.junit.MockitoRule;
52import org.mockito.stubbing.Answer;
53
Aaron Heuckroth45d20be2018-09-18 13:47:26 -040054/**
55 * Tests for {@link NotificationSwipeHelper}.
56 */
57@SmallTest
58@RunWith(AndroidJUnit4.class)
Beverlyc4305e62018-11-06 14:45:30 -050059@UiThreadTest
Aaron Heuckroth45d20be2018-09-18 13:47:26 -040060public class NotificationSwipeHelperTest extends SysuiTestCase {
61
62 private NotificationSwipeHelper mSwipeHelper;
63 private NotificationSwipeHelper.NotificationCallback mCallback;
64 private NotificationMenuRowPlugin.OnMenuEventListener mListener;
65 private View mView;
66 private MotionEvent mEvent;
67 private NotificationMenuRowPlugin mMenuRow;
68 private Handler mHandler;
69 private ExpandableNotificationRow mNotificationRow;
70 private Runnable mFalsingCheck;
71
72 @Rule public MockitoRule mockito = MockitoJUnit.rule();
73
74 @Before
Aaron Heuckroth45d20be2018-09-18 13:47:26 -040075 public void setUp() throws Exception {
76 mCallback = mock(NotificationSwipeHelper.NotificationCallback.class);
77 mListener = mock(NotificationMenuRowPlugin.OnMenuEventListener.class);
78 mSwipeHelper = spy(new NotificationSwipeHelper(SwipeHelper.X, mCallback, mContext, mListener));
79 mView = mock(View.class);
80 mEvent = mock(MotionEvent.class);
81 mMenuRow = mock(NotificationMenuRowPlugin.class);
82 mNotificationRow = mock(ExpandableNotificationRow.class);
83 mHandler = mock(Handler.class);
84 mFalsingCheck = mock(Runnable.class);
85 }
86
87 @Test
88 public void testSetExposedMenuView() {
89 assertEquals("intialized with null exposed menu view", null,
90 mSwipeHelper.getExposedMenuView());
91 mSwipeHelper.setExposedMenuView(mView);
92 assertEquals("swipe helper has correct exposedMenuView after setExposedMenuView to a view",
93 mView, mSwipeHelper.getExposedMenuView());
94 mSwipeHelper.setExposedMenuView(null);
95 assertEquals("swipe helper has null exposedMenuView after setExposedMenuView to null",
96 null, mSwipeHelper.getExposedMenuView());
97 }
98
99 @Test
100 public void testClearExposedMenuView() {
101 doNothing().when(mSwipeHelper).setExposedMenuView(mView);
102 mSwipeHelper.clearExposedMenuView();
103 verify(mSwipeHelper, times(1)).setExposedMenuView(null);
104 }
105
106 @Test
107 public void testGetTranslatingParentView() {
108 assertEquals("intialized with null translating parent view", null,
109 mSwipeHelper.getTranslatingParentView());
110 mSwipeHelper.setTranslatingParentView(mView);
111 assertEquals("has translating parent view after setTranslatingParentView with a view",
112 mView, mSwipeHelper.getTranslatingParentView());
113 }
114
115 @Test
116 public void testClearTranslatingParentView() {
117 doNothing().when(mSwipeHelper).setTranslatingParentView(null);
118 mSwipeHelper.clearTranslatingParentView();
119 verify(mSwipeHelper, times(1)).setTranslatingParentView(null);
120 }
121
122 @Test
123 public void testSetCurrentMenuRow() {
124 assertEquals("currentMenuRow initializes to null", null,
125 mSwipeHelper.getCurrentMenuRow());
126 mSwipeHelper.setCurrentMenuRow(mMenuRow);
127 assertEquals("currentMenuRow set correctly after setCurrentMenuRow", mMenuRow,
128 mSwipeHelper.getCurrentMenuRow());
129 mSwipeHelper.setCurrentMenuRow(null);
130 assertEquals("currentMenuRow set to null after setCurrentMenuRow to null",
131 null, mSwipeHelper.getCurrentMenuRow());
132 }
133
134 @Test
135 public void testClearCurrentMenuRow() {
136 doNothing().when(mSwipeHelper).setCurrentMenuRow(null);
137 mSwipeHelper.clearCurrentMenuRow();
138 verify(mSwipeHelper, times(1)).setCurrentMenuRow(null);
139 }
140
141 @Test
142 public void testOnDownUpdate_ExpandableNotificationRow() {
143 when(mSwipeHelper.getHandler()).thenReturn(mHandler);
144 when(mSwipeHelper.getFalsingCheck()).thenReturn(mFalsingCheck);
145 doNothing().when(mSwipeHelper).resetExposedMenuView(true, false);
146 doNothing().when(mSwipeHelper).clearCurrentMenuRow();
147 doNothing().when(mSwipeHelper).initializeRow(any());
148
149 mSwipeHelper.onDownUpdate(mNotificationRow, mEvent);
150
151 verify(mSwipeHelper, times(1)).clearCurrentMenuRow();
152 verify(mHandler, times(1)).removeCallbacks(mFalsingCheck);
153 verify(mSwipeHelper, times(1)).resetExposedMenuView(true, false);
154 verify(mSwipeHelper, times(1)).initializeRow(mNotificationRow);
155 }
156
157 @Test
158 public void testOnDownUpdate_notExpandableNotificationRow() {
159 when(mSwipeHelper.getHandler()).thenReturn(mHandler);
160 when(mSwipeHelper.getFalsingCheck()).thenReturn(mFalsingCheck);
161 doNothing().when(mSwipeHelper).resetExposedMenuView(true, false);
162 doNothing().when(mSwipeHelper).clearCurrentMenuRow();
163 doNothing().when(mSwipeHelper).initializeRow(any());
164
165 mSwipeHelper.onDownUpdate(mView, mEvent);
166
167 verify(mSwipeHelper, times(1)).clearCurrentMenuRow();
168 verify(mHandler, times(1)).removeCallbacks(mFalsingCheck);
169 verify(mSwipeHelper, times(1)).resetExposedMenuView(true, false);
170 verify(mSwipeHelper, times(0)).initializeRow(any());
171 }
172
173 @Test
174 public void testOnMoveUpdate_menuRow() {
175 when(mSwipeHelper.getCurrentMenuRow()).thenReturn(mMenuRow);
176 when(mSwipeHelper.getHandler()).thenReturn(mHandler);
177 when(mSwipeHelper.getFalsingCheck()).thenReturn(mFalsingCheck);
178
179 mSwipeHelper.onMoveUpdate(mView, mEvent, 0, 10);
180
181 verify(mHandler, times(1)).removeCallbacks(mFalsingCheck);
182 verify(mMenuRow, times(1)).onTouchMove(10);
183 }
184
185 @Test
186 public void testOnMoveUpdate_noMenuRow() {
187 when(mSwipeHelper.getHandler()).thenReturn(mHandler);
188 when(mSwipeHelper.getFalsingCheck()).thenReturn(mFalsingCheck);
189
190 mSwipeHelper.onMoveUpdate(mView, mEvent, 0, 10);
191
192 verify(mHandler, times(1)).removeCallbacks(mFalsingCheck);
193 }
194
195 @Test
196 public void testHandleUpEvent_noMenuRow() {
197 assertFalse("Menu row does not exist",
198 mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
199 }
200
201 @Test
202 public void testHandleUpEvent_menuRow() {
203 when(mSwipeHelper.getCurrentMenuRow()).thenReturn(mMenuRow);
204 doNothing().when(mSwipeHelper).handleMenuRowSwipe(mEvent, mView, 0, mMenuRow);
205
206 assertTrue("Menu row exists",
207 mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
208 verify(mMenuRow, times(1)).onTouchEnd();
209 verify(mSwipeHelper, times(1)).handleMenuRowSwipe(mEvent, mView, 0, mMenuRow);
210 }
211
212 @Test
213 public void testDismissChild_notExpanded() {
214 when(mCallback.isExpanded()).thenReturn(false);
215 doNothing().when(mSwipeHelper).superDismissChild(mView, 0, false);
216 doNothing().when(mSwipeHelper).handleMenuCoveredOrDismissed();
217
218 mSwipeHelper.dismissChild(mView, 0, false);
219
220 verify(mSwipeHelper, times(1)).superDismissChild(mView, 0, false);
221 verify(mCallback, times(0)).handleChildViewDismissed(mView);
222 verify(mCallback, times(1)).onDismiss();
223 verify(mSwipeHelper, times(1)).handleMenuCoveredOrDismissed();
224 }
225
226 @Test
227 public void testSnapchild_targetIsZero() {
228 doNothing().when(mSwipeHelper).superSnapChild(mView, 0, 0);
229 mSwipeHelper.snapChild(mView, 0, 0);
230
231 verify(mCallback, times(1)).onDragCancelled(mView);
232 verify(mSwipeHelper, times(1)).superSnapChild(mView, 0, 0);
233 verify(mSwipeHelper, times(1)).handleMenuCoveredOrDismissed();
234 }
235
236
237 @Test
238 public void testSnapchild_targetNotZero() {
239 doNothing().when(mSwipeHelper).superSnapChild(mView, 10, 0);
240 mSwipeHelper.snapChild(mView, 10, 0);
241
242 verify(mCallback, times(1)).onDragCancelled(mView);
243 verify(mSwipeHelper, times(1)).superSnapChild(mView, 10, 0);
244 verify(mSwipeHelper, times(0)).handleMenuCoveredOrDismissed();
245 }
246
247 @Test
248 public void testSnooze() {
249 StatusBarNotification sbn = mock(StatusBarNotification.class);
250 SnoozeOption snoozeOption = mock(SnoozeOption.class);
251 mSwipeHelper.snooze(sbn, snoozeOption);
252 verify(mCallback, times(1)).onSnooze(sbn, snoozeOption);
253 }
254
255 @Test
256 public void testGetViewTranslationAnimator_notExpandableNotificationRow() {
257 Animator animator = mock(Animator.class);
258 AnimatorUpdateListener listener = mock(AnimatorUpdateListener.class);
259 doReturn(animator).when(mSwipeHelper).superGetViewTranslationAnimator(mView, 0, listener);
260
261 assertEquals("returns the correct animator from super", animator,
262 mSwipeHelper.getViewTranslationAnimator(mView, 0, listener));
263
264 verify(mSwipeHelper, times(1)).superGetViewTranslationAnimator(mView, 0, listener);
265 }
266
267 @Test
268 public void testGetViewTranslationAnimator_expandableNotificationRow() {
269 Animator animator = mock(Animator.class);
270 AnimatorUpdateListener listener = mock(AnimatorUpdateListener.class);
271 doReturn(animator).when(mNotificationRow).getTranslateViewAnimator(0, listener);
272
273 assertEquals("returns the correct animator from super when view is an ENR", animator,
274 mSwipeHelper.getViewTranslationAnimator(mNotificationRow, 0, listener));
275
276 verify(mNotificationRow, times(1)).getTranslateViewAnimator(0, listener);
277 }
278
279 @Test
280 public void testSetTranslation() {
281 mSwipeHelper.setTranslation(mNotificationRow, 0);
282 verify(mNotificationRow, times(1)).setTranslation(0);
283 }
284
285 @Test
286 public void testGetTranslation() {
287 doReturn(30f).when(mNotificationRow).getTranslation();
288
289 assertEquals("Returns getTranslation for the ENR",
290 mSwipeHelper.getTranslation(mNotificationRow), 30f);
291
292 verify(mNotificationRow, times(1)).getTranslation();
293 }
294
295 @Test
296 public void testDismiss() {
297 doNothing().when(mSwipeHelper).dismissChild(mView, 0, true);
298 doReturn(false).when(mSwipeHelper).swipedFastEnough();
299
300 mSwipeHelper.dismiss(mView, 0);
301
302 verify(mSwipeHelper, times(1)).swipedFastEnough();
303 verify(mSwipeHelper, times(1)).dismissChild(mView, 0, true);
304 }
305
306 @Test
307 public void testSnapOpen() {
308 doNothing().when(mSwipeHelper).snapChild(mView, 30, 0);
309
310 mSwipeHelper.snapOpen(mView, 30, 0);
311
312 verify(mSwipeHelper, times(1)).snapChild(mView, 30, 0);
313 }
314
315 @Test
316 public void testSnapClosed() {
317 doNothing().when(mSwipeHelper).snapChild(mView, 0, 0);
318
319 mSwipeHelper.snapClosed(mView, 0);
320
321 verify(mSwipeHelper, times(1)).snapChild(mView, 0, 0);
322 }
323
324 @Test
325 public void testGetMinDismissVelocity() {
326 doReturn(30f).when(mSwipeHelper).getEscapeVelocity();
327
328 assertEquals("Returns getEscapeVelocity", 30f, mSwipeHelper.getMinDismissVelocity());
329 }
330
331 @Test
332 public void onMenuShown_noAntiFalsing() {
333 doNothing().when(mSwipeHelper).setExposedMenuView(mView);
334 doReturn(mView).when(mSwipeHelper).getTranslatingParentView();
335 doReturn(mHandler).when(mSwipeHelper).getHandler();
336 doReturn(false).when(mCallback).isAntiFalsingNeeded();
337 doReturn(mFalsingCheck).when(mSwipeHelper).getFalsingCheck();
338
339 mSwipeHelper.onMenuShown(mView);
340
341 verify(mSwipeHelper, times(1)).setExposedMenuView(mView);
342 verify(mCallback, times(1)).onDragCancelled(mView);
343 verify(mCallback, times(1)).isAntiFalsingNeeded();
344
345 verify(mHandler, times(0)).removeCallbacks(mFalsingCheck);
346 verify(mHandler, times(0)).postDelayed(mFalsingCheck, mSwipeHelper.COVER_MENU_DELAY);
347 }
348
349 @Test
350 public void onMenuShown_antiFalsing() {
351 doNothing().when(mSwipeHelper).setExposedMenuView(mView);
352 doReturn(mView).when(mSwipeHelper).getTranslatingParentView();
353 doReturn(mHandler).when(mSwipeHelper).getHandler();
354 doReturn(true).when(mCallback).isAntiFalsingNeeded();
355 doReturn(mFalsingCheck).when(mSwipeHelper).getFalsingCheck();
356
357 mSwipeHelper.onMenuShown(mView);
358
359 verify(mSwipeHelper, times(1)).setExposedMenuView(mView);
360 verify(mCallback, times(1)).onDragCancelled(mView);
361 verify(mCallback, times(1)).isAntiFalsingNeeded();
362
363 verify(mHandler, times(1)).removeCallbacks(mFalsingCheck);
364 verify(mHandler, times(1)).postDelayed(mFalsingCheck, mSwipeHelper.COVER_MENU_DELAY);
365 }
366
367 @Test
368 public void testResetExposedMenuView_noReset() {
369 doReturn(false).when(mSwipeHelper).shouldResetMenu(false);
370 doNothing().when(mSwipeHelper).clearExposedMenuView();
371
372 mSwipeHelper.resetExposedMenuView(false, false);
373
374 verify(mSwipeHelper, times(1)).shouldResetMenu(false);
375
376 // should not clear exposed menu row
377 verify(mSwipeHelper, times(0)).clearExposedMenuView();
378 }
379
380 @Test
381 public void testResetExposedMenuView_animate() {
382 Animator animator = mock(Animator.class);
383
384 doReturn(true).when(mSwipeHelper).shouldResetMenu(false);
385 doReturn(mNotificationRow).when(mSwipeHelper).getExposedMenuView();
386 doReturn(false).when(mNotificationRow).isRemoved();
387 doReturn(animator).when(mSwipeHelper).getViewTranslationAnimator(mNotificationRow, 0, null);
388 doNothing().when(mSwipeHelper).clearExposedMenuView();
389
390 mSwipeHelper.resetExposedMenuView(true, false);
391
392 verify(mSwipeHelper, times(1)).shouldResetMenu(false);
393
394 // should retrieve and start animator
395 verify(mSwipeHelper, times(1)).getViewTranslationAnimator(mNotificationRow, 0, null);
396 verify(animator, times(1)).start();
397
398 // should not reset translation on row directly
399 verify(mNotificationRow, times(0)).resetTranslation();
400
401 // should clear exposed menu row
402 verify(mSwipeHelper, times(1)).clearExposedMenuView();
403 }
404
405
406 @Test
407 public void testResetExposedMenuView_noAnimate() {
408 Animator animator = mock(Animator.class);
409
410 doReturn(true).when(mSwipeHelper).shouldResetMenu(false);
411 doReturn(mNotificationRow).when(mSwipeHelper).getExposedMenuView();
412 doReturn(false).when(mNotificationRow).isRemoved();
413 doReturn(animator).when(mSwipeHelper).getViewTranslationAnimator(mNotificationRow, 0, null);
414 doNothing().when(mSwipeHelper).clearExposedMenuView();
415
416 mSwipeHelper.resetExposedMenuView(false, false);
417
418 verify(mSwipeHelper, times(1)).shouldResetMenu(false);
419
420 // should not retrieve and start animator
421 verify(mSwipeHelper, times(0)).getViewTranslationAnimator(mNotificationRow, 0, null);
422 verify(animator, times(0)).start();
423
424 // should reset translation on row directly
425 verify(mNotificationRow, times(1)).resetTranslation();
426
427 // should clear exposed menu row
428 verify(mSwipeHelper, times(1)).clearExposedMenuView();
429 }
430
431 @Test
432 public void testIsTouchInView() {
433 assertEquals("returns false when view is null", false,
434 NotificationSwipeHelper.isTouchInView(mEvent, null));
435
436 doReturn(5f).when(mEvent).getRawX();
437 doReturn(10f).when(mEvent).getRawY();
438
439 doReturn(20).when(mView).getWidth();
440 doReturn(20).when(mView).getHeight();
441
442 Answer answer = (Answer) invocation -> {
443 int[] arr = invocation.getArgument(0);
444 arr[0] = 0;
445 arr[1] = 0;
446 return null;
447 };
448 doAnswer(answer).when(mView).getLocationOnScreen(any());
449
450 assertTrue("Touch is within the view",
451 mSwipeHelper.isTouchInView(mEvent, mView));
452
453 doReturn(50f).when(mEvent).getRawX();
454
455 assertFalse("Touch is not within the view",
456 mSwipeHelper.isTouchInView(mEvent, mView));
457 }
458
459 @Test
460 public void testIsTouchInView_expandable() {
461 assertEquals("returns false when view is null", false,
462 NotificationSwipeHelper.isTouchInView(mEvent, null));
463
464 doReturn(5f).when(mEvent).getRawX();
465 doReturn(10f).when(mEvent).getRawY();
466
467 doReturn(20).when(mNotificationRow).getWidth();
468 doReturn(20).when(mNotificationRow).getActualHeight();
469
470 Answer answer = (Answer) invocation -> {
471 int[] arr = invocation.getArgument(0);
472 arr[0] = 0;
473 arr[1] = 0;
474 return null;
475 };
476 doAnswer(answer).when(mNotificationRow).getLocationOnScreen(any());
477
478 assertTrue("Touch is within the view",
479 mSwipeHelper.isTouchInView(mEvent, mNotificationRow));
480
481 doReturn(50f).when(mEvent).getRawX();
482
483 assertFalse("Touch is not within the view",
484 mSwipeHelper.isTouchInView(mEvent, mNotificationRow));
485 }
486}