1 /* 2 * Copyright (C) 2019 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.globalactions; 18 19 import static junit.framework.Assert.assertEquals; 20 21 import static org.mockito.ArgumentMatchers.any; 22 import static org.mockito.ArgumentMatchers.eq; 23 import static org.mockito.Mockito.doReturn; 24 import static org.mockito.Mockito.spy; 25 26 import android.content.Context; 27 import android.testing.AndroidTestingRunner; 28 import android.util.AttributeSet; 29 import android.view.View; 30 import android.view.ViewGroup; 31 32 import androidx.test.filters.SmallTest; 33 34 import com.android.systemui.MultiListLayout; 35 import com.android.systemui.SysuiTestCase; 36 37 import org.junit.Before; 38 import org.junit.Test; 39 import org.junit.runner.RunWith; 40 41 import java.util.ArrayList; 42 43 /** 44 * Tests for {@link ListGridLayout}. 45 */ 46 @SmallTest 47 @RunWith(AndroidTestingRunner.class) 48 public class GlobalActionsLayoutTest extends SysuiTestCase { 49 50 private TestLayout mLayout; 51 private TestAdapter mAdapter; 52 53 private class TestAdapter extends MultiListLayout.MultiListAdapter { 54 @Override onClickItem(int index)55 public void onClickItem(int index) { } 56 57 @Override onLongClickItem(int index)58 public boolean onLongClickItem(int index) { 59 return true; 60 } 61 62 @Override countSeparatedItems()63 public int countSeparatedItems() { 64 return -1; 65 } 66 67 @Override countListItems()68 public int countListItems() { 69 return -1; 70 } 71 72 @Override shouldBeSeparated(int position)73 public boolean shouldBeSeparated(int position) { 74 return false; 75 } 76 77 @Override getCount()78 public int getCount() { 79 return countSeparatedItems() + countListItems(); 80 } 81 82 @Override getItem(int position)83 public Object getItem(int position) { 84 return null; 85 } 86 87 @Override getItemId(int position)88 public long getItemId(int position) { 89 return -1; 90 } 91 92 @Override getView(int position, View convertView, ViewGroup parent)93 public View getView(int position, View convertView, ViewGroup parent) { 94 return null; 95 } 96 } 97 98 private class TestLayout extends GlobalActionsLayout { 99 ArrayList<View> mSeparatedViews = new ArrayList<>(); 100 ArrayList<View> mListViews = new ArrayList<>(); 101 boolean mSeparatedViewVisible = false; 102 TestLayout(Context context, AttributeSet attrs)103 TestLayout(Context context, AttributeSet attrs) { 104 super(context, attrs); 105 } 106 107 @Override shouldReverseListItems()108 protected boolean shouldReverseListItems() { 109 return false; 110 } 111 112 @Override getAnimationOffsetX()113 public float getAnimationOffsetX() { 114 return 0; 115 } 116 117 @Override getAnimationOffsetY()118 public float getAnimationOffsetY() { 119 return 0; 120 } 121 122 @Override addToListView(View v, boolean reverse)123 protected void addToListView(View v, boolean reverse) { 124 if (reverse) { 125 mListViews.add(0, v); 126 } else { 127 mListViews.add(v); 128 } 129 } 130 131 @Override addToSeparatedView(View v, boolean reverse)132 protected void addToSeparatedView(View v, boolean reverse) { 133 if (reverse) { 134 mSeparatedViews.add(0, v); 135 } else { 136 mSeparatedViews.add(v); 137 } 138 } 139 140 @Override setSeparatedViewVisibility(boolean visible)141 protected void setSeparatedViewVisibility(boolean visible) { 142 mSeparatedViewVisible = visible; 143 } 144 } 145 146 @Before setUp()147 public void setUp() throws Exception { 148 mLayout = spy(new TestLayout(mContext, null)); 149 mAdapter = spy(new TestAdapter()); 150 mLayout.setAdapter(mAdapter); 151 } 152 153 @Test(expected = IllegalStateException.class) testOnUpdateList_noAdapter()154 public void testOnUpdateList_noAdapter() { 155 mLayout.setAdapter(null); 156 mLayout.updateList(); 157 } 158 159 @Test testOnUpdateList_noItems()160 public void testOnUpdateList_noItems() { 161 doReturn(0).when(mAdapter).countSeparatedItems(); 162 doReturn(0).when(mAdapter).countListItems(); 163 mLayout.updateList(); 164 165 assertEquals(0, mLayout.mSeparatedViews.size()); 166 assertEquals(0, mLayout.mListViews.size()); 167 168 assertEquals(false, mLayout.mSeparatedViewVisible); 169 } 170 171 @Test testOnUpdateList_oneSeparatedOneList()172 public void testOnUpdateList_oneSeparatedOneList() { 173 doReturn(1).when(mAdapter).countSeparatedItems(); 174 doReturn(1).when(mAdapter).countListItems(); 175 View view1 = new View(mContext, null); 176 View view2 = new View(mContext, null); 177 178 doReturn(view1).when(mAdapter).getView(eq(0), any(), any()); 179 doReturn(true).when(mAdapter).shouldBeSeparated(0); 180 181 doReturn(view2).when(mAdapter).getView(eq(1), any(), any()); 182 doReturn(false).when(mAdapter).shouldBeSeparated(1); 183 184 mLayout.updateList(); 185 186 assertEquals(1, mLayout.mSeparatedViews.size()); 187 assertEquals(1, mLayout.mListViews.size()); 188 assertEquals(view1, mLayout.mSeparatedViews.get(0)); 189 assertEquals(view2, mLayout.mListViews.get(0)); 190 } 191 192 193 @Test testOnUpdateList_twoSeparatedItems()194 public void testOnUpdateList_twoSeparatedItems() { 195 doReturn(2).when(mAdapter).countSeparatedItems(); 196 doReturn(0).when(mAdapter).countListItems(); 197 View view1 = new View(mContext, null); 198 View view2 = new View(mContext, null); 199 200 doReturn(view1).when(mAdapter).getView(eq(0), any(), any()); 201 doReturn(true).when(mAdapter).shouldBeSeparated(0); 202 doReturn(view2).when(mAdapter).getView(eq(1), any(), any()); 203 doReturn(true).when(mAdapter).shouldBeSeparated(1); 204 205 mLayout.updateList(); 206 207 assertEquals(2, mLayout.mSeparatedViews.size()); 208 assertEquals(0, mLayout.mListViews.size()); 209 210 assertEquals(view1, mLayout.mSeparatedViews.get(0)); 211 assertEquals(view2, mLayout.mSeparatedViews.get(1)); 212 213 // if separated view has items in it, should be made visible 214 assertEquals(true, mLayout.mSeparatedViewVisible); 215 } 216 217 @Test testOnUpdateList_twoSeparatedItems_reverse()218 public void testOnUpdateList_twoSeparatedItems_reverse() { 219 doReturn(2).when(mAdapter).countSeparatedItems(); 220 doReturn(0).when(mAdapter).countListItems(); 221 doReturn(true).when(mLayout).shouldReverseListItems(); 222 View view1 = new View(mContext, null); 223 View view2 = new View(mContext, null); 224 225 doReturn(view1).when(mAdapter).getView(eq(0), any(), any()); 226 doReturn(true).when(mAdapter).shouldBeSeparated(0); 227 228 doReturn(view2).when(mAdapter).getView(eq(1), any(), any()); 229 doReturn(true).when(mAdapter).shouldBeSeparated(1); 230 231 mLayout.updateList(); 232 233 assertEquals(2, mLayout.mSeparatedViews.size()); 234 assertEquals(0, mLayout.mListViews.size()); 235 236 // separated view items are not reversed in current implementation, and this is intentional! 237 assertEquals(view1, mLayout.mSeparatedViews.get(0)); 238 assertEquals(view2, mLayout.mSeparatedViews.get(1)); 239 } 240 241 @Test testOnUpdateList_fourInList()242 public void testOnUpdateList_fourInList() { 243 doReturn(0).when(mAdapter).countSeparatedItems(); 244 doReturn(4).when(mAdapter).countListItems(); 245 View view1 = new View(mContext, null); 246 View view2 = new View(mContext, null); 247 View view3 = new View(mContext, null); 248 View view4 = new View(mContext, null); 249 250 doReturn(view1).when(mAdapter).getView(eq(0), any(), any()); 251 doReturn(false).when(mAdapter).shouldBeSeparated(0); 252 253 doReturn(view2).when(mAdapter).getView(eq(1), any(), any()); 254 doReturn(false).when(mAdapter).shouldBeSeparated(1); 255 256 doReturn(view3).when(mAdapter).getView(eq(2), any(), any()); 257 doReturn(false).when(mAdapter).shouldBeSeparated(2); 258 259 doReturn(view4).when(mAdapter).getView(eq(3), any(), any()); 260 doReturn(false).when(mAdapter).shouldBeSeparated(3); 261 262 mLayout.updateList(); 263 264 assertEquals(0, mLayout.mSeparatedViews.size()); 265 assertEquals(4, mLayout.mListViews.size()); 266 assertEquals(view1, mLayout.mListViews.get(0)); 267 assertEquals(view2, mLayout.mListViews.get(1)); 268 assertEquals(view3, mLayout.mListViews.get(2)); 269 assertEquals(view4, mLayout.mListViews.get(3)); 270 } 271 272 @Test testOnUpdateList_fourInList_reverse()273 public void testOnUpdateList_fourInList_reverse() { 274 doReturn(0).when(mAdapter).countSeparatedItems(); 275 doReturn(4).when(mAdapter).countListItems(); 276 doReturn(true).when(mLayout).shouldReverseListItems(); 277 View view1 = new View(mContext, null); 278 View view2 = new View(mContext, null); 279 View view3 = new View(mContext, null); 280 View view4 = new View(mContext, null); 281 282 doReturn(view1).when(mAdapter).getView(eq(0), any(), any()); 283 doReturn(false).when(mAdapter).shouldBeSeparated(0); 284 285 doReturn(view2).when(mAdapter).getView(eq(1), any(), any()); 286 doReturn(false).when(mAdapter).shouldBeSeparated(1); 287 288 doReturn(view3).when(mAdapter).getView(eq(2), any(), any()); 289 doReturn(false).when(mAdapter).shouldBeSeparated(2); 290 291 doReturn(view4).when(mAdapter).getView(eq(3), any(), any()); 292 doReturn(false).when(mAdapter).shouldBeSeparated(3); 293 294 mLayout.updateList(); 295 296 assertEquals(0, mLayout.mSeparatedViews.size()); 297 assertEquals(4, mLayout.mListViews.size()); 298 assertEquals(view1, mLayout.mListViews.get(3)); 299 assertEquals(view2, mLayout.mListViews.get(2)); 300 assertEquals(view3, mLayout.mListViews.get(1)); 301 assertEquals(view4, mLayout.mListViews.get(0)); 302 } 303 } 304