blob: 31054260eb157d654b22fc1e5061a832b6cca9e0 [file] [log] [blame]
Selim Cinek8a9308d2017-08-24 09:31:08 -07001/*
2 * Copyright (C) 2017 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.
Jason Monke59dc402018-08-16 12:05:01 -04006 * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 *
Selim Cinek8a9308d2017-08-24 09:31:08 -07007 * 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
Rohan Shah20790b82018-07-02 17:21:04 -070014package com.android.systemui.statusbar.notification.stack;
Selim Cinek8a9308d2017-08-24 09:31:08 -070015
Gus Prevase2d6f042018-10-17 15:25:30 -040016import static android.provider.Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL;
17
Jason Monke59dc402018-08-16 12:05:01 -040018import static junit.framework.Assert.assertEquals;
19import static junit.framework.Assert.assertNotNull;
Gus Prevas99ba4ba2018-10-01 16:40:23 -040020import static junit.framework.Assert.assertNull;
21
Jason Monk297c04e2018-08-23 17:16:59 -040022import static org.junit.Assert.assertFalse;
23import static org.junit.Assert.assertTrue;
Rohan Shah524cf7b2018-03-15 14:40:02 -070024import static org.mockito.ArgumentMatchers.any;
25import static org.mockito.ArgumentMatchers.anyBoolean;
Jason Monke59dc402018-08-16 12:05:01 -040026import static org.mockito.ArgumentMatchers.anyInt;
Will Brockmane718d582019-01-17 16:38:38 -050027import static org.mockito.ArgumentMatchers.argThat;
Selim Cinekd60ef9e2018-05-16 16:01:05 -070028import static org.mockito.ArgumentMatchers.eq;
Gus Prevase2d6f042018-10-17 15:25:30 -040029import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
Evan Lairdfec77662018-09-18 16:56:50 -040030import static org.mockito.Mockito.atLeastOnce;
Jason Monke59dc402018-08-16 12:05:01 -040031import static org.mockito.Mockito.clearInvocations;
Rohan Shah524cf7b2018-03-15 14:40:02 -070032import static org.mockito.Mockito.doNothing;
Selim Cinek8a9308d2017-08-24 09:31:08 -070033import static org.mockito.Mockito.mock;
Rohan Shah524cf7b2018-03-15 14:40:02 -070034import static org.mockito.Mockito.reset;
35import static org.mockito.Mockito.spy;
Julia Reynolds9cf17562018-03-14 09:49:35 -040036import static org.mockito.Mockito.verify;
Selim Cinek8a9308d2017-08-24 09:31:08 -070037import static org.mockito.Mockito.when;
38
Will Brockmane718d582019-01-17 16:38:38 -050039import android.metrics.LogMaker;
Gus Prevase2d6f042018-10-17 15:25:30 -040040import android.provider.Settings;
Ned Burnsd4a69f72019-06-19 19:49:19 -040041import android.testing.AndroidTestingRunner;
42import android.testing.TestableLooper;
Gus Prevas99ba4ba2018-10-01 16:40:23 -040043import android.view.View;
Selim Cinek8a9308d2017-08-24 09:31:08 -070044
Brett Chabot84151d92019-02-27 15:37:59 -080045import androidx.test.annotation.UiThreadTest;
46import androidx.test.filters.SmallTest;
Brett Chabot84151d92019-02-27 15:37:59 -080047
Will Brockmane718d582019-01-17 16:38:38 -050048import com.android.internal.logging.MetricsLogger;
49import com.android.internal.logging.nano.MetricsProto;
Ned Burns9eb06332019-04-23 16:02:12 -040050import com.android.systemui.ActivityStarterDelegate;
Jason Monk297c04e2018-08-23 17:16:59 -040051import com.android.systemui.Dependency;
Rohan Shah524cf7b2018-03-15 14:40:02 -070052import com.android.systemui.ExpandHelper;
Jason Monk297c04e2018-08-23 17:16:59 -040053import com.android.systemui.InitController;
Julia Reynolds9cf17562018-03-14 09:49:35 -040054import com.android.systemui.R;
Selim Cinek8a9308d2017-08-24 09:31:08 -070055import com.android.systemui.SysuiTestCase;
Dave Mankoff781ef7e2019-06-28 16:33:25 -040056import com.android.systemui.classifier.FalsingManagerFake;
Will Brockmane718d582019-01-17 16:38:38 -050057import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
Beverly8fdb5332019-02-04 14:29:49 -050058import com.android.systemui.plugins.statusbar.StatusBarStateController;
Julia Reynolds9cf17562018-03-14 09:49:35 -040059import com.android.systemui.statusbar.EmptyShadeView;
Jason Monke59dc402018-08-16 12:05:01 -040060import com.android.systemui.statusbar.NotificationPresenter;
Jason Monk297c04e2018-08-23 17:16:59 -040061import com.android.systemui.statusbar.NotificationRemoteInputManager;
62import com.android.systemui.statusbar.NotificationShelf;
63import com.android.systemui.statusbar.RemoteInputController;
64import com.android.systemui.statusbar.StatusBarState;
Selim Cinek5454a0d2019-07-30 17:14:50 -070065import com.android.systemui.statusbar.SysuiStatusBarStateController;
Selim Cinek6f0a62a2019-04-09 18:40:12 -070066import com.android.systemui.statusbar.notification.DynamicPrivacyController;
Jason Monke59dc402018-08-16 12:05:01 -040067import com.android.systemui.statusbar.notification.NotificationEntryManager;
Ned Burnsf81c4c42019-01-07 14:10:43 -050068import com.android.systemui.statusbar.notification.collection.NotificationData;
69import com.android.systemui.statusbar.notification.collection.NotificationEntry;
Jason Monke59dc402018-08-16 12:05:01 -040070import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
Rohan Shah20790b82018-07-02 17:21:04 -070071import com.android.systemui.statusbar.notification.row.FooterView;
72import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
Rohan Shah524cf7b2018-03-15 14:40:02 -070073import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
Selim Cinekc3fec682019-06-06 18:11:07 -070074import com.android.systemui.statusbar.phone.KeyguardBypassController;
Rohan Shah524cf7b2018-03-15 14:40:02 -070075import com.android.systemui.statusbar.phone.NotificationGroupManager;
Lucas Dupinfe218782019-06-11 15:20:32 -070076import com.android.systemui.statusbar.phone.NotificationIconAreaController;
Selim Cinek8a9308d2017-08-24 09:31:08 -070077import com.android.systemui.statusbar.phone.ScrimController;
Jason Monk297c04e2018-08-23 17:16:59 -040078import com.android.systemui.statusbar.phone.ShadeController;
Selim Cinek8a9308d2017-08-24 09:31:08 -070079import com.android.systemui.statusbar.phone.StatusBar;
Jason Monke59dc402018-08-16 12:05:01 -040080import com.android.systemui.statusbar.phone.StatusBarTest.TestableNotificationEntryManager;
Ned Burns2c74c2a2019-06-13 19:06:47 -040081import com.android.systemui.statusbar.policy.ConfigurationController;
Jason Monke59dc402018-08-16 12:05:01 -040082
Gus Prevase2d6f042018-10-17 15:25:30 -040083import org.junit.After;
Selim Cinek8a9308d2017-08-24 09:31:08 -070084import org.junit.Before;
Rohan Shah524cf7b2018-03-15 14:40:02 -070085import org.junit.Rule;
Selim Cinek8a9308d2017-08-24 09:31:08 -070086import org.junit.Test;
87import org.junit.runner.RunWith;
Jason Monke59dc402018-08-16 12:05:01 -040088import org.mockito.ArgumentCaptor;
Will Brockmane718d582019-01-17 16:38:38 -050089import org.mockito.ArgumentMatcher;
Rohan Shah524cf7b2018-03-15 14:40:02 -070090import org.mockito.Mock;
91import org.mockito.junit.MockitoJUnit;
92import org.mockito.junit.MockitoRule;
Selim Cinek8a9308d2017-08-24 09:31:08 -070093
Jason Monk297c04e2018-08-23 17:16:59 -040094import java.util.ArrayList;
95
Rohan Shah524cf7b2018-03-15 14:40:02 -070096/**
97 * Tests for {@link NotificationStackScrollLayout}.
98 */
Selim Cinek8a9308d2017-08-24 09:31:08 -070099@SmallTest
Ned Burnsd4a69f72019-06-19 19:49:19 -0400100@RunWith(AndroidTestingRunner.class)
101@TestableLooper.RunWithLooper
Selim Cinek8a9308d2017-08-24 09:31:08 -0700102public class NotificationStackScrollLayoutTest extends SysuiTestCase {
103
Will Brockmane718d582019-01-17 16:38:38 -0500104 private NotificationStackScrollLayout mStackScroller; // Normally test this
105 private NotificationStackScrollLayout mStackScrollerInternal; // See explanation below
Rohan Shah524cf7b2018-03-15 14:40:02 -0700106
107 @Rule public MockitoRule mockito = MockitoJUnit.rule();
108 @Mock private StatusBar mBar;
Selim Cinek5454a0d2019-07-30 17:14:50 -0700109 @Mock private SysuiStatusBarStateController mBarState;
Rohan Shah524cf7b2018-03-15 14:40:02 -0700110 @Mock private HeadsUpManagerPhone mHeadsUpManager;
111 @Mock private NotificationBlockingHelperManager mBlockingHelperManager;
112 @Mock private NotificationGroupManager mGroupManager;
113 @Mock private ExpandHelper mExpandHelper;
114 @Mock private EmptyShadeView mEmptyShadeView;
Jason Monke59dc402018-08-16 12:05:01 -0400115 @Mock private NotificationData mNotificationData;
116 @Mock private NotificationRemoteInputManager mRemoteInputManager;
117 @Mock private RemoteInputController mRemoteInputController;
Lucas Dupinfe218782019-06-11 15:20:32 -0700118 @Mock private NotificationIconAreaController mNotificationIconAreaController;
Will Brockmane718d582019-01-17 16:38:38 -0500119 @Mock private MetricsLogger mMetricsLogger;
Lucas Dupin00be88f2019-01-03 17:50:52 -0800120 @Mock private NotificationRoundnessManager mNotificationRoundnessManager;
Selim Cinekc3fec682019-06-06 18:11:07 -0700121 @Mock private KeyguardBypassController mKeyguardBypassController;
Jason Monke59dc402018-08-16 12:05:01 -0400122 private TestableNotificationEntryManager mEntryManager;
Gus Prevase2d6f042018-10-17 15:25:30 -0400123 private int mOriginalInterruptionModelSetting;
Selim Cinek8a9308d2017-08-24 09:31:08 -0700124
Will Brockmane718d582019-01-17 16:38:38 -0500125
Selim Cinek8a9308d2017-08-24 09:31:08 -0700126 @Before
127 @UiThreadTest
128 public void setUp() throws Exception {
Ned Burnsd4a69f72019-06-19 19:49:19 -0400129 com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper();
130
Ned Burns9eb06332019-04-23 16:02:12 -0400131 mOriginalInterruptionModelSetting = Settings.Secure.getInt(mContext.getContentResolver(),
132 NOTIFICATION_NEW_INTERRUPTION_MODEL, 0);
133 Settings.Secure.putInt(mContext.getContentResolver(),
134 NOTIFICATION_NEW_INTERRUPTION_MODEL, 1);
135
Rohan Shah524cf7b2018-03-15 14:40:02 -0700136 // Inject dependencies before initializing the layout
137 mDependency.injectTestDependency(
138 NotificationBlockingHelperManager.class,
139 mBlockingHelperManager);
Selim Cinekeec58842019-08-02 09:35:28 -0700140 mDependency.injectTestDependency(SysuiStatusBarStateController.class, mBarState);
Will Brockmane718d582019-01-17 16:38:38 -0500141 mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger);
Jason Monke59dc402018-08-16 12:05:01 -0400142 mDependency.injectTestDependency(NotificationRemoteInputManager.class,
143 mRemoteInputManager);
Jason Monk297c04e2018-08-23 17:16:59 -0400144 mDependency.injectMockDependency(ShadeController.class);
Jason Monke59dc402018-08-16 12:05:01 -0400145 when(mRemoteInputManager.getController()).thenReturn(mRemoteInputController);
146
Gus Prevas92586462019-01-04 16:06:12 -0500147 mEntryManager = new TestableNotificationEntryManager(mContext);
Jason Monk297c04e2018-08-23 17:16:59 -0400148 mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
149 Dependency.get(InitController.class).executePostInitTasks();
Gus Prevas8621bd22018-12-20 15:04:25 -0500150 mEntryManager.setUpForTest(mock(NotificationPresenter.class), null, mHeadsUpManager,
Kevina5ff1fa2018-08-21 16:35:48 -0700151 mNotificationData);
Rohan Shah524cf7b2018-03-15 14:40:02 -0700152
Jason Monk297c04e2018-08-23 17:16:59 -0400153
154 NotificationShelf notificationShelf = mock(NotificationShelf.class);
Will Brockmane718d582019-01-17 16:38:38 -0500155
156 // The actual class under test. You may need to work with this class directly when
157 // testing anonymous class members of mStackScroller, like mMenuEventListener,
158 // which refer to members of NotificationStackScrollLayout. The spy
159 // holds a copy of the CUT's instances of these classes, so they still refer to the CUT's
160 // member variables, not the spy's member variables.
161 mStackScrollerInternal = new NotificationStackScrollLayout(getContext(), null,
Selim Cinek34518f62019-02-28 19:41:18 -0800162 true /* allowLongPress */, mNotificationRoundnessManager,
Ned Burns9eb06332019-04-23 16:02:12 -0400163 mock(DynamicPrivacyController.class),
Ned Burns2c74c2a2019-06-13 19:06:47 -0400164 mock(ConfigurationController.class),
Ned Burns7eeccdd2019-05-15 14:50:11 -0400165 mock(ActivityStarterDelegate.class),
Selim Cinekeec58842019-08-02 09:35:28 -0700166 mock(SysuiStatusBarStateController.class),
Selim Cinekc3fec682019-06-06 18:11:07 -0700167 mHeadsUpManager,
Dave Mankoff781ef7e2019-06-28 16:33:25 -0400168 mKeyguardBypassController,
169 new FalsingManagerFake());
Will Brockmane718d582019-01-17 16:38:38 -0500170 mStackScroller = spy(mStackScrollerInternal);
Rohan Shah524cf7b2018-03-15 14:40:02 -0700171 mStackScroller.setShelf(notificationShelf);
Selim Cinek8a9308d2017-08-24 09:31:08 -0700172 mStackScroller.setStatusBar(mBar);
173 mStackScroller.setScrimController(mock(ScrimController.class));
Rohan Shah524cf7b2018-03-15 14:40:02 -0700174 mStackScroller.setGroupManager(mGroupManager);
175 mStackScroller.setEmptyShadeView(mEmptyShadeView);
Lucas Dupinfe218782019-06-11 15:20:32 -0700176 mStackScroller.setIconAreaController(mNotificationIconAreaController);
Rohan Shah524cf7b2018-03-15 14:40:02 -0700177
178 // Stub out functionality that isn't necessary to test.
179 doNothing().when(mBar)
180 .executeRunnableDismissingKeyguard(any(Runnable.class),
181 any(Runnable.class),
182 anyBoolean(),
183 anyBoolean(),
184 anyBoolean());
185 doNothing().when(mGroupManager).collapseAllGroups();
186 doNothing().when(mExpandHelper).cancelImmediately();
187 doNothing().when(notificationShelf).setAnimationsEnabled(anyBoolean());
Gus Prevase2d6f042018-10-17 15:25:30 -0400188 }
189
190 @After
191 public void tearDown() {
192 Settings.Secure.putInt(mContext.getContentResolver(),
193 NOTIFICATION_NEW_INTERRUPTION_MODEL, mOriginalInterruptionModelSetting);
Selim Cinek8a9308d2017-08-24 09:31:08 -0700194 }
195
196 @Test
197 public void testNotDimmedOnKeyguard() {
Jason Monk1fd3fc32018-08-14 17:20:09 -0400198 when(mBarState.getState()).thenReturn(StatusBarState.SHADE);
Selim Cinek8a9308d2017-08-24 09:31:08 -0700199 mStackScroller.setDimmed(true /* dimmed */, false /* animate */);
200 mStackScroller.setDimmed(true /* dimmed */, true /* animate */);
Jason Monk297c04e2018-08-23 17:16:59 -0400201 assertFalse(mStackScroller.isDimmed());
Selim Cinek8a9308d2017-08-24 09:31:08 -0700202 }
203
Lucas Dupin0cd882f2018-01-30 12:19:49 -0800204 @Test
Julia Reynolds34f14962018-05-03 12:40:20 +0000205 public void updateEmptyView_dndSuppressing() {
206 when(mEmptyShadeView.willBeGone()).thenReturn(true);
207 when(mBar.areNotificationsHidden()).thenReturn(true);
208
209 mStackScroller.updateEmptyShadeView(true);
210
211 verify(mEmptyShadeView).setText(R.string.dnd_suppressing_shade_text);
212 }
213
214 @Test
215 public void updateEmptyView_dndNotSuppressing() {
216 mStackScroller.setEmptyShadeView(mEmptyShadeView);
217 when(mEmptyShadeView.willBeGone()).thenReturn(true);
218 when(mBar.areNotificationsHidden()).thenReturn(false);
219
220 mStackScroller.updateEmptyShadeView(true);
221
222 verify(mEmptyShadeView).setText(R.string.empty_shade_text);
223 }
224
225 @Test
226 public void updateEmptyView_noNotificationsToDndSuppressing() {
227 mStackScroller.setEmptyShadeView(mEmptyShadeView);
228 when(mEmptyShadeView.willBeGone()).thenReturn(true);
229 when(mBar.areNotificationsHidden()).thenReturn(false);
230 mStackScroller.updateEmptyShadeView(true);
231 verify(mEmptyShadeView).setText(R.string.empty_shade_text);
232
233 when(mBar.areNotificationsHidden()).thenReturn(true);
234 mStackScroller.updateEmptyShadeView(true);
235 verify(mEmptyShadeView).setText(R.string.dnd_suppressing_shade_text);
236 }
237
238 @Test
Rohan Shah524cf7b2018-03-15 14:40:02 -0700239 @UiThreadTest
240 public void testSetExpandedHeight_blockingHelperManagerReceivedCallbacks() {
241 mStackScroller.setExpandedHeight(0f);
242 verify(mBlockingHelperManager).setNotificationShadeExpanded(0f);
243 reset(mBlockingHelperManager);
244
245 mStackScroller.setExpandedHeight(100f);
246 verify(mBlockingHelperManager).setNotificationShadeExpanded(100f);
Julia Reynolds9cf17562018-03-14 09:49:35 -0400247 }
Julia Reynoldsed1c9af2018-03-21 15:21:09 -0400248
249 @Test
250 public void manageNotifications_visible() {
251 FooterView view = mock(FooterView.class);
252 mStackScroller.setFooterView(view);
253 when(view.willBeGone()).thenReturn(true);
Julia Reynoldsed1c9af2018-03-21 15:21:09 -0400254
255 mStackScroller.updateFooterView(true, false);
256
Selim Cinekd60ef9e2018-05-16 16:01:05 -0700257 verify(view).setVisible(eq(true), anyBoolean());
258 verify(view).setSecondaryVisible(eq(false), anyBoolean());
Julia Reynoldsed1c9af2018-03-21 15:21:09 -0400259 }
260
261 @Test
262 public void clearAll_visible() {
263 FooterView view = mock(FooterView.class);
264 mStackScroller.setFooterView(view);
265 when(view.willBeGone()).thenReturn(true);
Julia Reynoldsed1c9af2018-03-21 15:21:09 -0400266
267 mStackScroller.updateFooterView(true, true);
268
Selim Cinekd60ef9e2018-05-16 16:01:05 -0700269 verify(view).setVisible(eq(true), anyBoolean());
270 verify(view).setSecondaryVisible(eq(true), anyBoolean());
Julia Reynoldsed1c9af2018-03-21 15:21:09 -0400271 }
Jason Monke59dc402018-08-16 12:05:01 -0400272
273 @Test
274 public void testInflateFooterView() {
275 mStackScroller.inflateFooterView();
276 ArgumentCaptor<FooterView> captor = ArgumentCaptor.forClass(FooterView.class);
277 verify(mStackScroller).setFooterView(captor.capture());
278
279 assertNotNull(captor.getValue().findViewById(R.id.manage_text).hasOnClickListeners());
280 assertNotNull(captor.getValue().findViewById(R.id.dismiss_text).hasOnClickListeners());
281 }
282
283 @Test
284 public void testUpdateFooter_noNotifications() {
285 setBarStateForTest(StatusBarState.SHADE);
286 assertEquals(0, mNotificationData.getActiveNotifications().size());
287
288 mStackScroller.updateFooter();
Jason Monk297c04e2018-08-23 17:16:59 -0400289 verify(mStackScroller, atLeastOnce()).updateFooterView(false, false);
Jason Monke59dc402018-08-16 12:05:01 -0400290 }
291
292 @Test
293 public void testUpdateFooter_remoteInput() {
294 setBarStateForTest(StatusBarState.SHADE);
Ned Burnsf81c4c42019-01-07 14:10:43 -0500295 ArrayList<NotificationEntry> entries = new ArrayList<>();
296 entries.add(mock(NotificationEntry.class));
Jason Monke59dc402018-08-16 12:05:01 -0400297 when(mNotificationData.getActiveNotifications()).thenReturn(entries);
298
299 ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
300 when(row.canViewBeDismissed()).thenReturn(true);
301 when(mStackScroller.getChildCount()).thenReturn(1);
302 when(mStackScroller.getChildAt(anyInt())).thenReturn(row);
303 when(mRemoteInputController.isRemoteInputActive()).thenReturn(true);
304
305 mStackScroller.updateFooter();
306 verify(mStackScroller).updateFooterView(false, true);
307 }
308
309 @Test
310 public void testUpdateFooter_oneClearableNotification() {
311 setBarStateForTest(StatusBarState.SHADE);
Ned Burnsf81c4c42019-01-07 14:10:43 -0500312 ArrayList<NotificationEntry> entries = new ArrayList<>();
313 entries.add(mock(NotificationEntry.class));
Jason Monke59dc402018-08-16 12:05:01 -0400314 when(mNotificationData.getActiveNotifications()).thenReturn(entries);
315
316 ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
317 when(row.canViewBeDismissed()).thenReturn(true);
318 when(mStackScroller.getChildCount()).thenReturn(1);
319 when(mStackScroller.getChildAt(anyInt())).thenReturn(row);
320
321 mStackScroller.updateFooter();
322 verify(mStackScroller).updateFooterView(true, true);
323 }
324
325 @Test
326 public void testUpdateFooter_oneNonClearableNotification() {
327 setBarStateForTest(StatusBarState.SHADE);
Ned Burnsf81c4c42019-01-07 14:10:43 -0500328 ArrayList<NotificationEntry> entries = new ArrayList<>();
329 entries.add(mock(NotificationEntry.class));
Jason Monk297c04e2018-08-23 17:16:59 -0400330 when(mEntryManager.getNotificationData().getActiveNotifications()).thenReturn(entries);
331 assertTrue(mEntryManager.getNotificationData().getActiveNotifications().size() != 0);
Jason Monke59dc402018-08-16 12:05:01 -0400332
333 mStackScroller.updateFooter();
334 verify(mStackScroller).updateFooterView(true, false);
335 }
336
337 @Test
338 public void testUpdateFooter_atEnd() {
339 // add footer
340 mStackScroller.inflateFooterView();
341
342 // add notification
343 ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
Ned Burnsf81c4c42019-01-07 14:10:43 -0500344 NotificationEntry entry = mock(NotificationEntry.class);
Evan Laird94492852018-10-25 13:43:01 -0400345 when(row.getEntry()).thenReturn(entry);
346 when(entry.isClearable()).thenReturn(true);
Jason Monke59dc402018-08-16 12:05:01 -0400347 mStackScroller.addContainerView(row);
348
349 mStackScroller.onUpdateRowStates();
350
351 // move footer to end
352 verify(mStackScroller).changeViewPosition(any(FooterView.class), eq(-1 /* end */));
353 }
354
355 @Test
356 public void testOnDensityOrFontScaleChanged_reInflatesFooterViews() {
357 clearInvocations(mStackScroller);
358 mStackScroller.onDensityOrFontScaleChanged();
359 verify(mStackScroller).setFooterView(any());
360 verify(mStackScroller).setEmptyShadeView(any());
361 }
362
Gus Prevas99ba4ba2018-10-01 16:40:23 -0400363 @Test
364 @UiThreadTest
365 public void testSetIsBeingDraggedResetsExposedMenu() {
366 NotificationSwipeHelper swipeActionHelper =
367 (NotificationSwipeHelper) mStackScroller.getSwipeActionHelper();
368 swipeActionHelper.setExposedMenuView(new View(mContext));
369 mStackScroller.setIsBeingDragged(true);
370 assertNull(swipeActionHelper.getExposedMenuView());
371 }
372
373 @Test
374 @UiThreadTest
375 public void testPanelTrackingStartResetsExposedMenu() {
376 NotificationSwipeHelper swipeActionHelper =
377 (NotificationSwipeHelper) mStackScroller.getSwipeActionHelper();
378 swipeActionHelper.setExposedMenuView(new View(mContext));
379 mStackScroller.onPanelTrackingStarted();
380 assertNull(swipeActionHelper.getExposedMenuView());
381 }
382
383 @Test
384 @UiThreadTest
385 public void testDarkModeResetsExposedMenu() {
386 NotificationSwipeHelper swipeActionHelper =
387 (NotificationSwipeHelper) mStackScroller.getSwipeActionHelper();
388 swipeActionHelper.setExposedMenuView(new View(mContext));
Selim Cinek195dfc52019-05-30 19:35:05 -0700389 mStackScroller.setHideAmount(0.1f, 0.1f);
Gus Prevas99ba4ba2018-10-01 16:40:23 -0400390 assertNull(swipeActionHelper.getExposedMenuView());
391 }
392
Will Brockmane718d582019-01-17 16:38:38 -0500393 class LogMatcher implements ArgumentMatcher<LogMaker> {
394 private int mCategory, mType;
395
396 LogMatcher(int category, int type) {
397 mCategory = category;
398 mType = type;
399 }
400 public boolean matches(LogMaker l) {
401 return (l.getCategory() == mCategory)
402 && (l.getType() == mType);
403 }
404
405 public String toString() {
406 return String.format("LogMaker(%d, %d)", mCategory, mType);
407 }
408 }
409
410 private LogMaker logMatcher(int category, int type) {
411 return argThat(new LogMatcher(category, type));
412 }
413
414 @Test
415 @UiThreadTest
416 public void testOnMenuClickedLogging() {
417 // Set up the object under test to have a valid mLongPressListener. We're testing an
418 // anonymous-class member, mMenuEventListener, so we need to modify the state of the
419 // class itself, not the Mockito spy copied from it. See notes in setup.
420 mStackScrollerInternal.setLongPressListener(
421 mock(ExpandableNotificationRow.LongPressListener.class));
422
423 ExpandableNotificationRow row = mock(ExpandableNotificationRow.class, RETURNS_DEEP_STUBS);
424 when(row.getStatusBarNotification().getLogMaker()).thenReturn(new LogMaker(
425 MetricsProto.MetricsEvent.VIEW_UNKNOWN));
426
427 mStackScroller.mMenuEventListener.onMenuClicked(row, 0, 0, mock(
428 NotificationMenuRowPlugin.MenuItem.class));
429 verify(row.getStatusBarNotification()).getLogMaker(); // This writes most of the log data
430 verify(mMetricsLogger).write(logMatcher(MetricsProto.MetricsEvent.ACTION_TOUCH_GEAR,
431 MetricsProto.MetricsEvent.TYPE_ACTION));
432 }
433
434 @Test
435 @UiThreadTest
Selim Cinekc3fec682019-06-06 18:11:07 -0700436 public void testOnMenuShownLogging() { ;
Will Brockmane718d582019-01-17 16:38:38 -0500437
438 ExpandableNotificationRow row = mock(ExpandableNotificationRow.class, RETURNS_DEEP_STUBS);
439 when(row.getStatusBarNotification().getLogMaker()).thenReturn(new LogMaker(
440 MetricsProto.MetricsEvent.VIEW_UNKNOWN));
441
442 mStackScroller.mMenuEventListener.onMenuShown(row);
443 verify(row.getStatusBarNotification()).getLogMaker(); // This writes most of the log data
444 verify(mMetricsLogger).write(logMatcher(MetricsProto.MetricsEvent.ACTION_REVEAL_GEAR,
445 MetricsProto.MetricsEvent.TYPE_ACTION));
446 }
447
Jason Monke59dc402018-08-16 12:05:01 -0400448 private void setBarStateForTest(int state) {
Jason Monk297c04e2018-08-23 17:16:59 -0400449 // Can't inject this through the listener or we end up on the actual implementation
450 // rather than the mock because the spy just coppied the anonymous inner /shruggie.
451 mStackScroller.setStatusBarState(state);
Jason Monke59dc402018-08-16 12:05:01 -0400452 }
Selim Cinek8a9308d2017-08-24 09:31:08 -0700453}