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